Когда я импортирую данные в новую таблицу из большого Excel, если одна запись не удалась, то ничего не импортируется. Я думаю, что это нормально, потому что это соответствует правилу атомарности. Однако, когда я исправил ошибку исходных данных и снова импортировал, столбец идентификаторов не начинается с 1, а начинается с большого значения.
Например
create table #test (id int identity(1,1), name varchar(4) default '')
insert into #test (name) values('1 insert will failed');
select ident_current('#test') as ident_current
insert into #test (name) values('2 insert will failed');
select ident_current('#test') as ident_current
insert into #test (name) values('3 OK');
select ident_current('#test') as ident_current
select * from #test
drop table #test
Результат
id name
----------- ----
3 3 OK
Википедия описывает ACID следующим образом.
атомарность
Атомарность требует, чтобы каждая транзакция была «все или ничего»: если одна часть транзакции завершается сбоем, вся транзакция завершается с ошибкой, а состояние базы данных остается неизменным. Атомарная система должна гарантировать атомарность в любой ситуации, включая сбои питания, ошибки и сбои.
Итак, похоже, что SQL Server не оставляет состояние базы данных (значение идентификатора) неизменным, если вставка не удалась, так что нарушает ли это правило ACID?
Кстати, PostgreSQL не позволяет увеличивать значение идентификатора (серийного номера) при сбое вставки. (Обновление: только иногда, см. комментарии. НЕ полагайтесь на это.).
test=# create table AutoIncrementTest (id serial not null, name varchar(4));
NOTICE: CREATE TABLE will create implicit sequence "autoincrementtest_id_seq" for serial column "autoincrementtest.id"
CREATE TABLE
test=# insert into autoincrementtest(name) values('12345');
ERROR: value too long for type character varying(4)
test=# insert into autoincrementtest(name) values('12345');
ERROR: value too long for type character varying(4)
test=# insert into autoincrementtest(name) values('1234');
INSERT 0 1
test=# select * from autoincrementtest;
id | name
----+------
1 | 1234
ALTER TABLE AutoIncrementTest ADD CONSTRAINT UQ_Name UNIQUE (name); insert into autoincrementtest(name) values('123'); insert into autoincrementtest(name) values('123'); insert into autoincrementtest(name) values('1233');
, дает следующий результат:id=2,name=123; id=4,name=1233
- person LiuYan 刘研   schedule 19.07.2012SEQUENCE
, если вам нужны последовательности без пробелов в PostgreSQL, потому что некоторые сбои возникают только во время фиксации (например, сбои сериализации). Вы должны использовать обычную таблицу с одной строкой, где выSELECT ... FOR UPDATE
илиUPDATE ... RETURNING
значение. Это заблокирует выполнение других транзакций после этой точки до тех пор, пока транзакция с блокировкой не зафиксирует или не откатится, поэтому убедитесь, что транзакции, основанные на беспрерывных последовательностях, действительно короткие. Если возможно, исправьте свой дизайн, чтобы он не нуждался в бесконечных последовательностях. - person Craig Ringer   schedule 20.07.2012