简体   繁体   English

存储过程与条件结果

[英]Stored Procedure with conditional results

I want to write a stored procedure that works something like this: 我想编写一个类似这样的存储过程:

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

if that returns rows, return those rows, if not, return 如果返回行,则返回这些行,否则返回

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

Edit: 编辑:

It feels that there should be a way to create a procedure such that it runs the first query once and runs the second query only if necessary . 感觉应该有一种方法来创建一个过程,使其运行第一个查询一次,仅在必要时运行第二个查询。

End Edit. 结束编辑。

The best I could manage was the follow, which (in theory) runs the first query twice, unless maybe its cached: 我能管理的最好的是跟随,它(理论上)运行第一个查询两次,除非缓存它:

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

For what its worth, this is in Microsoft SQL Server 2008 值得一提的是,这是在Microsoft SQL Server 2008中

This should avoid the additional table access for the existence check. 这应该避免存在检查的附加表访问。 I'm not sure if there's a neater way. 我不确定是否有更简洁的方式。

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

I think you can do this with a table variable, which should avoid the two resultsets issue. 我认为你可以使用表变量来做到这一点,这应该避免两个结果集问题。 Something like: 就像是:

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

You can also do it in one query: 您也可以在一个查询中执行此操作:

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)

Why can't you do this in a single query: 为什么不能在单个查询中执行此操作:

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
                    )

Another single query solution: 另一种查询解决方案:

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)

I don't know it if helps at all performance-wise, but you could try table-valued function: 我不知道它是否在性能上有所帮助,但你可以尝试表值函数:

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

But I doubt it helps. 但我怀疑它有帮助。

Generally I would stick with your original approach. 一般来说,我会坚持你的原始方法。 It is the simplest and cleanest. 这是最简单,最干净的。 And cache and good index should take care of performance. 缓存和良好的索引应该兼顾性能。

If there were real performance problems here, I would step back and look at this database design. 如果这里有真正的性能问题,我会退一步看看这个数据库设计。 Why are you having nulls there? 你为什么在那里有空? Why are you trying two filters? 你为什么要尝试两个过滤器? Can it be modeled differently? 可以用不同的方式建模吗? If not, maybe a little denormalization? 如果没有,也许有点非规范化?

Try this, if the first select return rows , then it returns if the first fails then the next select returns or finally the last select: 试试这个,如果第一个选择返回行,那么如果第一个失败则返回,然后下一个选择返回或最后选择:

IF EXISTS(SELECT * FROM Customers 

     INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID where Customers.CustomerID='BERJGS')
    BEGIN
             SELECT * FROM Customers 
                    INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID where Customers.CustomerID='BERJGS'
              PRINT 'TOLA'
              RETURN
     END
ELSE
     BEGIN
               SELECT * FROM Customers 
                    INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID where Customers.CustomerID='6CHOPS'             
              IF @@ROWCOUNT > 0             
                    RETURN              
              --RETURN
     END



SELECT * FROM Customers  where Customers.CustomerID='FRANK'

EDIT The answer was edited after the question was edited. 编辑在编辑问题后编辑答案。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM