T-SQL 和存储过程使用相同的查询给出不同的结果

T-SQL and Stored Procedure gives different results with same query

我是新来的。有一个奇怪的问题。我的 T-SQL 查询 returns 69 行,但存储过程中的相同查询 returns 零个结果。

在 Whosebug 的一篇帖子中,有人切换了 EXEC 语句中的参数/变量,但这对我来说也不起作用,如下所示。

而不是 BETWEEN,我也尝试了 >=<=,但没有成功。

谢谢。

SELECT 
    T1.CustKey
FROM 
    INVOICEROWS T0 
INNER JOIN 
    INVOICE T1 ON T1.INVKEY = T0.INVKEY 
INNER JOIN 
    ITEMS T2 ON T2.PARTCODE = T0.PARTCODE  
INNER JOIN 
    CUSTOMERS T5 ON T5.CustKey = T1.CustKey
WHERE 
    T1.INVDATE BETWEEN '2018-03-26' AND '2018-03-26'
    AND ((T1.CustKey BETWEEN 'ABC' AND 'ABC') OR (T5.CustGroupKey = ''))
    AND ((T0.ItemKey BETWEEN 'PQR' AND 'STU') OR (T2.ItemGroupKey = ''))

结果:69 行具有相同的值 'ABC'(正确)

ALTER PROCEDURE [dbo].[PROC1]
    (@DATEFROM AS DATE,
     @DATETO AS DATE,
     @CUSTKEYFROM AS NVARCHAR,
     @CUSTKEYTO AS NVARCHAR,
     @CUSTGROUPKEY AS SMALLINT,
     @ItemKeyFrom NVARCHAR(20),
     @ItemKeyTo NVARCHAR(20),
     @ItemGroupKey NVARCHAR(11)
    )
AS
BEGIN
    SET NOCOUNT ON;

    -- Insert statements for procedure here
    SELECT 
        T1.CustKey
    FROM 
        INVOICEROWS T0 
    INNER JOIN 
        INVOICE T1 ON T1.INVKEY = T0.INVKEY 
    INNER JOIN 
        ITEMS T2 ON T2.PARTCODE = T0.PARTCODE  
    INNER JOIN 
        CUSTOMERS T5 ON T5.CustKey = T1.CustKey
    WHERE 
        T1.INVDATE BETWEEN @DATEFROM AND @DATETO
        AND ((T1.CustKey BETWEEN @CUSTKEYFROM AND @CUSTKEYTO) OR (T5.CustGroupKey = @CUSTGROUPKEY))
        AND ((T0.ItemKey BETWEEN @ItemKeyFrom AND @ItemKeyTo) OR (T2.ItemGroupKey = @ItemGroupKey))
END

运行这个存储过程:

EXEC PROC1 '2018-03-26', '2018-03-26', 'ABC', 'ABC', '', 'PQR', 'STU', '' 

returns 零行

EXEC PROC1 '2018-03-26', '2018-03-26', 'ABC', 'PQR', '', 'ABC', 'STU', '' 

还有 returns 零行

在存储过程中,您已将 @CUSTGROUPKEY 参数声明为 SMALLINT,但在查询中您将 T5.CustGroupKey 与 '' 进行了比较。当您将值 '' 传递给 SMALLINT 参数时,它变为 0 并且当您将它与 nvarchar 列进行比较时 您正在搜索 '0' ,您在比较之前强制将该列中的所有值转换为 smallint(由于数据类型的优先级)。虽然错误的参数类型可能会导致错误,但这不是您得不到任何结果的原因。请参阅 marc_s 的答案。

我打赌你的问题是你的两个存储过程参数的错误声明

ALTER PROCEDURE [dbo].[PROC1]
    (@DATEFROM AS DATE,
     @DATETO AS DATE,
     @CUSTKEYFROM AS NVARCHAR,
     @CUSTKEYTO AS NVARCHAR,
     @CUSTGROUPKEY AS SMALLINT,
     @ItemKeyFrom NVARCHAR(20),
     @ItemKeyTo NVARCHAR(20),
     @ItemGroupKey NVARCHAR(11)
    )

您已将 @CUSTKEYFROM@CUSTKEYTO 声明为 NVARCHAR。这 表示 :您得到一个 恰好一个字符 长度的字符串!这很少是您期望或想要的......

尝试用长度声明这两个参数——你应该总是这样做! - 我现在敢打赌,您的存储过程将 return 得到想要的结果!

ALTER PROCEDURE [dbo].[PROC1]
    (@DATEFROM AS DATE,
     @DATETO AS DATE,
     -- add explicit LENGTH to the NVARCHAR! However long you need it
     @CUSTKEYFROM AS NVARCHAR(25),
     @CUSTKEYTO AS NVARCHAR(25),

请参阅 Bad habits to kick : declaring VARCHAR without (length),了解您应该立即改掉的这个“坏习惯”的详尽解释