Пишу Web Service, с MS SQL Serverom вообще не работал
Вот наткнулся на такую вещь, есть табличка, мне нужно в нее вставить строку и получить идентификатор (уникальное поле)
под которым она вставилась, чтобы в последующих функциях работать с это строкой. Посоветуйте, как это лусше сделать?
Здравствуйте .smoke, Вы писали:
S>Я прошу меня извенить, здесь клнечнл уже много раз это обсуждали, но просмотрев треды у меня все-таки остался вопрос S>Если я сделаю вот так
S>
S>INSERT INTO .... VALUES (....) SELECT @@IDENTITY;
S>
S>Возможна ли такая ситуация, что между INSERT и SELECT кто-нибудь другой втисниться и успеет сделать INSERT?
Здравствуйте Lloyd, Вы писали:
L>Здравствуйте .smoke, Вы писали:
[]
L>Нет. (с)
Это почему? Наоборот! Да'с!
Аргументирую. Если сервер работает в режиме автоматических транзакций, то
MSDN: individual Transact-SQL statement is committed automatically if it is successful and rolled back automatically if it generates an error.
В таком случае между insert'ом и последующим select'ом может проскочить другая транзакция. Результат будет не верный. Для предотвращения этого необходимо непосредственно указать принадлежность двух инструкций одной транзакции.
При чем, если тупо написать
begin tran
insert into dmd values(1291,4575)
select @@IDENTITY
commit
то это не особо поможет. Так как после insert пользователю (по умолчанию) запрещается только читать данные. Необходимо явно указать вид блокировки.
begin tran
insert into dmd with (tablock)values(1291,4575)
select @@IDENTITY
commit
Здравствуйте Алекс, Вы писали:
А>individual Transact-SQL statement is committed automatically if it is successful and rolled back automatically if it generates an error.
А>В таком случае между insert'ом и последующим select'ом может проскочить другая транзакция. Результат будет не верный. Для предотвращения этого необходимо непосредственно указать принадлежность двух инструкций одной транзакции.
Другая транзакция конечно может влезть, но на @@IDENTITY это не повлияет никак, посему все извращения с транзакциями и блокировками можно опустить ибо @@IDENTITY возвращает последнее значение столбца с IDENTITY в пределах текущей сессии.
Единственный вариант когда @@IDENTITY может вернуть неверное значение это если на таблице висит триггер на INSERT, который тоже что-то, кому-то, куда-то вставляет, в этом случае @@IDENTITY возвращает значение этого что-то, где-то, кем-то, но опять же строго в пределах текущей сессии.
Но так у них на хитрую задницу есть свой хрен с винтом, то у нас на их хрен с винтом есть своя ж@па с лабиринтом, в виде SCOPE_IDENTITY() который кладет афигенский болт на все триггеры на свете..
@@IDENTITY and SCOPE_IDENTITY will return the last identity value generated in any table
in the current session. However, SCOPE_IDENTITY returns the value only within the current
scope
A scope is a module -- a stored procedure, trigger, function, or batch. Thus, two
statements are in the same scope if they are in the same stored procedure, function, or
batch.
Здравствуйте Merle, Вы писали:
M>Здравствуйте Алекс, Вы писали:
А>>individual Transact-SQL statement is committed automatically if it is successful and rolled back automatically if it generates an error.
А>>В таком случае между insert'ом и последующим select'ом может проскочить другая транзакция. Результат будет не верный. Для предотвращения этого необходимо непосредственно указать принадлежность двух инструкций одной транзакции.
M> M>Другая транзакция конечно может влезть, но на @@IDENTITY это не повлияет никак, посему все извращения с транзакциями и блокировками можно опустить ибо @@IDENTITY возвращает последнее значение столбца с IDENTITY в пределах текущей сессии.
[]
Ну забыл, и че! Зачем нулями-то разбрасываться! И же исправился (потом), к тому же этих нулей у меня и так много.
Если обощить, то нужно всегда думать о подобных вещах. Представть вместо SELECT @@IDENTITY выплнялся бы другой запрос из другой таблы, которая бы была связана с нашей. Могли бы возникнуть проблемы.
И сам FAQ уже назрел и этот вопрос чуть ли не на первое место в этом FAQ'е....
А>Ну забыл, и че! Зачем нулями-то разбрасываться! И же исправился (потом), к тому же этих нулей у меня и так много.
Ну, тем более, нулем больше — нулем меньше...
Вот уж девять баллов, ты точно не за что получил, так что это я чтобы справедливость хоть отчасти восторжествовала...
А>Если обощить, то нужно всегда думать о подобных вещах. Представть вместо SELECT @@IDENTITY выплнялся бы другой запрос из другой таблы, которая бы была связана с нашей. Могли бы возникнуть проблемы.
Ага, давай тогда вообще сделаем одну большую SERIALIZABLE транзакцию и всю работу с базой в эту транзакцию запихнем, точно никаких проблемм не будет.
А думать вообще никогда не вредно...
А>И сам FAQ уже назрел и этот вопрос чуть ли не на первое место в этом FAQ'е....
А>Про @@IDENTITY? Лучше бы про блокировки написал!
Да запросто... К тому же Sinclair это давно сделал, очень все доходчиво объяснил, насколько я помню.