2012-10-02 23 views
6

Estoy un poco atrapado con por qué parece que no puedo obtener la 'nueva identidad' de la fila insertada con la siguiente declaración. SCOPE_IDENTITY() simplemente devuelve nulo.Cláusula de SALIDA de SQL Server

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) 

Cualquier ayuda sería muy apreciada.

Por ahora uso una solución como esta.

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 

Respuesta

3

Usted puede tratar de utilizar una variable de tabla para su cláusula output, lo que le permite insertar de forma explícita en 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

Hice exactamente eso al final, aplausos – Terry

3

EDITADO FEB'2013

@MartinSmith nos alerta de que este error don't want be fixed by Microsoft.

"Publicado por Microsoft el 02/27/2013 a las 2:18 PM ¡Hola Martin, nos investigó el tema y encontraron que el cambio de la conducta no es una cosa fácil de hacer . Básicamente se requeriría alguna redefinición . del comportamiento cuando ambos INSERT & SALIDA eN objetivo tiene columnas de identidad Dada la naturaleza del problema & el escenario poco común, tenemos decidieron no para solucionar el problema -. Umachandar, capacidad de programación SQL equipo"

editado OCT'2012

Esto se debe a un error:

Prueba de fallos:

Quoting OUTPUT Clause doc:

@@ IDENTITY, SCOPE_IDENTITY, y el retorno IDENT_CURRENT valores de identidad generados solo por la declaración DML anidada, y no aquellos generados por la instrucción INSERT externa.

Después de la prueba que Parece que SCOPE_IDENTITY() sólo funciona si la operación externa es una inserción en una tabla con columnas de identidad:

Prueba 1: Eliminar

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 

Prueba 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 

Prueba 3: Inserción en la mesa exterior sin identidad

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 - La razón por la que 'OPCIÓN (MAXDOP 1)' no funciona es porque el informe de errores que ha encontrado en Connect no es el mismo que este. [He creado uno nuevo aquí] (https://connect.microsoft.com/SQLServer/feedback/details/765809/odd-behavior-of-scope-identity-with-insert-into) –

+0

Este elemento de conexión se acaba de actualizar para indicar que el error no se solucionará ... –

+0

@MartinSmith, puesto actualizado, gracias! – danihp

Cuestiones relacionadas