2011-08-29 2 views
0

Код как этотИспользование @@ IDENTITY или SCOPE_IDENTITY() + Insert, а в хранимых процедурах

INSERT INTO TABLE (VAL1,VAL2,VAL3) VALUES (X,Y,Z) 

    GetLastInsertID @tablename='TABLE' 

GetLastInsertID это хранимая процедура:

SELECT @@IDENTITY AS LastID FROM TABLE 

Как получить хранимую процедуру вернуть «LastID» в соответствии с запросом в выписке Select @@ IDENTITY выше?

я получаю следующее сообщение об ошибке:

Incorrect syntax near 'GetLastInsertId'. 

... но это хорошо работает, когда выполняется сама по себе:

GetLastInsertID @tablename='TABLE' 

Хорошо, спасибо я обновил его scope_identity(). Но вы говорите, что не ставите его в другой SP, чтобы поместить его в тот же SP, что и Insert?

Опять же, я до сих пор я получаю сообщение об ошибке, когда я объединить вставку с этим:

SELECT SCOPE_IDENTITY() AS LastID FROM TABLE 

Вот новое сообщение об ошибке:

There is already an object named 'TABLE' in the database. 
+4

Используя [SCOPE_IDENTITY()] (http://msdn.microsoft.com/en-us/library/ms190315.aspx) предпочтительнее вместо '@@ IDENTITY'. –

+0

@Joe: см. [Ответ Джоэля] (http://stackoverflow.com/questions/7236141/using-identity-insert-together-in-stored-procedures/7236192#7236192), SCOPE_IDENTITY не будет работать, процедура является другой сферой. –

+0

См. [Кризис идентичности] (http://msdn.microsoft.com/en-us/library/aa224821 (SQL.80) .aspx), почему @@ IDentity является плохим. Его старая статья, но название легко запомнить –

ответ

5

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

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

+0

Не уверен, что вы имеете в виду «Если один пользователь в сеансе вставляет много строк вместе, вы можете получить неправильный результат». AFAIK единственная проблема - триггеры (и ошибка с параллелизмом, которая применяется как к @@ IDENTITY, так и к SCOPE_IDENTITY) –

+0

@Martin - см. Эту страницу [msdn] (http://msdn.microsoft.com/en-us /library/ms190315.aspx) - 'SCOPE_IDENTITY и @@ IDENTITY возвращают последние идентификационные значения, которые генерируются в любой таблице текущего сеанса. Однако SCOPE_IDENTITY возвращает значения, вставленные только в пределах текущей области; @@ IDENTITY не ограничивается конкретной областью. «Таким образом, у @ @ identity может возникнуть проблема, если у вас есть несколько вставок в одном сеансе, даже если область отличается. Триггеры - это самый распространенный пример. –

+1

@ Мартин - уверен. Хранимые процедуры (то есть: этот вопрос);) –

2

Прежде всего, вы никогда не захотите использовать идентификатор @@, поскольку он может сломаться, если кто-то добавит триггер.

Что вы хотите использовать, это предложение OUTPUT или scope_identity. См. «Книги онлайн» для примеров использования OUTPUT.

-1

Вот мой пример кода, который делает это. (. Но ХП не добавляет никакого значения)

--First create a test table. 
    create table test 
    (id int identity, 
    name varchar(30)) 
    go 

--A stored proc that returns the scope_identity() 
    create proc dbo.spTest 
    as 

    insert into test(name) 
    values ('test') 

    return scope_identity() 

    go 


-- Sample call 
    declare @newId int 

    exec @newId = spTest 

    print @newId 
+0

SP выглядит так же, но он все еще дает ошибку при сохранении/изменении SP: Msg 2714 В базе данных уже имеется объект с именем «spTest». –

+0

Смешение 'return' in - очень плохая идея, хранимые процедуры никогда не должны использовать' return' (было нормально использовать его для кодов ошибок до SQL 2005, но теперь вы можете использовать RAISERROR и вместо этого бросать). Используйте параметр OUTPUT. –

+1

, если у вас уже есть sp с именем spTest, вы измените «create proc» на «alter proc». – JBrooks

0

ваша ошибка в вашей неспособности включить команду EXECUTE, попробуйте следующее:

INSERT INTO TABLE (VAL1,VAL2,VAL3) VALUES (X,Y,Z) 

EXEC GetLastInsertID @tablename='TABLE' 

EXEC предполагается при попытке выполните процедуру без каких-либо других команд, однако, когда вы включаете INSERT, она требует EXEC.

Теперь вам действительно нужно определить, является ли то, что вы пытаетесь сделать, это хороший дизайн.

попробовать это:

DECLARE @LastId int 
INSERT INTO TABLE (VAL1,VAL2,VAL3) VALUES (X,Y,Z) 
SELECT @LastID=SCOPE_IDENTITY() 
+0

ваш второй пример вызывает ошибку в примере выше. –

Смежные вопросы