2012-10-02 16 views
6

Trochę utknąłem z powodu, dlaczego nie mogę uzyskać "nowej tożsamości" wstawionego wiersza z poniższym stwierdzeniem. SCOPE_IDENTITY() właśnie zwraca wartość null.SQL Server OUTPUT klauzula

declare @WorkRequestQueueID int 
declare @LastException nvarchar(MAX) 
set @WorkRequestQueueID = 1 
set @LastException = 'test' 

set nocount off 

DELETE dbo.WorkRequestQueue 
OUTPUT 
     DELETED.MessageEnvelope, 
     DELETED.Attempts, 
     @LastException, 
     GetUtcdate(), -- WorkItemPoisened datetime 
     DELETED.WorkItemReceived_UTC 
    INTO dbo.FaildMessages 
FROM dbo.WorkRequestQueue 
WHERE 
    WorkRequestQueue.ID = @WorkRequestQueueID 

IF @@ROWCOUNT = 0 
    RAISERROR ('Record not found', 16, 1) 

SELECT Cast(SCOPE_IDENTITY() as int) 

Każda pomoc będzie najbardziej ceniona.

Na razie używam obejścia takiego jak to.

declare  @WorkRequestQueueID int 
declare @LastException nvarchar(MAX) 
set @WorkRequestQueueID = 7 
set @LastException = 'test' 

set nocount on 
set xact_abort on 

DECLARE @Failed TABLE 
(
    MessageEnvelope xml, 
    Attempts smallint, 
    LastException nvarchar(max), 
    WorkItemPoisened_UTC datetime, 
    WorkItemReceived_UTC datetime 
) 

BEGIN TRAN 

DELETE dbo.WorkRequestQueue 
OUTPUT 
    DELETED.MessageEnvelope, 
    DELETED.Attempts, 
    @LastException, 
    GetUtcdate(), -- WorkItemPoisened datetime 
    DELETED.WorkItemReceived_UTC 

INTO 
    @Failed 
FROM 
    dbo.WorkRequestQueue 
WHERE 
    WorkRequestQueue.ID = @WorkRequestQueueID 

IF @@ROWCOUNT = 0 BEGIN 
    RAISERROR ('Record not found', 16, 1) 
    Rollback 
END ELSE BEGIN 
    insert into dbo.FaildMessages select * from @Failed 
    COMMIT TRAN 
    SELECT Cast(SCOPE_IDENTITY() as int) 
END 

Odpowiedz

3

Można spróbować użyć zmiennej tabeli dla klauzuli output, umożliwiając w ten sposób wyraźnie wstawić do FaildMessages:

declare  @WorkRequestQueueID int 
declare @LastException nvarchar(MAX) 
set @WorkRequestQueueID = 1 
set @LastException = 'test' 

set nocount off 

    -- Declare a table variable to capture output 
    DECLARE @output TABLE (
     MessageEnvelope VARCHAR(50), -- Guessing at datatypes 
     Attempts INT,     -- Guessing at datatypes 
     WorkItemReceived_UTC DATETIME -- Guessing at datatypes 
    ) 

    -- Run the deletion with output 
    DELETE dbo.WorkRequestQueue 
    OUTPUT 
     DELETED.MessageEnvelope, 
     DELETED.Attempts, 
     DELETED.WorkItemReceived_UTC 
    -- Use the table var 
    INTO @output 
    FROM dbo.WorkRequestQueue 
    WHERE 
     WorkRequestQueue.ID = @WorkRequestQueueID 

    -- Explicitly insert 
    INSERT 
    INTO dbo.FaildMessages 
    SELECT 
     MessageEnvelope, 
     Attempts, 
     @LastException, 
     GetUtcdate(), -- WorkItemPoisened datetime 
     WorkItemReceived_UTC 
    FROM @output 


IF @@ROWCOUNT = 0 
    RAISERROR ('Record not found', 16, 1) 


SELECT Cast(SCOPE_IDENTITY() as int) 
+0

Zrobiłem dokładnie to w końcu, okrzyki – Terry

3

EDYCJI FEB'2013

@MartinSmith ostrzega nas, że ten błąd don't want be fixed by Microsoft.

„Wysłany przez Microsoft w dniu 2/27/2013 2:18 PM Witaj Martin, My zbadać sprawę i stwierdziła, że ​​zmiana zachowania nie jest łatwa rzecz do zrobienia. To w zasadzie wymagają przedefiniowania niektórych . zachowania gdy zarówno INSERT INTO & WYJŚCIE docelowy kolumny tożsamości Biorąc pod uwagę charakter problemu & niecodziennym scenariusz, mamy postanowił nie rozwiązać problem. - Umachandar SQL Programmability Team”

EDITED OCT'2012

Jest to spowodowane błędem:

Testing bug:

Quoting OUTPUT Clause doc:

@@ IDENTITY, SCOPE_IDENTITY i powrót IDENT_CURRENT wartości tożsamości generowane tylko przez zagnieżdżone oświadczenie DML, a nie wygenerowane przez Zewnętrzna instrukcja INSERT.

Po teście to Wydaje się, że SCOPE_IDENTITY() działa tylko wtedy, gdy operacja zewnętrzna jest wkładka w tabeli z kolumnami tożsamości:

Test 1: Usuń

create table #t (a char(1)); 
create table #d (a char(1), i int identity); 

insert into #t 
values ('a'),('b'),('c'); 

delete #t 
output deleted.a into #d; 

select SCOPE_IDENTITY(), * from #d; 

    a i 
---- - - 
null a 1 
null b 2 
null c 3 

testowy 2: Inserting in outer table with identity

create table #t (a char(1), i int identity); 
create table #d (a char(1), i int identity); 

insert into #t 
values ('x'),('x'),('x'); 

insert into #t 
output inserted.a into #d 
values ('a'),('b'); 

select scope_identity(), * from #d; 

    a i 
- - - 
2 a 1 
2 b 2 

Test 3: Wstawianie w tabeli zewnętrznej bez tożsamości

create table #t (a char(1)); 
create table #d (a char(1), i int identity); 

insert into #t 
values ('x'),('x'),('x'); 

insert into #t 
output inserted.a into #d 
values ('a'),('b'); 

select scope_identity(), * from #d; 


    a i 
---- - - 
null a 1 
null b 2 
+5

@danihp - Dlatego, że 'OPCJA (MAXDOP 1)' nie działa ponieważ raport o błędach znaleziony w Connect nie jest tym samym. [Stworzyłem tutaj nowy] (https://connect.microsoft.com/SQLServer/feedback/details/765809/odd-behavior-of-scope-identity-with-insert-into) –

+0

Ten element połączenia został właśnie zaktualizowany, aby powiedzieć, że błąd nie zostanie naprawiony ... –

+0

@MartinSmith, po aktualizacji, dzięki! – danihp