【问题标题】:Getting rows affected in stored procedure INSERT statement with NOCOUNT OFF在 NOCOUNT OFF 的存储过程 INSERT 语句中获取受影响的行
【发布时间】:2015-12-15 21:34:00
【问题描述】:

我在 SQL Server 2014 中有一个存储过程,我首先从表中删除数据并执行另一个存储过程,如下所示。我不关心受此代码影响的行,因此我使用 SET NOCOUNT ON。然后我执行一个插入语句,首先设置 SET NOCOUNT OFF。我希望存储过程能够从 INSERT 返回自动受影响的行,但事实并非如此。我搜索了 SO 并找到了 @@ROWCOUNT 并且它正在工作。然而,这真的需要吗?为什么下面代码中的 INSERT 语句不会返回受影响的记录?

ALTER PROCEDURE [dbo].[SaveTextSetting]
    @UserId INT ,
    @SettingType INT = 0 ,
    @SettingValue NVARCHAR(MAX)
AS
    BEGIN
        BEGIN
            SET NOCOUNT ON;
            DELETE  FROM Settings
            WHERE   UserId = @UserId
                    AND SettingType = @SettingType;
            EXEC dbo.PurgeExpiredSettings;
        END;
        BEGIN
            SET NOCOUNT OFF;
            INSERT  INTO dbo.Settings
                    ( UserId ,
                      SettingsText ,
                      SettingType
                    )
            VALUES  ( @UserId ,
                      @SettingValue ,
                      @SettingType
                    );
            RETURN @@ROWCOUNT; --without this we don't get the rows affected
        END;
    END;

【问题讨论】:

  • 因为存储过程的返回值并不打算返回值。它返回一个状态码,指示执行的状态。如果你想返回一个值,你应该使用一个 OUTPUT 参数。
  • "为什么下面代码中的 INSERT 语句不会返回受影响的记录?" 1) 如果您有两个没有取消计数的语句,SQL Server 应该返回哪个值? 2)它正在返回它,而不是通过返回值。如果您在 SSMS 中运行该过程,您可以看到这一点。
  • @SeanLange - 从技术上讲,存储过程的返回值只是一个整数。该整数的值及其含义取决于开发人员。所以很容易受到影响的行数。
  • NOCOUNT 设置不影响@@ROWCOUNT,它决定SQL 是否返回一条消息,指示影响到客户端的行数(即你在Management Studio 的消息选项卡)。您在哪里没有受到影响的行?在调用这个存储过程的代码中?
  • @CodeNaked 是的 RETURN_VALUE 是一个整数,但在实践中,根据 MS 文档,它旨在返回指示执行状态的状态代码。 msdn.microsoft.com/en-us/library/ms188655.aspx 这当然可以用来返回受影响的行数,但不是标准的。

标签: sql-server tsql stored-procedures sql-server-2014


【解决方案1】:

你确定吗?

CREATE PROCEDURE spTest AS RETURN
GO
ALTER PROCEDURE spTest
AS
BEGIN
    SET NOCOUNT OFF
    DECLARE @rt int
    CREATE TABLE #t (
        v int NOT NULL
    )
    INSERT INTO #t (v)
    SELECT v FROM (VALUES (1), (1), (2)) AS t (v) 
    SET @rt = @@ROWCOUNT
    DROP TABLE #t
    RETURN @rt
END
GO

DECLARE @rt int
EXEC @rt = spTest
SELECT @rt
GO

DROP PROCEDURE spTest
GO

【讨论】:

  • 你上面的例子有点不同。尝试首先使用 SET NOCOUNT ON 执行代码块,然后在完成后使用 SET NOCOUNT OFF 执行另一个操作,看看会发生什么。看看我的示例如何首先执行 DELETE,然后在 INSERT 之前执行存储过程,我期望行会受到影响?
  • 您使用哪个版本的 SQL Server?
  • 使用 SET ROWCOUNT 不会影响 SQL Server 未来版本中的 DELETE、INSERT 和 UPDATE 语句。避免在新的开发工作中将 SET ROWCOUNT 与 DELETE、INSERT 和 UPDATE 语句一起使用,并计划修改当前使用它的应用程序。对于类似的行为,请使用 TOP 语法。 msdn.microsoft.com/en-us/library/ms188774%28v=sql.120%29.aspx
  • 即使 SET NOCOUNT 为 ON,@@ROWCOUNT 函数也会更新。 SET NOCOUNT 指定的设置在执行或运行时有效,而不是在解析时有效。 msdn.microsoft.com/en-us/library/ms189837%28v=sql.120%29.aspx
【解决方案2】:

我会使用类似于.....的输出参数

ALTER PROCEDURE [dbo].[SaveTextSetting]
    @UserId       INT ,
    @SettingType  INT = 0 ,
    @SettingValue NVARCHAR(MAX),
    @RowCount     INT             OUTPUT
AS
BEGIN
  SET NOCOUNT ON;

   DELETE  FROM Settings
   WHERE   UserId = @UserId
     AND   SettingType = @SettingType;

  EXEC dbo.PurgeExpiredSettings;

  INSERT  INTO dbo.Settings( UserId ,SettingsText ,SettingType)
  VALUES  ( @UserId ,@SettingValue ,@SettingType);

      SET @RowCount=  @@ROWCOUNT; 
END

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-15
    • 2020-12-08
    相关资源
    最近更新 更多