当n可以为0时,将SET ROWCOUNT n转换为TOP(n)

时间:2017-09-15 17:24:51

标签: sql-server tsql sql-server-2016 sql-limit

我们目前正在使用SQL Server 2016.基于Microsoft页面Deprecated Database Engine Features in SQL Server 2016SET ROWCOUNT已被弃用。因此,我们尝试将所有SET ROWCOUNT N语句转换为TOP(N)语句。看起来很容易但我们遇到了一个案例,其中N是存储过程中的参数,默认为0.

所以在旧代码中,它类似于SET ROWCOUNT @NumRows。如果@NumRows为0,则表示关闭SET ROWCOUNT选项,因此以下查询将返回所有行。但如果我们将其转换为TOP(@NumRows),则意味着它将返回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

2 个答案:

答案 0 :(得分:1)

您可以在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

<强> Rextester Demo

请注意可能的性能影响。另外,ORDER BY没有明确的post_id可能会返回不同的结果集。

答案 1 :(得分:1)

听起来你的程序定义是这样的。如果您发布了定义,那么在这里帮助会更容易。

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