2010-07-02 67 views
5

我想写的作品像这样一个存储过程:存储过程与条件结果

SELECT * from T where T.A = @a and T.B = @b 

如果返回行,返回那些行,如果没有,返回

SELECT * from T where T.A = @a and T.B IS NULL 

编辑:

感觉应该有一种方法来创建一个程序,使其运行第一个查询一次并仅在必要时运行第二个查询

End Edit。

我可以管理是后续的,这(理论上)运行在第一个查询两次,最好除非也许它的缓存:

IF EXISTS (SELECT * from T where T.A = @a and T.B = @b) THEN 
    SELECT * from T where T.A = @a and T.B = @b 
ELSE 
    SELECT * from T where T.A = @a and T.B IS NULL 

为了什么它的价值,这是Microsoft SQL Server 2008中

+0

哪个数据库和版本? – Blorgbeard 2010-07-02 18:26:09

+0

你的问题或问题是?!?!?!?你似乎有一种方法 - 这是行不通的,还是有什么问题? – 2010-07-02 18:26:18

+0

如果这是SQL Server 2000,那么这是我知道的最好的方法,但是+1因为我想知道是否有另一种方法! – 2010-07-02 18:27:36

回答

5

这应该避免存在检查的附加表访问。我不确定是否有更好的方法。

SELECT * from T where T.A = @a and T.B = @b 


IF (@@ROWCOUNT = 0) 
BEGIN 
    SELECT * from T where T.A = @a and T.B IS NULL 
END 
+1

请注意,返回两个结果集。 – 2010-07-02 18:30:05

+1

@BC - 好点。 – 2010-07-02 18:32:56

+2

我认为这是表现最好的,但如果第一个结果为空,则应用程序必须查看第二个结果。 – 2010-07-02 18:36:49

-2

编辑的问题进行修改后,将答案编辑。

CREATE PROCEDURE myconditionalsp 
@a <type>, 
@b <type> 
AS 

SELECT * from T 
where 
    -- the second condition is true AND the first condition is false 
    (((T.A = @a) and (T.B IS NULL)) AND NOT ((T.A = @a) and (T.B = @b))) 
    OR 
    -- the first condition is true (regardless what is the second condition) 
    ((T.A = @a) and (T.B = @b)) 
GO 
+0

为了以相同的方式工作,“AND NOT”部分将需要“AND NOT EXISTS(......) – 2010-07-05 07:09:32

0

你也可以做到在一个查询:

SELECT * from T where (T.A = @a and T.B = @b) OR 
(0=(SELECT COUNT(*) T1 where (T1.A = @a and T1.B = @b)) 
    AND T.A = @a and T.b IS NULL) 
1

我想你可以用一个表变量,应该避免两个结果的问题做到这一点。喜欢的东西:

declare @result1 table (...) 
insert into @result1 select * from T where T.A = @a and T.B = @b 

if (@@rowcount = 0) 
    select * from T where T.A = @a and T.B is null 
else 
    select * from @result1 
+0

这种方法虽然在创建表变量时插入了一个开销,然后从中选择可能超过避免检查的任何潜在好处我开始认为这个问题的方法不能真正改善 – 2010-07-02 18:49:06

0

在一个查询为什么你不能做到这一点:

Select ... 
From T 
Where T.A = @a 
    And T.B = @b 
Union All 
Select ... 
From T 
Where T.A = @a 
    And T.B Is Null 
    And Not Exists (
        Select 1 
        From T 
        Where T.A = @a 
         And T.B = @b 
        ) 

另一个单号查询解决方案:

Select ... 
From T 
Where T.A = @a 
    And T.B = @b 
Union All 
(Select ... 
From T 
Where T.A = @a 
    And T.B Is Null 
Except 
Select ... 
From T 
Where T.A = @a 
    And T.B = @b) 
+0

单个查询是,但相同或更差的执行计划 – 2010-07-02 18:48:09

+0

@BC - 不一定,它可能比IF语句更好地处理参数嗅探问题。 – Thomas 2010-07-02 18:53:58

0

我不知道它是否在帮助所有的表现明智,但你可以尝试表值函数:

create function fun(@a <aType>, @b <bType>) 
returns @result (<...columns...>) 
as begin 
insert into @result 
select * from T where T.A = @a and T.B = @b; 

if (@@ROWCOUNT = 0) begin 
    insert into @result 
    select * from T where T.A = @a and T.B is null; 
end; 
return; 
end; 
GO 

但我怀疑它有帮助。

通常我会坚持你的原始方法。这是最简单和最干净的。缓存和良好的索引应该考虑到性能。

如果在这里有真正的性能问题,我会退后一步,看看这个数据库设计。你为什么在那里有空位?你为什么要尝试两种过滤器?它可以以不同的方式建模吗?如果不是,也许有点反规范化?