6

我有点不明白为什么我似乎无法通过下面的语句获得插入行的“新身份”。SCOPE_IDENTITY()只返回空值。

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) 

任何帮助将不胜感激。

现在我使用这样的解决方法。

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
4

2 回答 2

4

2013 年 2 月编辑

@MartinSmith 提醒我们,微软不想修复这个错误。

“Microsoft 于 2013 年 2 月 27 日下午 2:18 发布 您好 Martin,我们调查了这个问题,发现改变行为并不是一件容易的事。基本上需要在 INSERT 和 OUTPUT 时重新定义一些行为INTO 目标具有标识列。鉴于问题的性质和不常见的情况,我们决定不解决该问题。-- Umachandar,SQL 可编程性团队“

2012 年 10 月编辑

这是由一个错误引起的:

测试错误:

引用 OUTPUT 子句文档

@@IDENTITY、SCOPE_IDENTITY 和 IDENT_CURRENT 返回仅由嵌套 DML 语句生成的标识值,而不是由外部 INSERT 语句生成的标识值。

经过测试,似乎 scope_identity() 仅在外部操作是在具有标识列的表中插入时才有效:

测试 1:删除

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 

测试 2:以身份插入外部表

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 

测试 3:在没有身份的情况下插入外部表

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 
于 2012-10-02T21:22:37.260 回答
3

您可能会尝试为您的output子句使用表变量,从而允许您显式插入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) 
于 2012-10-02T22:04:10.443 回答