-- OK
insert into testtable ([Value]) values ('12345')
begin tran
-- String or binary data would be truncated. The statement has been terminated.
insert into testtable ([Value]) values ('123456789')
rollback
-- OK
insert into testtable ([Value]) values ('12345')
В результате имеем дыру:
select * from testtable
ID Value
1 12345
3 12345
При чем неважно был ли средний insert-запрос выполнен в транзакции или нет.
Кто может объяснить такое странное поведение?
Failed statements and transactions can change the current identity for a table and create gaps in the identity column values. The identity value is never rolled back even though the transaction that tried to insert the value into the table is not committed.
Здравствуйте, Muxa, Вы писали:
M>забавно. M>это считается нормальным поведением? M>есть ли способ не увеличивать @@IDENTITY в случае фэйла или роллбэка?
Абсолютно нормальное. Сами подумайте, как еще может работать IDENTITY при наличии нескольких паралельных вставляющих транзакций?
M>это считается нормальным поведением?
Абсолютно.
M>есть ли способ не увеличивать @@IDENTITY в случае фэйла или роллбэка?
Использовать самописные триггеры или запрос на выборку первого отсутствующего ID. Serializable-транзакции и аццкие тормоза в подарок!
Если серьёзно — поле с Identity надо рассматривать исключительно как служебное и не пытаться организовать с его помощью последовательную нумерацию. Намекну: что вы будете делать с последовательной нумерацией после удаления записи?
Re[3]: [MSSQL] Дыры с таблице
От:
Аноним
Дата:
13.12.10 10:00
Оценка:
Здравствуйте, Muxa, Вы писали:
M>забавно. M>это считается нормальным поведением?
А чем это не нормально? IDENTITY — это генерация уникального ключа, а не генерация непрерывных последовательностей.
M>есть ли способ не увеличивать @@IDENTITY в случае фэйла или роллбэка?
В принципе, возможность есть:
Убрать IDENTITY из основной таблицы, а каждый раз перед вставкой заливать данные во временную таблицу (со своим IDENTITY), а потом из неё уже — в основную, прибавляя к ключу последнее значение IDENTITY из основной таблицы.
Кроме того, что это через не то место, тут ещё можно огрести проблемы с concurrency. Но, с другой стороны, странное требование — странное решение
S>Если серьёзно — поле с Identity надо рассматривать исключительно как служебное и не пытаться организовать с его помощью последовательную нумерацию.
я не пытался получить последовательную нумерацию, я думал она у меня уже есть
хотя завязки на нее не было.
S>Намекну: что вы будете делать с последовательной нумерацией после удаления записи?
ну, тут без вариантов.
хотя из этой таблицы записи не удаляются.
L>Абсолютно нормальное. Сами подумайте, как еще может работать IDENTITY при наличии нескольких паралельных вставляющих транзакций?
а разве в этом случае не будет блокировки страницы или таблицы целиком?
Здравствуйте, Muxa, Вы писали:
L>>Абсолютно нормальное. Сами подумайте, как еще может работать IDENTITY при наличии нескольких паралельных вставляющих транзакций? M>а разве в этом случае не будет блокировки страницы или таблицы целиком?
А>В принципе, возможность есть: А>Убрать IDENTITY из основной таблицы, а каждый раз перед вставкой заливать данные во временную таблицу (со своим IDENTITY), а потом из неё уже — в основную, прибавляя к ключу последнее значение IDENTITY из основной таблицы.
А заодно проделать этот фокус и со всеми ссылающимися таблицами
Здравствуйте, avpavlov, Вы писали:
А>>Убрать IDENTITY из основной таблицы, а каждый раз перед вставкой заливать данные во временную таблицу (со своим IDENTITY), а потом из неё уже — в основную, прибавляя к ключу последнее значение IDENTITY из основной таблицы.
A>А заодно проделать этот фокус и со всеми ссылающимися таблицами
Не совсем понятно, что имеется в виду. Причем тут ссылающиеся таблицы?