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),了解您应该立即改掉的这个“坏习惯”的详尽解释
我是新来的。有一个奇怪的问题。我的 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 列进行比较时 您正在搜索 ,您在比较之前强制将该列中的所有值转换为 smallint(由于数据类型的优先级)。虽然错误的参数类型可能会导致错误,但这不是您得不到任何结果的原因。请参阅 marc_s 的答案。'0'
我打赌你的问题是你的两个存储过程参数的错误声明:
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),了解您应该立即改掉的这个“坏习惯”的详尽解释