T-SQL EXEC и область применения - PullRequest
5 голосов
/ 09 апреля 2009

Допустим, у меня есть хранимая процедура с этим в его теле:

EXEC 'INSERT INTO ' + quotename(@table) ' blah...'
SELECT IDENT_CURRENT('' + @table + '')

Гарантируется ли IDENT_CURRENT () получение идентификатора этой строки, вставленной в EXEC? IDENT_CURRENT () «возвращает последнее значение идентификатора, сгенерированное для конкретной таблицы в любом сеансе и любой области», но область внутри EXEC отличается от хранимой процедуры, верно?

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

РЕДАКТИРОВАТЬ: Или мне нужно сделать INSERT и SELECT в EXEC, например, так:

declare @insert nvarchar
set @insert = 
    'INSERT INTO ' + quotename(@table) ' blah...' +
    'SELECT IDENT_CURRENT(''' + @table + ''')'
EXEC @insert

И если это так, как ВЫБРАТЬ результат EXEC, если я хочу продолжить с большим количеством кода в T-SQL? Вот так (хотя это явно не правильно):

declare @insert nvarchar
set @insert = 
    'INSERT INTO ' + quotename(@table) ' blah...' +
    'SELECT IDENT_CURRENT(''' + @table + ''')'

declare @ident int
set @ident = EXEC @insert

-- more code
SELECT * FROM blah

ОБНОВЛЕНИЕ: В самом первом фрагменте, если я ВЫБИРАЮ SCOPE_IDENTITY () вместо использования IDENT_CURRENT (), NULL возвращается SELECT. (

Ответы [ 5 ]

6 голосов
/ 09 апреля 2009

Попробуйте

EXEC 'INSERT INTO ' + quotename(@table) ' blah...; SELECT @@IDENTITY'

или лучше, согласно это

EXEC 'INSERT INTO ' + quotename(@table) ' blah...; SELECT SCOPE_IDENTITY()'
4 голосов
/ 09 апреля 2009

Согласно документам Microsoft T-SQL:

IDENT_CURRENT похож на SQL Идентификационные функции Server 2000 SCOPE_IDENTITY и @@ IDENTITY. Все три функции возвращают последний сгенерированный ценности личности. Тем не менее, сфера и сеанс, на котором определяется последний в каждой из этих функций различаются:

IDENT_CURRENT возвращает последний значение идентичности, сгенерированное для конкретная таблица в любой сессии и любой Объем.

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

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

Так что я бы сказал, нет, IDENT_CURRENT не гарантирует, что вернет вам правильное значение. Это может быть последнее значение IDENTITY, вставленное в другой сеанс.

Я бы использовал вместо этого SCOPE_IDENTITY - это должно работать надежно.

Марк

2 голосов
/ 09 апреля 2009

http://blog.sqlauthority.com/2009/03/24/sql-server-2008-scope_identity-bug-with-multi-processor-parallel-plan-and-solution/

Ошибка в SCOPE_IDENTITY () Я переключил свои хранимые процедуры на методологию, используемую для извлечения значений по умолчанию из вставки:

 declare @TheNewIds table (Id bigint, Guid uniqueidentifier)
 insert [dbo].[TestTable] output inserted.Id, inserted.Guid into @TheNewIds
 values (default);
 select @Id = [Id], @Guid = [Guid] from @TheNewIds;
1 голос
/ 09 апреля 2009

Я думаю, что Scope_Identity () - это то, что вы ищете, что даст вам самую последнюю идентификацию в текущей области.

0 голосов
/ 21 апреля 2009

Я бы хотел добавить свое любимое решение, используя ключевое слово OUTPUT. Поскольку INSERT может поддерживать несколько строк одновременно, мы бы хотели знать вставленные идентификаторы. Здесь идет:

 
-- source table
if object_id('Source') is not null drop table Source
create table Source
(
    Value datetime
)
-- populate source
insert Source select getdate()
waitfor delay '00:00.1'
insert Source select getdate()
waitfor delay '00:00.1'
insert Source select getdate()
select * from Source -- test
-- destination table
if object_id('Destination') is null
create table Destination
(
    Id int identity(1, 1),
    Value datetime
)
-- tracking table to keep all generated Id by insertion of table Destination
if object_id('tempdb..#Track') is null
create table #Track 
(
    Id int  
)
else delete #Track
-- copy source into destination, track the Id using OUTPUT
insert Destination output inserted.Id into #Track select Value from Source
select Id from #Track -- list out all generated Ids

Попробуйте запустить это несколько раз, чтобы почувствовать, как это работает.

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