Получение следующего идентификатора без вставки строки - PullRequest
13 голосов
/ 09 октября 2009

Возможно ли в SQL (SQL Server) получить следующий идентификатор (целое число) из столбца идентификаторов в таблице до и без фактической вставки строки? Это не обязательно самый высокий идентификатор плюс 1, если самая последняя строка была удалена.

Я спрашиваю об этом, потому что иногда нам приходится обновлять действующую БД новыми строками. Идентификатор строки используется в нашем коде (например, Switch (ID) {Case ID:} и должен совпадать. Если наша БД разработки и живая БД не синхронизированы, было бы неплохо заранее предсказать идентификатор строки). до развертывания.

Я мог бы, конечно, УСТАНОВИТЬ ИДЕНТИЧНОСТЬ ВЫКЛ. УСТАНОВИТЬ INSERT_IDENTITY ON или запустить транзакцию (откатывает ли ID обратно?) И т. Д., Но задавался вопросом, была ли функция, которая возвращала следующий идентификатор (без его увеличения) .

Ответы [ 5 ]

11 голосов
/ 09 октября 2009

Edit:

Потратив несколько часов на сравнение целых дампов страниц, я понял, что есть более простой способ, и мне следует остаться на DMV.

Значение сохраняется при резервном копировании / восстановлении, что является четким признаком того, что оно сохранено - я сбросил все страницы в БД и не смог найти расположение / изменение для того времени запись была добавлена. Сравнение 200-строчных дампов страниц не очень интересно.

Я использовал выделенную консоль администратора, я делал дамп каждой отдельной внутренней таблицы, вставлял строку, а затем еще один дамп системных таблиц. Оба дампа были идентичны, что указывает на то, что, хотя оно сохранилось и, следовательно, должно храниться, оно не подвергается воздействию даже на этом уровне.

Итак, пройдя по кругу, я понял, что у DMV был ответ.

create table foo (MyID int identity not null, MyField char(10))
insert into foo values ('test')
go 10

-- Inserted 10 rows
select Convert(varchar(8),increment_value) as IncrementValue,
   Convert(varchar(8),last_value) as LastValue
from sys.identity_columns where name ='myid'


-- insert another row
insert into foo values ('test')

-- check the values again
select Convert(varchar(8),increment_value) as IncrementValue,
   Convert(varchar(8),last_value) as LastValue
from sys.identity_columns where name ='myid'

-- delete the rows
delete from foo


-- check the DMV again
select Convert(varchar(8),increment_value) as IncrementValue,
   Convert(varchar(8),last_value) as LastValue
from sys.identity_columns where name ='myid'

-- value is currently 11 and increment is 1, so the next insert gets 12
insert into foo values ('test')
select * from foo

Result:
MyID        MyField
----------- ----------
12          test      

(1 row(s) affected)

Только потому, что строки были удалены, последнее значение не было сброшено, поэтому последнее значение + приращение должно быть правильным ответом.

Также напишу эпизод в моем блоге.

Да, и кратчайший путь ко всему этому:

select ident_current('foo') + ident_incr('foo')

Так что на самом деле все получается просто - но все это предполагает, что никто другой не использовал ваш идентификатор, пока вы его вернули. Хорошо для расследования, но я не хотел бы использовать это в коде.

11 голосов
/ 09 октября 2009

try IDENT_CURRENT :

Select IDENT_CURRENT('yourtablename')

Это работает, даже если вы не вставили ни одной строки в текущем сеансе:

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

3 голосов
/ 09 октября 2009

Это немного странно, но это будет работать:

Если вы хотите узнать следующее значение, начните с получения наибольшего значения плюс один:

SELECT max(id) FROM yourtable

Чтобы это работало, вам нужно сбросить личность при вставке:

DECLARE @value INTEGER

SELECT @value = max(id) + 1 FROM yourtable

DBCC CHECKIDENT (yourtable, reseed, @value)

INSERT INTO yourtable ...

Не совсем элегантное решение, но я еще не выпил кофе; -)

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

3 голосов
/ 09 октября 2009

Вместо использования столбца IDENTITY вы можете использовать столбец UNIQUEIDENTIFIER (Guid) в качестве уникального идентификатора строки и вставить известные значения.

Другой вариант (который я использую) - это SET IDENTITY_INSERT ON, где идентификаторы строк управляются в отдельном «документе», управляемом источником.

1 голос
/ 09 октября 2009

Вы можете довольно легко определить, что последнее использованное значение :

SELECT
    last_value
FROM 
    sys.identity_columns
WHERE
    object_id = OBJECT_ID('yourtablename')

Обычно следующим идентификатором будет last_value + 1 - но для этого нет гарантии.

Марк

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