2009-04-08 12 views
5

Sagen wir, ich habe eine gespeicherte Prozedur mit diesem in seinem Körper:T-SQL EXEC und Umfang

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

Ist IDENT_CURRENT() garantiert die Identität dieser Zeile in der EXEC eingefügt zu bekommen? IDENT_CURRENT() "gibt den letzten Identitätswert zurück, der für eine bestimmte Tabelle in jeder Sitzung und jedem Bereich generiert wurde", aber der Bereich ist innerhalb der EXEC anders als die gespeicherte Prozedur, richtig?

Ich möchte sicherstellen, dass, wenn die gespeicherte Prozedur mehrere Male auf einmal aufgerufen wird, die richtige Identität ausgewählt wird.

EDIT: Oder muss ich sowohl die INSERT tun und in der EXEC SELECT, etwa so:

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

Und wenn das der Fall ist, Wie wähle ich das Ergebnis der EXEC, wenn ich will weiter mit mehr Code in T-SQL? Wie dies (obwohl es offensichtlich nicht korrekt ist):

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 

UPDATE: Gleich im ersten Schnipsel, wenn ich SELECT SCOPE_IDENTITY() anstelle von IDENT_CURRENT() NULL wird durch die SELECT zurückgegeben. :(

Antwort

6

Versuchen

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

oder besser, nach this

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

Dringend empfehlen Sie die zweite zu verwenden. @@ Identität sollte fast nie verwendet werden, da sie oft keine korrekten Ergebnisse liefert. Kudos zum Erkennen, dass die Bereichsidentität in der exec-Anweisung enthalten sein muss. – HLGEM

1

denke ich SCOPE_IDENTITY() ist das, was Sie suchen, die Ihnen die neuesten identifizieren der aktuelle Bereich

4

Laut Microsoft-T-SQL-Dokumentation:

IDENT_CURRENT ist ähnlich der SQL Server 2000 Identität Funktionen SCOPE_IDENTITY und @ IDENTITY. Alle drei Funktionen geben die zuletzt erzeugten Identitätswerte zurück. der Umfang und Sitzungs, auf das jedoch zuletzt definierten in jedem dieser Funktionen unterscheiden:

IDENT_CURRENT gibt den letzten Identitätswert für eine bestimmte Tabelle in jeder Sitzung und jeden Umfang erzeugt.

@@ IDENTITY gibt die letzte Identität Wert für alle Tabelle in der aktuellen Sitzung über alle Bereiche zurückgegeben.

SCOPE_IDENTITY gibt den letzten Identitätswert für jede Tabelle erzeugt in der aktuellen Sitzung und der aktuellen Umfang.

Also ich würde sagen, nein, IDENT_CURRENT tut nicht Garantie Sie geben den richtigen Wert zurück. Es könnte der letzte IDENTITY-Wert sein, der in einer anderen Sitzung eingefügt wurde.

Ich würde sicherstellen, stattdessen SCOPE_IDENTITY verwenden - das sollte zuverlässig funktionieren.

Marc

2

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

Es ist ein Fehler in SCOPE_IDENTITY() Ich habe meine gespeicherten Prozeduren über die Methodik geschaltet verwendet, um die Standardwerte von einem Einsatz abrufen:

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; 
0

Ich möchte meine Lieblingslösung mithilfe des Schlüsselworts OUTPUT einbetten. Da INSERT mehrere Zeilen gleichzeitig unterstützen kann, möchten wir die eingefügten Identitäten wissen. Hier gehts:


-- 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 

Gehen Sie voran, um das mehrmals zu laufen, um zu fühlen, wie es funktioniert.