【问题标题】:SQL Server : Optional Parameter Behavior LogicSQL Server:可选参数行为逻辑
【发布时间】:2019-07-05 23:00:24
【问题描述】:

我正在 SQL Server 2014 中实现一个存储过程,它有两个参数:@CLIENTID@CONTRACTID。其中一个参数是可选的,因此,当存储过程只接收到客户端 ID 时,它应该返回与该客户端相关的所有信息,当它同时接收到客户端 ID 和合同 ID 时,它应该只返回与该客户端相关的信息来自该特定客户的特定合同。

这是一些示例代码...

CREATE PROCEDURE SP_EXAMPLE_STACKOVERFLOW
    @CLIENTID INT,
    @CONTRACTID INT = NULL
AS
    SELECT
        *
    FROM 
        Table T
    WHERE 
        T.CLIENTID = @CLIENTID
        AND (T.CONTRACTID = @CONTRACTID OR ISNULL(@CONTRACTID, 0) = 0)

上面的代码有效,但是我的第一次尝试是把最后一行写成这样:

AND T.CONTRACTID = ISNULL(@CONTRACTID, T.CONTRACTID)

但是这不起作用...它基本上认为最后一行一直被评估为 FALSE。

我不知道为什么......我会很感激一些帮助

【问题讨论】:

  • 听起来 T.CONTRACTID 在您的数据集中为 NULL。在这种情况下,ISNULL 将丢弃 NULL 参数,然后改用 NULL 字段。在 SQL 中,比较 NULL = NULL 的行为类似于 FALSE(从技术上讲,比较 NULL = NULL 将评估为 NULL,当与其他条件进行 AND 运算时,它的行为类似于 FALSE。)
  • 旁注:您应该为您的存储过程使用sp_ 前缀。微软有reserved that prefix for its own use (see Naming Stored Procedures),你确实会在未来某个时候冒着名称冲突的风险。 It's also bad for your stored procedure performance。最好只是简单地避免sp_ 并使用其他东西作为前缀 - 或者根本不使用前缀!

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


【解决方案1】:

我想你想要:

SELECT T.*
FROM Table T
WHERE T.CLIENTID = @CLIENTID AND
      (@CONTRACTID IS NULL OR T.CONTRACTID = @CONTRACTID)

如果@CONTRACTIDNULL,这将返回客户端的所有合同。如果不是NULL,它将只返回指定的合约。

事实并非如此:

T.CONTRACTID = ISNULL(@CONTRACTID, T.CONTRACTID)

建议T.CONTRACTID 可以是NULL。这是唯一不等于自身的值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-22
    • 2018-10-30
    相关资源
    最近更新 更多