SQL 查询在 运行 和 sp_executesql 时表现不同
SQL query behaving differently when run with sp_executesql
我在 SQL Server 2012 中有一个查询,我首先 运行 不使用 sp_executesql,然后 运行 使用 sp_executesql 对其进行查询。奇怪的是,这两个 运行s 给出了不同的结果,当它们应该相同时,因为它们使用相同的 SQL 查询。
我什至尝试过使用 OUTPUT
作为 @productId
,如下面的代码所示,但即便如此也没有任何区别。在此 post 末尾给出的屏幕截图中,前两个结果集应与后两个结果集重复,但它们不会。
EXECUTE sp_executesql @qry,
N'@maxRows int,@startingRowNumber int,@productId bigint OUTPUT',
@maxRows = @maxRows,
@productId = @productId OUTPUT,
@startingRowNumber = @numberOfRowsToSkip
问题:是什么导致相同查询的结果不同?
DECLARE @startingRowNumber INT = 1;
DECLARE @productId BIGINT;
DECLARE @maxRows INT = 10;
DECLARE @qryCount NVARCHAR(MAX);
DECLARE @qry NVARCHAR(MAX);
DECLARE @numberOfRowsToSkip INT;
SET @numberOfRowsToSkip = @startingRowNumber - 1;
--RUN query batch without sp_executesql
SELECT @productId = MAX(ProductId)
FROM (SELECT TOP (@startingRowNumber)
ProductId
FROM dbo.Prods
WHERE [Product Cost] < 1005
ORDER BY ProductId ASC) x;
SELECT @productId AS ProductId;
SELECT ProductId,Product,Vendor,VendorId,[Product Cost]
FROM dbo.Prods WITH (NOLOCK)
WHERE ProductId >= @productId
AND [Product Cost] < 1005
ORDER BY [Product Cost] ASC OFFSET @numberOfRowsToSkip
ROWS FETCH NEXT @maxRows ROWS ONLY;
--RUN query batch using sp_executesql
SET @qry = N'SELECT @productId = MAX(ProductId)
FROM (SELECT TOP (@startingRowNumber)
ProductId
FROM dbo.Prods
WHERE [Product Cost] < 1005
ORDER BY ProductId ASC) x;
SELECT @productId AS ProductId;
SELECT ProductId,Product,Vendor,VendorId,[Product Cost]
FROM dbo.Prods WITH (NOLOCK)
WHERE ProductId >= @productId
AND [Product Cost] < 1005
ORDER BY [Product Cost] ASC OFFSET @numberOfRowsToSkip
ROWS FETCH NEXT @maxRows ROWS ONLY';
EXECUTE sp_executesql @qry,
N'@maxRows int,@startingRowNumber int,@productId bigint',
@maxRows = @maxRows,
@productId = @productId,
@startingRowNumber = @numberOfRowsToSkip
PRINT N'Executed select query'
查询结果截图
更新 1
有趣的是,我还注意到查询 1 returns 一个值,但查询 2 没有。我很确定这个问题的答案就是原始问题的答案。
查询 1
SELECT @productId = Max(x.ProductId) FROM
(SELECT TOP (@startingRowNumber) ProductId FROM dbo.Prods WHERE
[Product Cost] < 1005 ORDER BY ProductId ASC) x;
SELECT @productId AS ProductId
查询 2
SET @qry = N'SELECT @productId = Max(x.ProductId) FROM
(SELECT TOP (@startingRowNumber) ProductId FROM dbo.Prods WHERE
[Product Cost] < 1005 ORDER BY ProductId ASC) x;';
EXECUTE sp_executesql @qry,
N'@maxRows int,@startingRowNumber int,@productId bigint OUTPUT',
@productId = @productId OUTPUT,
@startingRowNumber = @numberOfRowsToSkip,
@maxRows = @maxRows
SELECT @productId AS ProductId
我认为你的差异是由以下原因造成的:
No dynamic: {OFFSET @startingRowNumber}
Dynamic: {OFFSET @numberOfRowsToSkip} = {OFFSET @startingRowNumber - 1;}
此外,@productId 在您的动态查询中分配,但也作为输入提供。您应该在查询中声明它并将其从 sp_executesql
:
的参数列表中删除
DECLARE @productId BIGINT
SET @qry = N'SELECT @productId = MAX(ProductId)
FROM (SELECT TOP (@startingRowNumber)
...
我的动态查询中出现了一个愚蠢的错误。以下 sp_executesql 导致正确执行。我不得不改变两件事。另外,我不必将 @productId
声明为 OUTPUT
类型参数。
- 已将
@startingRowNumber = @numberOfRowsToSkip
更改为 @startingRowNumber = @startingRowNumber
- 将
@numberOfRowsToSkip
的另一个参数添加到 sp_executesql
使其工作的代码
EXECUTE sp_executesql @qry,
N'@maxRows int,@startingRowNumber int,@productId bigint,@numberOfRowsToSkip int ',
@maxRows = @maxRows,
@productId = @productId,
@startingRowNumber = @startingRowNumber,
@numberOfRowsToSkip = @numberOfRowsToSkip
我在 SQL Server 2012 中有一个查询,我首先 运行 不使用 sp_executesql,然后 运行 使用 sp_executesql 对其进行查询。奇怪的是,这两个 运行s 给出了不同的结果,当它们应该相同时,因为它们使用相同的 SQL 查询。
我什至尝试过使用 OUTPUT
作为 @productId
,如下面的代码所示,但即便如此也没有任何区别。在此 post 末尾给出的屏幕截图中,前两个结果集应与后两个结果集重复,但它们不会。
EXECUTE sp_executesql @qry,
N'@maxRows int,@startingRowNumber int,@productId bigint OUTPUT',
@maxRows = @maxRows,
@productId = @productId OUTPUT,
@startingRowNumber = @numberOfRowsToSkip
问题:是什么导致相同查询的结果不同?
DECLARE @startingRowNumber INT = 1;
DECLARE @productId BIGINT;
DECLARE @maxRows INT = 10;
DECLARE @qryCount NVARCHAR(MAX);
DECLARE @qry NVARCHAR(MAX);
DECLARE @numberOfRowsToSkip INT;
SET @numberOfRowsToSkip = @startingRowNumber - 1;
--RUN query batch without sp_executesql
SELECT @productId = MAX(ProductId)
FROM (SELECT TOP (@startingRowNumber)
ProductId
FROM dbo.Prods
WHERE [Product Cost] < 1005
ORDER BY ProductId ASC) x;
SELECT @productId AS ProductId;
SELECT ProductId,Product,Vendor,VendorId,[Product Cost]
FROM dbo.Prods WITH (NOLOCK)
WHERE ProductId >= @productId
AND [Product Cost] < 1005
ORDER BY [Product Cost] ASC OFFSET @numberOfRowsToSkip
ROWS FETCH NEXT @maxRows ROWS ONLY;
--RUN query batch using sp_executesql
SET @qry = N'SELECT @productId = MAX(ProductId)
FROM (SELECT TOP (@startingRowNumber)
ProductId
FROM dbo.Prods
WHERE [Product Cost] < 1005
ORDER BY ProductId ASC) x;
SELECT @productId AS ProductId;
SELECT ProductId,Product,Vendor,VendorId,[Product Cost]
FROM dbo.Prods WITH (NOLOCK)
WHERE ProductId >= @productId
AND [Product Cost] < 1005
ORDER BY [Product Cost] ASC OFFSET @numberOfRowsToSkip
ROWS FETCH NEXT @maxRows ROWS ONLY';
EXECUTE sp_executesql @qry,
N'@maxRows int,@startingRowNumber int,@productId bigint',
@maxRows = @maxRows,
@productId = @productId,
@startingRowNumber = @numberOfRowsToSkip
PRINT N'Executed select query'
查询结果截图
更新 1
有趣的是,我还注意到查询 1 returns 一个值,但查询 2 没有。我很确定这个问题的答案就是原始问题的答案。
查询 1
SELECT @productId = Max(x.ProductId) FROM
(SELECT TOP (@startingRowNumber) ProductId FROM dbo.Prods WHERE
[Product Cost] < 1005 ORDER BY ProductId ASC) x;
SELECT @productId AS ProductId
查询 2
SET @qry = N'SELECT @productId = Max(x.ProductId) FROM
(SELECT TOP (@startingRowNumber) ProductId FROM dbo.Prods WHERE
[Product Cost] < 1005 ORDER BY ProductId ASC) x;';
EXECUTE sp_executesql @qry,
N'@maxRows int,@startingRowNumber int,@productId bigint OUTPUT',
@productId = @productId OUTPUT,
@startingRowNumber = @numberOfRowsToSkip,
@maxRows = @maxRows
SELECT @productId AS ProductId
我认为你的差异是由以下原因造成的:
No dynamic: {OFFSET @startingRowNumber}
Dynamic: {OFFSET @numberOfRowsToSkip} = {OFFSET @startingRowNumber - 1;}
此外,@productId 在您的动态查询中分配,但也作为输入提供。您应该在查询中声明它并将其从 sp_executesql
:
DECLARE @productId BIGINT
SET @qry = N'SELECT @productId = MAX(ProductId)
FROM (SELECT TOP (@startingRowNumber)
...
我的动态查询中出现了一个愚蠢的错误。以下 sp_executesql 导致正确执行。我不得不改变两件事。另外,我不必将 @productId
声明为 OUTPUT
类型参数。
- 已将
@startingRowNumber = @numberOfRowsToSkip
更改为@startingRowNumber = @startingRowNumber
- 将
@numberOfRowsToSkip
的另一个参数添加到 sp_executesql
使其工作的代码
EXECUTE sp_executesql @qry,
N'@maxRows int,@startingRowNumber int,@productId bigint,@numberOfRowsToSkip int ',
@maxRows = @maxRows,
@productId = @productId,
@startingRowNumber = @startingRowNumber,
@numberOfRowsToSkip = @numberOfRowsToSkip