取(简化的)存储过程定义这里:
create procedure get_some_stuffs
@max_records int = null
as
begin
set NOCOUNT on
select top (@max_records) *
from my_table
order by mothers_maiden_name
end
Run Code Online (Sandbox Code Playgroud)
我想限制所选记录的数量,如果只 @max_records提供。
问题:
在真正的查询是肮脏和大; 我想避免重复此操作:
if(@max_records is null)
begin
select *
from {massive query}
end
else
begin
select top (@max_records)
from {massive query}
end
Run Code Online (Sandbox Code Playgroud)任意定点值感觉不对:
select top (ISNULL(@max_records, 2147483647)) *
from {massive query}
Run Code Online (Sandbox Code Playgroud)
例如,如果@max_records是null与{massive query}返回小于2147483647行,这将是相同的:
select *
from {massive query}
Run Code Online (Sandbox Code Playgroud)
或者是有某种惩罚的选择top (2147483647) *从表中只有50行?
是否有其他现有模式可用于可选地限制计数的结果集,而无需重复查询或使用标记值?
我正在考虑这个问题,虽然我喜欢IF你Problem 1声明中的明确表述,但我理解重复的问题。因此,您可以将主查询放在单个 CTE 中,并使用一些技巧从中查询(粗体部分是此解决方案的亮点):
CREATE PROC get_some_stuffs
(
@max_records int = NULL
)
AS
BEGIN
SET NOCOUNT ON;
WITH staged AS (
-- Only write the main query one time
SELECT * FROM {massive query}
)
-- This part below the main query never changes:
SELECT *
FROM (
-- A little switcheroo based on the value of @max_records
SELECT * FROM staged WHERE @max_records IS NULL
UNION ALL
SELECT TOP(ISNULL(@max_records, 0)) * FROM staged WHERE @max_records IS NOT NULL
) final
-- Can't use ORDER BY in combination with a UNION, so move it out here
ORDER BY mothers_maiden_name
END
Run Code Online (Sandbox Code Playgroud)
UNION ALL我查看了每个查询的实际查询计划,优化器足够聪明,可以完全避免不需要运行的部分。
之所以ISNULL(@max_records, 0)存在在那里,是因为TOP NULL无效,并且无法编译。