当 n 可能为 0 时,将 SET ROWCOUNT n 转换为 TOP (n)
Convert SET ROWCOUNT n to TOP (n) when n could be 0
我们目前正在使用 SQL server 2016。根据 Microsoft 页面 Deprecated Database Engine Features in SQL Server 2016,SET ROWCOUNT
已弃用。所以我们试图将所有 SET ROWCOUNT N
语句转换为 TOP(N)
语句。看起来很容易,但是我们遇到了一个情况,N是存储过程中的参数,默认为0。
所以在旧代码中,它类似于 SET ROWCOUNT @NumRows
。如果 @NumRows
为 0,则表示关闭 SET ROWCOUNT
选项,因此以下查询将 return 所有行。但是,如果我们将其转换为 TOP(@NumRows)
,则意味着它将 return 0 行。为了避免这个问题,我们可以添加额外的 IF 条件,如果 @NumRows
为 0,则将 @NumRows
设置为一个巨大的数字。或者我们可以添加额外的 IF 条件,如果 @NumRows
为 0,那么我们使用 SELECT 而不使用 TOP,否则我们照常使用 SELECT TOP(N)
。
但是这些解决方案中的任何一个都会在存储过程中添加额外的代码,所以我的问题是:考虑到 N 可能为 0,是否有一种优雅的方法将 SET ROWCOUNT N
转换为 TOP (N)
?
更新:添加了存储过程模板
-- Default to 0, in this case, SET ROWCOUNT 0 will return all result
-- But if we change it to TOP(@rows), it returns no result.
CREATE PROCEDURE Proc1
@rows int = 0
AS
SET ROWCOUNT @rows
SELECT Col1 FROM table1
ORDER BY Col2
SET ROWCOUNT 0
-- In this case, the default is not 0
-- But the program that calls this stored procedure could pass in value 0.
-- We also don't want to change default value for this stored procedure.
-- So I think in this case, we may have to add IF @rows = 0, SET @rows = huge_number
CREATE PROCEDURE Proc2
@rows int = 10
AS
SET ROWCOUNT @rows
SELECT Col3 FROM table2
ORDER BY Col4
SET ROWCOUNT 0
您可以在 TOP
子句中使用 subquery/expression 而不是特定值:
DECLARE @param INT = 0;
SELECT TOP (SELECT IIF(@param=0,2000000, @param)) * FROM sys.objects;
SELECT TOP (IIF(@param=0,2000000, @param)) * FROM sys.objects;
注意可能的性能影响。此外 TOP
没有显式 ORDER BY
可能 return 不同的结果集。
听起来你的过程定义是这样的。如果您发布定义,在这里提供帮助会容易得多。
create procedure MyProc
(
@NumRows int = 0
)
as
if @NumRows > 0
set rowcount @NumRows
else
set rowcount 0
select Columns
from Table
假设定义如上,您可以将其更改为类似的内容。
create procedure MyProc
(
@NumRows int = 2147483648 --max value for an int. This could be a bigint also if you have LOTS of data.
)
as
select top(@NumRows) Columns
from Table
请注意,在使用 TOP 时,您需要指定一个顺序,否则您无法知道将返回哪些行。
--编辑--
感谢您提供代码示例。看来我的猜测非常接近。您不必在此处使用 IF 语句,您可以直接在查询中更轻松地完成此操作。这类似于lad2025发布的答案。
select top(isnull(nullif(@NumRows, 0), 2147483647)) Columns
from Table
我们目前正在使用 SQL server 2016。根据 Microsoft 页面 Deprecated Database Engine Features in SQL Server 2016,SET ROWCOUNT
已弃用。所以我们试图将所有 SET ROWCOUNT N
语句转换为 TOP(N)
语句。看起来很容易,但是我们遇到了一个情况,N是存储过程中的参数,默认为0。
所以在旧代码中,它类似于 SET ROWCOUNT @NumRows
。如果 @NumRows
为 0,则表示关闭 SET ROWCOUNT
选项,因此以下查询将 return 所有行。但是,如果我们将其转换为 TOP(@NumRows)
,则意味着它将 return 0 行。为了避免这个问题,我们可以添加额外的 IF 条件,如果 @NumRows
为 0,则将 @NumRows
设置为一个巨大的数字。或者我们可以添加额外的 IF 条件,如果 @NumRows
为 0,那么我们使用 SELECT 而不使用 TOP,否则我们照常使用 SELECT TOP(N)
。
但是这些解决方案中的任何一个都会在存储过程中添加额外的代码,所以我的问题是:考虑到 N 可能为 0,是否有一种优雅的方法将 SET ROWCOUNT N
转换为 TOP (N)
?
更新:添加了存储过程模板
-- Default to 0, in this case, SET ROWCOUNT 0 will return all result
-- But if we change it to TOP(@rows), it returns no result.
CREATE PROCEDURE Proc1
@rows int = 0
AS
SET ROWCOUNT @rows
SELECT Col1 FROM table1
ORDER BY Col2
SET ROWCOUNT 0
-- In this case, the default is not 0
-- But the program that calls this stored procedure could pass in value 0.
-- We also don't want to change default value for this stored procedure.
-- So I think in this case, we may have to add IF @rows = 0, SET @rows = huge_number
CREATE PROCEDURE Proc2
@rows int = 10
AS
SET ROWCOUNT @rows
SELECT Col3 FROM table2
ORDER BY Col4
SET ROWCOUNT 0
您可以在 TOP
子句中使用 subquery/expression 而不是特定值:
DECLARE @param INT = 0;
SELECT TOP (SELECT IIF(@param=0,2000000, @param)) * FROM sys.objects;
SELECT TOP (IIF(@param=0,2000000, @param)) * FROM sys.objects;
注意可能的性能影响。此外 TOP
没有显式 ORDER BY
可能 return 不同的结果集。
听起来你的过程定义是这样的。如果您发布定义,在这里提供帮助会容易得多。
create procedure MyProc
(
@NumRows int = 0
)
as
if @NumRows > 0
set rowcount @NumRows
else
set rowcount 0
select Columns
from Table
假设定义如上,您可以将其更改为类似的内容。
create procedure MyProc
(
@NumRows int = 2147483648 --max value for an int. This could be a bigint also if you have LOTS of data.
)
as
select top(@NumRows) Columns
from Table
请注意,在使用 TOP 时,您需要指定一个顺序,否则您无法知道将返回哪些行。
--编辑--
感谢您提供代码示例。看来我的猜测非常接近。您不必在此处使用 IF 语句,您可以直接在查询中更轻松地完成此操作。这类似于lad2025发布的答案。
select top(isnull(nullif(@NumRows, 0), 2147483647)) Columns
from Table