代码之家  ›  专栏  ›  技术社区  ›  jinsungy

SQL Server 2008 SCOPE\u IDENTITY()出现问题

  •  2
  • jinsungy  · 技术社区  · 14 年前

    我的代码不更新线程字段。它是空的。有人有什么想法吗?

    INSERT INTO [Messages]([Sender], [Receiver], [Job_Number], [Subject], [MessageText], [DateSent])
    VALUES(@Sender, @Receiver, @Job_Number, @Subject, @MessageText, @DateSent)
    
    SET @ThreadID = SCOPE_IDENTITY()
    
    UPDATE [Messages] 
    SET Thread = @ThreadID
    WHERE MessageID = @ThreadID
    

    似乎根本没有执行更新例程。我甚至在存储过程的末尾添加了以下代码,但没有更新任何内容。

    UPDATE Comments 
    SET SomeField = @ThreadID
    where SCID = 33
    

    /****** Object:  Table [dbo].[Messages]    Script Date: 04/09/2010 12:08:55 ******/
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    SET ANSI_PADDING ON
    GO
    
    CREATE TABLE [dbo].[Messages](
        [MessageID] [int] IDENTITY(1,1) NOT NULL,
        [Sender] [varchar](30) NOT NULL,
        [Receiver] [varchar](30) NOT NULL,
        [Job_Number] [varchar](20) NULL,
        [Subject] [varchar](200) NULL,
        [MessageText] [varchar](max) NULL,
        [DateSent] [datetime] NULL,
        [Thread] [int] NULL,
     CONSTRAINT [PK_Messages] PRIMARY KEY CLUSTERED 
    (
        [MessageID] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    
    GO
    
    SET ANSI_PADDING OFF
    GO
    
    ALTER TABLE [dbo].[Messages] ADD  CONSTRAINT [DF_Messages_DateSent]  DEFAULT (getdate()) FOR [DateSent]
    GO
    

    编辑: 当我从managementstudio执行存储过程时,更新工作正常。当我使用SQLHelper调用我的应用程序时,问题就出现了:

    SqlHelper.ExecuteNonQuery(ConfigurationManager.ConnectionStrings["Conn"].ConnectionString,
                "spMessagesInsert",
                0,
                message.Sender, 
                message.Receiver,
                message.Job_Number,
                message.Subject,
                message.MessageText,
                message.DateSent
                );
    

    最后,我修改了程序代码,使用linqtosql调用存储过程,而不是使用SqlHelper。这似乎解决了问题。

    4 回复  |  直到 14 年前
        1
  •  2
  •   Thomas    14 年前

    “当你消除了不可能,

    如果我们假设没有错误,那么只有少数几种可能性:

    1. 未插入或删除该值。我们可以通过在 Set @ThreadId = SCOPE_IDENTITY()
    2. @@TRANCOUNT Update语句前后。
    3. @@ROWCOUNT 就在Update语句之后。如果它为零,那么唯一的可能性就是记录不再存在。如果它是1,那么很明显更新起作用了。在Update语句之后,您应该能够调用 Select * From Messages Where MessageId = @ThreadId And Thread Is Not Null 去拿张唱片。这意味着,如果代码后面的部分再次为Null,则是其他内容更改了它。

    Set NoCount Off
    
    INSERT INTO [Messages]([Sender], [Receiver], [Job_Number], [Subject], [MessageText], [DateSent])
    
    VALUES(@Sender, @Receiver, @Job_Number, @Subject, @MessageText, @DateSent)
    
    SET @ThreadID = SCOPE_IDENTITY()
    
    -- ensure that the value is not null
    Select @ThreadId
    
    -- we should get our record from this query
    Select * From Messages Where MessageId = @ThreadId
    
    UPDATE [Messages] 
    SET Thread = @ThreadID
    WHERE MessageID = @ThreadID
    
    -- we should get 1
    Select @@ROWCOUNT
    
    -- we should get a value
    Select * From Messages Where MessageId = @ThreadId And Thread Is Not Null
    
    -- are we in a transaction?
    Select @@TRANCOUNT
    

    编辑 另一个非常有用的工具是sqlserverprofiler,它可以解决这些问题。例如,你可以告诉它显示 Rollback Tran completed Commit Tran completed 事件以及其他SQL语句,并查看是否有什么东西正在回滚事务。

        2
  •  4
  •   gbn    14 年前

    identity/parallelism bug reported on MS Connect now a KB article too 在SQLServer2005和2008上。

    OPTION (MAXDOP 1) 按条款建议插入

        3
  •  0
  •   Amy B    14 年前

    检查消息表中的触发器。


    SET @ThreadID = SCOPE_IDENTITY() 
    
    PRINT convert(varchar(30), @ThreadID)
    
    UPDATE [Messages]  
    SET Thread = @ThreadID 
    WHERE MessageID = @ThreadID 
    

    它印的是你想要的吗?

        4
  •  -1
  •   Joe L.    14 年前

    我以前也见过同样的问题。解决方案是在存储过程代码的顶部启用NOCOUNT(假设它不会对您造成任何不必要的副作用):

    或者,您可以从SQLHelper为您使用的连接设置nocount。

    我不知道为什么会这样做,除了nocount关闭时(即行被计数),它似乎“混淆”了下面的update语句(如果我得到更多细节,我稍后会更新我的答案)。与您所描述的相同的事情发生了…下面的UPDATE语句从未执行,而且存储过程意外退出(基于SQL事件探查器中记录的内容)。