Как вы скажете, какой будет следующая колонка идентификации? - PullRequest
7 голосов
/ 18 февраля 2009

Есть ли запрос tsql, чтобы узнать, какое значение столбца идентификаторов SQL-сервера предполагается использовать для вставки следующей строки?

Отредактировано, чтобы добавить:

Я удалил и заново создал таблицу с

[personID] [int] IDENTITY(1,1) NOT NULL

как часть моей команды CREATE TABLE. Я также попытался повторно заполнить столбцы идентификаторов, удалив всю информацию в этой таблице, и это не всегда работало. Это заставило меня задуматься, есть ли способ узнать, что SQL ожидает использовать для вашего следующего номера столбца идентификаторов.

Ответы [ 6 ]

15 голосов
/ 18 февраля 2009

Возможно, вы захотите использовать SCOPE_IDENTITY, а не @@ IDENTITY, чтобы ограничить его значением идентификатора в текущей области. Это позволяет избежать получения новых значений идентификаторов, вставленных триггерами в другие таблицы, а не в таблицу, в которую вы только что вставили.

Но вы можете вычислить, каково следующее значение идентичности

SELECT IDENT_CURRENT('mytable') + IDENT_INCR('mytable') FROM mytable

Проблема в том, что вам не гарантировано, что это значение. Вы должны иметь блокировку, чтобы другие таблицы не запускались при запуске таблицы, чтобы обеспечить точное значение. Кроме того, после того, как у вас закончились 32-битные целые числа, я не знаю, какова логика. Я не знаю, перевернулся ли он или нет.

Edit: Я только что проверил это (см. Ниже для SQL), и он не возвращает правильное значение, когда нет данных. И повторное заполнение с помощью DBCC CHECKIDENT ('tablename', RESEED, 200) фактически привело к следующему значению 201, а не 200.

CREATE TABLE willtest (myid integer IDENTITY(1,1), myvalue varchar(255))

SELECT IDENT_CURRENT('willtest') + IDENT_INCR('willtest')

INSERT INTO willtest (myvalue)
VALUES ('1')
INSERT INTO willtest (myvalue)
VALUES ('2')
INSERT INTO willtest (myvalue)
VALUES ('3')
INSERT INTO willtest (myvalue)
VALUES ('4')
INSERT INTO willtest (myvalue)
VALUES ('5')
INSERT INTO willtest (myvalue)
VALUES ('6')
INSERT INTO willtest (myvalue)
VALUES ('7')
INSERT INTO willtest (myvalue)
VALUES ('8')

SELECT IDENT_CURRENT('willtest') + IDENT_INCR('willtest')

DBCC CHECKIDENT ('willtest', RESEED, 200)

SELECT IDENT_CURRENT('willtest') + IDENT_INCR('willtest')

INSERT INTO willtest (myvalue)
VALUES ('200')
INSERT INTO willtest (myvalue)
VALUES ('201')
INSERT INTO willtest (myvalue)
VALUES ('202')
INSERT INTO willtest (myvalue)
VALUES ('203')
INSERT INTO willtest (myvalue)
VALUES ('204')
INSERT INTO willtest (myvalue)
VALUES ('205')
INSERT INTO willtest (myvalue)
VALUES ('206')
INSERT INTO willtest (myvalue)
VALUES ('207')

SELECT IDENT_CURRENT('willtest') + IDENT_INCR('willtest')

SELECT * FROM willtest

DROP TABLE willtest
10 голосов
/ 18 февраля 2009

Нет, гарантированный способ не существует (хотя вы, безусловно, можете узнать, каким может быть следующее значение , другая команда может пойти и использовать его, прежде чем вы сможете использование этого). Единственное гарантированное значение, которое вы можете получить - это ранее вставленное значение идентификатора через SCOPE_IDENTITY() (которое вернет значение идентификатора, которое было сгенерировано последним для текущей области).

Сомнительно, с какой целью нужно знать это значение раньше (при использовании автоматически увеличенного столбца с идентификатором).

Если вам нужно узнать значение раньше, тогда я рекомендую генерировать идентификаторы самостоятельно. Вы можете сделать это с помощью таблицы идентификаторов, связанной с именем таблицы, или, если у вас есть проблемы с масштабируемостью (и вы используете транзакции), вы можете создать таблицу идентификаторов для каждой таблицы, для которой требуется идентификатор, в который должен быть вставлен идентификатор ( и впоследствии увеличивается).

Или вы можете использовать GUID, и вы сможете легко сгенерировать их на стороне клиента перед отправкой в ​​вашу базу данных.

4 голосов
/ 19 февраля 2009

Этот фрагмент sql даст вам следующее значение столбца идентификаторов (возможно, есть много причин не повторять этот фрагмент в рабочем коде)

declare @nextid int;
declare @previousid int;

begin tran

 insert into dbo.TestTable (Col1) values ('11');
 select @nextid = SCOPE_IDENTITY(); 

rollback tran

 select @previousid = @nextid -1
 DBCC CHECKIDENT('dbo.TestTable', RESEED, @previousid);
 select @nextid

этот вопрос о переполнении стека дает некоторую дополнительную информацию - sql-identity-autonumber-is-увеличивается-даже-с-транзакцией-откат

0 голосов
/ 09 октября 2013
SELECT IDENT_CURRENT('mytable') + IDENT_INCR('mytable') FROM mytable
0 голосов
/ 18 февраля 2009

Используйте GUID столбцы для ваших первичных ключей. Если у вас нет миллиардов записей и тысяч запросов в секунду, вы, вероятно, не заметите разницу в производительности. Но если вам не нравится тратить слишком много времени на такие глупые проблемы, вы заметите разницу в уровне стресса и продолжительности жизни.

0 голосов
/ 18 февраля 2009

Так как вы начинаете с 1 и увеличиваете на 1 (IDENTITY (1,1)), мне интересно, можете ли вы создать процедуру, в которой вы можете установить переменную типа «Select @@ IDENTITY + 1» или что-то подобное .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...