Załóżmy, że mamy taką tabelę T, która ma pola:
ID - int, identyfikator nadawany automatycznie przy dodawaniu rekordów
A - varchar
B - varchar
Wartości A i B mogą się powtarzać, a ID jest niepowtarzalny i nadawany automatycznie (kolejne numery):
Załóżmy, że chcemy, żeby w polu B był identyfikator (nie ważne, czemu to ma służyć, chodzi o przykład), mam taki pomysł:
-- Dodanie wpisu ze znakiem charakterystycznym, identyfikator rekordu nie jest znany
insert into T (A, B)
values ('qwe', '<->')
-- Zdefiniowanie zmiennej do przechowania identyfikatora
define @I varchar
-- Znalezienie numeru ID wpisu ze znakiem charakterystycznym
select @I = ID from T where B = '<->'
-- Zamiana znaku charakterystycznego na identyfikator ze zmiennej @I
update table t set B = @I where B = '<->'
-- W tym miejscu mamy uzupełnione pole B, w którym jest identyfikator rekordu
Gdyby założyć, że w danej chwili tylko jeden klient wykonuje transakcję, to nie byłoby żadnego błędu.
Natomiast w przypadku wykonania ten procedury przez dwóch klientów naraz będzie błąd w poniższej sytuacji przy założeniu, że serwer wykonuje polecenia w dwóch wątkach:
A: insert into T (A, B)
values ('qwe', '<->')
B: insert into T (A, B)
values ('asd', '<->')
-- W tym miejscu w tabeli T są dwa wiersze zawierające znak charakterystyczny zamiast identyfikatora
-- Poniższe instrukcje nie będą wykonane u obu klientów, bo "select" zwróci dwa rekordy zamiast jednego
A: define @I varchar
A: select @I = ID from T where B = '<->'
B: define @I varchar
B: select @I = ID from T where B = '<->'
-- Nastąpi zmiana znaku zarówno dla rekordu z polem A o wartości 'qwe', jak i 'asd'
A: update table t set B = @I where B = '<->'
-- Poniższa instrukcja nie zostanie wykonana z powodu braku znaku charakterystycznego w tabeli
B: update table t set B = @I where B = '<->'
Czy rzeczywiście może dojść do błędu, czy serwer SQL przeczeka, aż jedna procedura będzie wykonana do końca, a potem uruchomi drugą i wtedy obie transakcje zostaną wykonane bezbłędnie (zgodnie z założeniami)?