-
Обычно в IB Или ORACLE для этой цели я юзал генераторы. Генератор - вещь понятная. По сути это глобальная переменная вне контекста транзакции.
В MSSQL для этой цели предлагается юзать тип поля IDENTITY. А после вставки проверять значение глобальной переменной @@IDENTITY, которая хранит значение "последнего" значения присвоенного полю IDENTITY в данной сессии.
Казалось бы, какие тут могут быть грабли? Все было великолепно, пока я не замучился отлаживать одно место, где у меня все время возникала ошибка нарушения ссылочной целостности.
Вот, что я делал в хранимой процедуре:
1. Вставляю запись в главную таблицу. 2. Сохраняю @@IDENTITY во временной переменной 3. В цикле пытаюсь вставить записи в подчиненную, используя сохраненное значение IDENTITY в локальной переменной.
На самом же деле происходило следующее. По условиям техзадания мне нужно было зачем-то в триггере той самой главной таблицы сделать инсерт еще в одну таблицу. И этот триггер делал этот инсерт. И вот он-то и портил "последнее значение" глобальной переменной @@IDENTITY, так как в той таблице тоже есть полде типа IDENTITY.
Вот такой вот интересный маразм получается. Если кто-то повесит триггер на таблицу, который вставит что-то в другую таблицу, то закончиться это может потерей правильного значения @@IDENTITY . Причем откуда его тогда брать, уже неизвестно. Похоже нужно воспользоваться запросом по альтернативному ключу к вставленной записи. Но тогда лучше вообще не юзать эту глобальную переменную @@IDENTITY. Или строго-настрого запретить себе и всем остальным что-либо вставлять из триггеров куда-либо. Даже в таблицу логов, если кто-то захочет. А то вдруг какая-то процедура юзает этот @@IDENTITY и он будет запорчен?
Вот так вот.
Готов выслушать битье ногами по полной программе. Просто 10 минут смотрел как ошалелый на то, как "сразу после вставки" в тексте процедуры @@IDENTITY меняет свое значение до неузнаваемости. Пока сообразил, что происходит.
-
> Вот, что я делал в хранимой процедуре: т.е. ничего? тут одни слова, в процедуре это не более чем коментарии.
> Причем откуда его тогда брать, уже неизвестно. известно. в справке написано, если пройти по ссылкам из @@IDENTITY. но ты опять просился делать "по аналогиям" не читая как оно на самом деле...
> Но тогда лучше вообще не юзать эту глобальную переменную @@IDENTITY. это как ложка, в обед ее очень полезно юзать, во время секса она практически бесполезна и лучше ее не юзать, а у Нео ее вообще нет...
-
> просился бросился
-
> а у Нео ее вообще нет...
Это как? Он что, палочками пользуется? :)
-
sniknik © (08.09.08 01:31) [1] > Вот, что я делал в хранимой процедуре: т.е. ничего? тут одни слова, в процедуре это не более чем коментарии.
Я думал, что хотя бы здесь я с людьми беседую, а не с SQL-сервером. :)
-
> kaif © (08.09.08 00:49)
SCOPE_IDENTITY
Электронная документация по MSSQL Server 2005
"...Допуская, что столбец идентификаторов имеется в обеих таблицах, T1 и T2, функции @@IDENTITY и SCOPE_IDENTITY вернут разные значения в конце инструкции INSERT в таблице T1. Функция @@IDENTITY возвращает значение столбца идентификаторов, добавленное в текущем сеансе последним во всех областях. Это значение, вставленное в таблицу T2. Функция SCOPE_IDENTITY() возвратит значение IDENTITY, вставленное в таблицу T1. Это было последним добавлением, произошедшим в заданной области. Функция SCOPE_IDENTITY() вернет значение NULL, если функция была вызвана до того, как какая-либо инструкция INSERT была выполнена для столбца идентификаторов в этой области..."
-
> kaif (08.09.2008 0:49:00) [0]
Читаешь BOL по теме @@IDENTITY и смотришь See ALso по двум другим фунциям из данного раздела, затем выбираешь нужную.
-
на 2005 вообще есть ретурн параметры после инсерта/апдейта. но это скорее для "на клиенте"
-
> Это как? Он что, палочками пользуется? внутривенно.
|