it-swarm.com.de

Fügen Sie eine leere Zeile hinzu, wenn keine Ergebnisse gefunden wurden

Ich schreibe gespeicherte Prozeduren, die von einem Altsystem aufgerufen werden. Eine der Einschränkungen des Altsystems besteht darin, dass sich in der einzelnen Ergebnismenge mindestens eine Zeile befinden muss, die von der gespeicherten Prozedur zurückgegeben wird. Der Standard ist, eine Null in der ersten Spalte zurückzugeben (ja, ich weiß!).

Der naheliegendste Weg, dies zu erreichen, ist das Erstellen einer temporären Tabelle, das Einfügen der Ergebnisse, das Testen auf Zeilen in der temporären Tabelle und entweder die Rückgabe der Ergebnisse aus der temporären Tabelle oder das einzelne leere Ergebnis.

Eine andere Möglichkeit besteht darin, ein EXISTS-Objekt gegen dieselbe where-Klausel auszuführen, die in der Hauptabfrage enthalten ist, bevor die Hauptabfrage ausgeführt wird.

Keines davon ist sehr befriedigend. Kann sich jemand einen besseren Weg vorstellen? Ich dachte an eine UNION-Art wie diese (ich bin mir bewusst, dass das nicht funktioniert):

--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
20
Chris Simpson

Es ist eine alte Frage, aber ich hatte das gleiche Problem. Die Lösung ist sehr einfach, OHNE doppelte Auswahl:

select top(1) WITH TIES * FROM (
select
id, category, 1 as orderdummy
from #test
where category = @category
union select 0, '', 2) ORDER BY orderdummy

bei "WITH TIES" erhalten Sie ALLE Zeilen (alle haben eine 1 als "Orderdummy", also alle sind Unentschieden), oder wenn es kein Ergebnis gibt, erhalten Sie Ihre Defaultrow.

10
swe

Sehr wenige Optionen fürchte ich.

Sie müssen die Tabelle immer zweimal berühren, ob COUNT, EXISTS before, EXISTs in UNION, TOP-Klausel etc

select
    id, category
from mytable
where category = @category
union all --edit, of course it's quicker
select
    0, ''
where NOT EXISTS (SELECT * FROM mytable where category = @category)

Eine EXISTS-Lösung ist besser als COUNT, da sie stoppt, wenn eine Zeile gefunden wird. COUNT durchläuft alle Zeilen, um sie tatsächlich zu zählen

28
gbn

Dies ist @subs Antwort, nur besser formatiert.

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
)
2
ensisNoctis

Sie können einen vollständigen äußeren Join verwenden. Etwas zur Wirkung von ...

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   

Derzeit wird dieses Szenario von der Leistung selbst getestet. Ich bin mir nicht sicher, welche Auswirkungen dies haben würde, aber es wird Ihnen eine leere Zeile geben, in der die Kategorie ausgefüllt ist. 

2
Andrew Jansen

Wie wäre es mit einer temporären Tabelle, um das Abfrageergebnis zuerst zu speichern, um ein Duplizieren der Auswahlabfrage zu vermeiden? Und basierend auf der temporären Tabelle, die Standardzeile zurückgeben, wenn die temporäre Tabelle leer ist, oder die temporäre Tabelle zurückgeben, wenn sie das Ergebnis hat?

0
JieLi

Ich denke, du könntest es versuchen:

Declare @count int
set @count = 0

Begin
Select @count = Count([Column])
From //Your query

if(@Count = 0) 
   select 0
else //run your query

Der Nachteil ist, dass Sie Ihre Abfrage effektiv zweimal ausführen. Die Nachteil ist, dass Sie die temporäre Tabelle überspringen.

0
AllenG