Добавить пустую строку для запроса результатов, если результатов не найдено
Я пишу хранимые procs, которые вызываются унаследованной системой. Одним из ограничений устаревшей системы является то, что в едином результирующем наборе, возвращаемом из сохраненного процесса, должна быть хотя бы одна строка. Стандарт должен вернуть ноль в первом столбце (да, я знаю!).
Очевидный способ добиться этого - создать временную таблицу, поместить в нее результаты, протестировать любые строки в таблице temp и либо вернуть результаты из таблицы temp, либо один пустой результат.
Другим способом может быть выполнение EXISTS против того же предложения where, что и в основном запросе до выполнения основного запроса.
Ни одно из них не очень удовлетворительно. Может ли кто-нибудь подумать о лучшем пути. Я думал о таких типах UNION вроде этого (я знаю, что это не работает):
--create table #test
--(
-- id int identity,
-- category varchar(10)
--)
--go
--insert #test values ('A')
--insert #test values ('B')
--insert #test values ('C')
declare @category varchar(10)
set @category = 'D'
select
id, category
from #test
where category = @category
union
select
0, ''
from #test
where @@rowcount = 0
Ответы
Ответ 1
Это старый вопрос, но у меня была такая же проблема.
Решение действительно просто БЕЗ двойного выбора:
select top(1) WITH TIES * FROM (
select
id, category, 1 as orderdummy
from #test
where category = @category
union select 0, '', 2) ORDER BY orderdummy
с помощью "WITH TIES" вы получаете ВСЕ строки (все они имеют 1 как "orderdummy", поэтому все являются связями), или если результата нет, вы получаете свое значение по умолчанию.
Ответ 2
Очень мало вариантов, которых я боюсь.
Вы всегда должны прикоснуться к таблице дважды, будь то COUNT, EXISTS before, EXISTs в разделе UNION, TOP и т.д.
select
id, category
from mytable
where category = @category
union all --edit, of course it quicker
select
0, ''
where NOT EXISTS (SELECT * FROM mytable where category = @category)
Решение EXISTS лучше, чем COUNT, потому что оно остановится, когда найдет строку. COUNT будет пересекать все строки, чтобы их действительно считать
Ответ 3
Вы можете использовать полное внешнее соединение. Что-то из-за...
declare @category varchar(10)
set @category = 'D'
select #test.id, ISNULL(#test.category, @category) as category from (
select
id, category
from #test
where category = @category
)
FULL OUTER JOIN (Select @category as CategoryHelper ) as EmptyHelper on 1=1
В настоящее время, тестируя этот сценарий, я не уверен, какое влияние это будет иметь, но это даст вам пустую строку с заполненной категорией.
Ответ 4
Это ответ @swe, только отформатированный лучше.
CREATE FUNCTION [mail].[f_GetRecipients]
(
@MailContentCode VARCHAR(50)
)
RETURNS TABLE
AS
RETURN
(
SELECT TOP 1 WITH TIES -- returns all rows having highest priority found
[To],
CC,
BCC
FROM (
SELECT
[To],
CC,
BCC,
1 AS Priority -- if no rows, priority 2 under UNION will get returned
FROM mail.Recipients
WHERE 1 = 1
AND IsActive = 1
AND MailContentCode = @MailContentCode
UNION ALL
SELECT
*
FROM (VALUES
(N'[email protected]', NULL, NULL, 2),
(N'[email protected]', NULL, NULL, 2)
) defaults([To], CC, BCC, Priority)
) emails
ORDER BY Priority
)
Ответ 5
Я думаю, вы могли бы попробовать:
Declare @count int
set @count = 0
Begin
Select @count = Count([Column])
From //Your query
if(@Count = 0)
select 0
else //run your query
Недостатком является то, что вы эффективно выполняете свой запрос дважды, а вверху - то, что вы пропускаете таблицу temp.
Ответ 6
Чтобы избежать дублирования запроса выбора, как насчет таблицы temp для сохранения результата запроса? И на основе временной таблицы возвращайте строку по умолчанию, если таблица temp пуста или возвращает temp, когда она имеет результат?