Хранимая процедура с условными результатами

Я хочу записать хранимую процедуру, которая работает что-то вроде этого:

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

если это возвращает строки, возвратите те строки, в противном случае возвратитесь

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

Править:

Это чувствует, что должен быть способ создать процедуру, таким образом, что это выполняет первый запрос однажды и выполняет второй запрос только если необходимый.

Редактирование конца.

Лучшим, которым я мог управлять, было следование, которое (в теории) выполняет первый запрос дважды, если, возможно, его кэшируемый:

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

5
задан Martin Smith 15 October 2011 в 13:10
поделиться

6 ответов

Это должно исключить дополнительный доступ к таблице для проверки существования. Я не уверен, что есть способ лучше.

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
5
ответ дан 15 December 2019 в 00:49
поделиться

Я думаю, вы можете сделать это с помощью табличной переменной, что позволит избежать проблемы с двумя наборами результатов. Что-то вроде:

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
1
ответ дан 15 December 2019 в 00:49
поделиться

Почему вы не можете сделать это в одном запросе:

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
ответ дан 15 December 2019 в 00:49
поделиться

Вы также можете сделать это с помощью одного запроса:

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)
0
ответ дан 15 December 2019 в 00:49
поделиться

Я не знаю, помогает ли это вообще с точки зрения производительности, но вы можете попробовать функцию с табличным значением:

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

Но я сомневаюсь, что это поможет.

В целом я придерживаюсь вашего оригинального подхода. Он самый простой и чистый. А кеш и хороший индекс должны позаботиться о производительности.

Если бы здесь были реальные проблемы с производительностью, я бы отступил и посмотрел на этот дизайн базы данных. Почему у вас там нули? Почему вы пробуете два фильтра? Можно по-другому смоделировать? Если нет, может быть, небольшая денормализация?

0
ответ дан 15 December 2019 в 00:49
поделиться

EDIT Ответ был отредактировано после того, как вопрос был отредактирован.

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
-2
ответ дан 15 December 2019 в 00:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: