【问题标题】:SQL Nested IF-ELSE StatementsSQL 嵌套 IF-ELSE 语句
【发布时间】:2015-08-13 23:00:59
【问题描述】:

好吧,我正式不知所措了。我正在尝试创建一个贯穿每个后续检查并执行相应查询的过程。

但是,当我使用一个/两个/所有参数执行该过程时,它总是会在最终的 ELSE 中被捕获并吐出“覆盖所有”结果集。为什么???

我怀疑它可能是: -If/Else 语法 - 括号的使用 - 开始/结束关键字 - IF 条件太多?

非常感谢任何帮助!

加分项:我可以在 WHERE 子句中使用搜索的 CASE 来优化它吗?我知道我真的可以减少这段代码——但我真的很好奇为什么这不起作用。

CREATE PROC spBalanceRange
    @VendorVar varchar(50) = NULL,
    @BalanceMax money = NULL,
    @BalanceMin money = NULL

AS
    IF
    (
        @VendorVar != NULL
        AND @BalanceMin != NULL             
        AND @BalanceMax != NULL
    )

    BEGIN
        SELECT VendorName, InvoiceNumber, InvoiceTotal - (PaymentTotal + CreditTotal) AS BalanceDue
        FROM Invoices JOIN Vendors
            ON Invoices.VendorID = Vendors.VendorID
        WHERE
            VendorName = @VendorVar
            AND InvoiceTotal - (PaymentTotal + CreditTotal) >= @BalanceMin
            AND InvoiceTotal - (PaymentTotal + CreditTotal) <= @BalanceMax
    END
ELSE IF
    (
        @VendorVar != NULL
        AND @BalanceMin = NULL
        AND
            (
                @BalanceMax = NULL
                OR @BalanceMax = 0
            )
    )
    BEGIN
        SELECT VendorName, InvoiceNumber, InvoiceTotal - (PaymentTotal + CreditTotal) AS BalanceDue
        FROM Invoices JOIN Vendors
            ON Invoices.VendorID = Vendors.VendorID
        WHERE
            VendorName = @VendorVar
            AND InvoiceTotal - (PaymentTotal + CreditTotal) > 0
    END
ELSE
    BEGIN
        SELECT VendorName, InvoiceNumber, InvoiceTotal - (PaymentTotal + CreditTotal) AS BalanceDue
        FROM Invoices JOIN Vendors
            ON Invoices.VendorID = Vendors.VendorID
        WHERE
            InvoiceTotal - (PaymentTotal + CreditTotal) > 0
    END
;

【问题讨论】:

  • 没有什么等于 NULL,也没有什么不等于 NULL。您需要使用IS NULL 和/或IS NOT NULL。这些是处理正常规则的特殊运算符;任何涉及 NULL 的操作都会导致 NULL,包括相等和不相等。 1 = NULL 不会产生 FALSE,它会产生 NULL。而NULL = NULL 不会产生 TRUE,它会产生 NULL。)
  • 该死!!一直以来,我都不知道。我真的很感激!

标签: sql-server if-statement case


【解决方案1】:

理想情况下,您应该使用动态 sql 来避免像这样的查询中出现类似问题的参数嗅探,使用动态 sql 的解决方案看起来像这样.....

CREATE PROC spBalanceRange
    @VendorVar varchar(50) = NULL,
    @BalanceMax money = NULL,
    @BalanceMin money = NULL

AS
BEGIN
  SET NOCOUNT ON;
  DECLARE @Sql NVARCHAR(MAX);



SET @Sql  = N'SELECT VendorName, InvoiceNumber, InvoiceTotal - (PaymentTotal + CreditTotal) AS BalanceDue
        FROM Invoices 
        INNER JOIN Vendors ON Invoices.VendorID = Vendors.VendorID
        WHERE '
        + CASE 
        WHEN         (@VendorVar IS NOT NULL 
                      AND @BalanceMin IS NOT NULL             
                      AND @BalanceMax IS NOT NULL)
         THEN N' VendorName = @VendorVar
            AND InvoiceTotal - (PaymentTotal + CreditTotal) >= @BalanceMin
            AND InvoiceTotal - (PaymentTotal + CreditTotal) <= @BalanceMax' 

        WHEN          ( @VendorVar IS NOT NULL
                        AND @BalanceMin IS NULL
                        AND (@BalanceMax IS NULL OR @BalanceMax = 0))
         THEN N' VendorName = @VendorVar
               AND InvoiceTotal - (PaymentTotal + CreditTotal) > 0'
        ELSE N' InvoiceTotal - (PaymentTotal + CreditTotal) > 0' END

Exec sp_executesql @Sql 
                  ,N'@VendorVar varchar(50),@BalanceMax money,@BalanceMin money'
                  ,@VendorVar 
                  ,@BalanceMax 
                  ,@BalanceMin 

END

【讨论】:

  • 我想知道是否要涉足这样的事情,这也详细说明了“IS”与“=”的问题。非常感谢。
【解决方案2】:

我认为这是因为您将它们与 null 与 == 进行比较。使用 t-sql,您始终需要使用 is 运算符。

试试

x is not null

x is null

改为。

【讨论】:

    【解决方案3】:

    我不在 Windows 机器附近,所以这可能需要调整:

    CREATE PROC spBalanceRange
        @VendorVar varchar(50) = NULL,
        @BalanceMax money = NULL,
        @BalanceMin money = NULL
    
    AS
    SELECT VendorName, InvoiceNumber, InvoiceTotal - (PaymentTotal + CreditTotal) AS BalanceDue
    FROM Invoices JOIN Vendors
    ON Invoices.VendorID = Vendors.VendorID
    WHERE
    case when @VendorVar is null then true else vendorName=@vendorVar end
    AND InvoiceTotal - (PaymentTotal + CreditTotal) >= coalesce(@BalanceMin,0)
    AND case when @BalanceMax is null then true else InvoiceTotal - (PaymentTotal + CreditTotal) <= coalesce(@BalanceMax, 1e15) end;
    

    【讨论】:

      【解决方案4】:

      使用 case 语句的另一种方法可能会显示您想要的结果:

      CREATE PROCEDURE spBalanceRange
      
      @VendorVar varchar(50) = NULL,
      @BalanceMax money = NULL,
      @BalanceMin money = NULL
      
      AS
      BEGIN
      SELECT 
      
      b.VendorName, a.InvoiceNumber, 
      
      case 
      when InvoiceTotal - (PaymentTotal + CreditTotal) between @BalanceMax and     @BalanceMin
      then InvoiceTotal - (PaymentTotal + CreditTotal) 
      else 0
      end BalanceDue
      FROM Invoices a
      JOIN Vendors b
      ON a.VendorID = b.VendorID
      WHERE
      b.VendorName = @VendorVar 
      and InvoiceTotal - (PaymentTotal + CreditTotal) between @BalanceMax and @BalanceMin
      END
      

      希望我能正确理解您要完成的工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-14
        • 2020-06-17
        相关资源
        最近更新 更多