SQL Server 存储过程返回意外值

Posted

技术标签:

【中文标题】SQL Server 存储过程返回意外值【英文标题】:SQL Server Stored procedure returning an unexpected value 【发布时间】:2018-04-03 23:21:56 【问题描述】:

我在 SQL Server 2008 中有这个从 C# 代码调用的存储过程:

CREATE PROCEDURE [dbo].[DepartmentStoreControlAccess]              
    @DeptId INT,             
    @intError tinyint OUTPUT,
AS
    SET @intError = 0

    SELECT @AccessTime = Hour
    FROM Entries
    WHERE DeptId = @DeptId

    IF @@ROWCOUNT = 1
    BEGIN
        -- DO STUFF and update @intError
    END
    ELSE
    BEGIN
        IF @@ROWCOUNT = 0   
            SET @intError = 0
        ELSE
            SET @intError = -1 
    END

有一个案例我确定是select:

SELECT @AccessTime = Hour
FROM Entries
WHERE DeptId = @DeptId

可能返回多于 1 行,比如说 2, 3, 4, .... , N 所以输出参数@intError 在这种情况下根据我的存储过程应该返回-1 但我不知道为什么,这种情况下的存储过程(当 select 返回超过 1 行时)在输出参数 @intError 中返回 0。为什么?

【问题讨论】:

不相关,但不能将 -1 分配给 tinyint 变量。您需要使用 smallint 或更大。 【参考方案1】:

原因是检查@@ROWCOUNT 会重置@@ROWCOUNT 中的值

IF @@ROWCOUNT = 1   -- From this point @@ROWCOUNT = 0
BEGIN
    -- DO STUFF and update @intError
END
ELSE
BEGIN
    if @@ROWCOUNT = 0   -- So we always end up here
        set @intError = 0
    else
        set @intError = -1 
END

【讨论】:

【参考方案2】:

第一次访问时需要将@@ROWCOUNT 保存到变量中,因为@@ROWCOUNT refers to the last statement。在您的 ELSE 案例中,@@ROWCOUNT 返回 0,因为您的最后一条语句是您的 IF 语句中的 @@ROWCOUNT

【讨论】:

【参考方案3】:
 DECLARE @Count INT
 SELECT @AccessTime=Hour
 FROM   Entries                                                                       
 WHERE  DeptId=@DeptId
 SET @Count = @@ROWCOUNT

并使用变量

返回受最后一条语句影响的行数。

【讨论】:

以上是关于SQL Server 存储过程返回意外值的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 存储过程返回值到gridview

SQL SERVER里面如何在存储过程里面获取另一个存储过程所返回的表的数据?

SQL SERVER里面如何在存储过程里面获取另一个存储过程所返回的表的数据?

hibernate 使用sql server的存储过程时没有返回值

Sql server2012存储过程参数传递null值,如何判定这个参数是null

SQL Server创建存储过程——动态SQL