Я знаю, что это не тот ответ, вы, кажется, хотят услышать, но ответ заключается в использовании SCOPE_IDENTITY()
. Проблема, о которой вы думаете (где это будет для любой стол), поэтому мы используем SCOPE_IDENTITY()
вместо @@IDENTITY
. Рассмотрим случай, когда у вас есть таблица с столбцом IDENTITY
и триггер вставки в ту таблицу, которая сама вставляет в таблицу с столбцом IDENTITY
.
CREATE TABLE dbo.Log(LogID INT IDENTITY(100,1), FooID INT);
CREATE TABLE dbo.Foo(FooID INT IDENTITY(1,1), name VARCHAR(32));
GO
CREATE TRIGGER dbo.Foo_Insert
ON dbo.Foo
FOR INSERT
AS
BEGIN
SET NOCOUNT ON;
INSERT dbo.Log(FooID) SELECT FooID FROM inserted;
END
GO
Теперь ваша ситуация в том, что вы хотите надежный способ получить идентификатор после вставки. SCOPE_IDENTITY()
дает, что, так как он ограничен ваша сфера, в то время как @@IDENTITY
не ограничивается вашей сферы (то есть он будет захватить последний IDENTITY
выдал, что произошло в рамках Триггеры, а не ваши возможности:
INSERT dbo.Foo(name) SELECT 'Bob';
SELECT
@@IDENTITY,
SCOPE_IDENTITY();
Результаты:.
---- ----
100 1
Обратите внимание, что ни SCOPE_IDENTITY()
, ни @@IDENTITY
следует использовать в том случае, когда вы вставить несколько строк способ сделать это было бы использовать предложение OUTPUT
. Во-первых, давайте уронить на курок:
DROP TRIGGER dbo.Foo_Insert;
Теперь давайте проверим вставку нескольких строк:
INSERT dbo.Foo(name)
OUTPUT inserted.FooID, inserted.name
SELECT 'Frank' UNION ALL SELECT 'Jim';
Результаты:
FooID name
----- -----
2 Frank
3 Jim
Если у вас есть условные вставки, нет никакой разницы. Ведение таблицы у нас есть, давайте попробуем этот код дважды:
DECLARE @table SYSNAME;
SET @table = N'Log';
IF @table = N'Log'
BEGIN
INSERT dbo.Log(FooID) SELECT 10;
END
IF @table = N'Foo'
BEGIN
INSERT dbo.Foo(name) SELECT 'Tom';
END
SELECT SCOPE_IDENTITY();
Результат:
----
101
Давайте попробуем снова N'Foo'
:
DECLARE @table SYSNAME;
SET @table = N'Foo';
IF @table = N'Log'
BEGIN
INSERT dbo.Log(FooID) SELECT 10;
END
IF @table = N'Foo'
BEGIN
INSERT dbo.Foo(name) SELECT 'Tom';
END
SELECT SCOPE_IDENTITY();
Результаты:
----
4
Если это более сложно, чем это (например,Вы можете вставить в более чем одной таблицы), вы можете сделать что-то вроде:
IF <some conditional>
BEGIN
INSERT dbo.sometable ...
SET @somevar = SCOPE_IDENTITY();
END
IF <some other conditional>
BEGIN
INSERT dbo.some_other_table ...
SET @some_other_var = SCOPE_IDENTITY();
END
я не уверен, почему вы думаете, что не работает, и я не знаю, почему я должен пойти на это чтобы убедить вас, что это так. Опять же, если вы покажете пример, где это не работает (или что «ЛЮБАЯ таблица», по вашему мнению, может мешать), мы могли бы прокомментировать. В его нынешнем виде это звучит так, как будто ваше мнение о SCOPE_IDENTITY()
основано на том, что вы слышали о @@IDENTITY
. Эти предположения довольно легко доказать или опровергнуть.
Как ни в стороне, IDENT_CURRENT
не следует упоминать в этом разговоре. Нельзя использовать для одновременной работы вообще, и вы должны притворяться, что никогда не слышали об этом, насколько мне известно. Вы также должны учитывать то же самое для @@IDENTITY
- я не могу думать о допустимом использовании для него, если вы действительно не хотите захватывать из-за триггера IDENTITY
, сгенерированный внутри триггера.
В какой ситуации SCOPE_IDENTITY() не работает? Можете ли вы продемонстрировать пример? IDENT_CURRENT - это не способ сделать это. –
Что именно нужно ID? Не могли бы вы немного разобраться в архитектуре, с которой работаете? Вы пытаетесь захватить значение идентификатора, вставленное в таблицу, отличную от той, на которую ссылается ваш запрос? –
Как я уже сказал, SCOPE_IDENTITY возвращает личность последней записи, вставленной для ЛЮБОЙ таблицы .................... – user577240