IF-Abfragen in SELECT-Statement
-
Tabellen anlegen ist keine Option.
Ich dachte an soetwas:GetText(A, B, C) { if !A and !B and !C return String1 ... } SELECT GetText(A, B, C) AS WantedText From ...
Also im Grunde sowas wie ne stored procedure, nur dass sie eben nicht stored sein soll, sondern direkt im SQL-Query.
-
So, habe jetzt herausgefunden, dass sich das wohl User Defined Function nennt.
Leider bekomme ich sie nicht hin
-
mit welcher Datenbank arbeitest du eigentlich?
-
Mit dem MSSQL Server 2005.
Habe es jetzt hinbekommen:
SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER OFF GO CREATE FUNCTION GetStatusText ( @A bit, @B bit, @C bit ) RETURNS varchar(255) AS BEGIN DECLARE @ResultVar varchar(255) if @A = 0 AND @B = 0 AND @C IS NULL SELECT @ResultVar = "String1" else if @A = 1 AND @B = 0 AND @C IS NULL SELECT @ResultVar = "String2" else if @A = 1 AND @B = 0 AND @C = 1 SELECT @ResultVar = "String3" else if @A = 0 AND @B = 0 AND @C = 1 SELECT @ResultVar = "String4" else if @A = 0 AND @B = 1 AND @C = 1 SELECT @ResultVar = "String5" else SELECT @ResultVar = "Invalid!" -- Return the result of the function RETURN @ResultVar END GO
Allerdings weiß ich nciht, ob das auch mit dem MSSQL-Server 2000 tut... Weiß jemand, ob sich da was geändert hat?
-
Ja die Funktionen sind nicht neu. Auch SQL-Server 2000 beherrscht sowas schon.
Im speziellen Fall halte ich das aber für ... na ja sagen wir mal suboptimal.
Estens geht's mit einer Case-Anweisung in einem einfachen Select auch. Und Du mußt nicht jedesmal die Funktion ändern, um die Werte der Strings zu ändern.
Zweitens könnte man hier auch ideal eine weitere Tabelle damit abfragen.
Die Funktion ist eher das Beheben eines Konstruktionsfehlers von hinten durch die Brust ins Auge.
Ach so. Deine Funktion hat noch einen kleinen Konstuktionsfehler. Du gehst von ohne Where-Bedingung von einer Tabelle mit einem ROW (Dastensatz) aus.
Was glaubst Du, gibt Deine Funktion zurück, wenn Du mehr als einen eintrag hast?
-
Der Case im Select wäre mir sehr viel lieber: How to?
Und zu der anderen Sache:
ich rufe das ganze so auf:
SELECT GetStatusText(Table.A, Table.B, Table.C) AS Status FROM Table WHERE xyz
Tut so wie es soll.
-
Also von hinten nach vorn. Du benutzt die Funktion ja bur innerhalb eines Selects's mit Where-Teil, sorgst also dafür, daß wirklich nur ein Row Werte übergeben wird. Laß mal den Where-Teil weg, dann siehst Du was ich meine.
Zum Case -> ist ganz simpel:
select CASE WHEN Table.A = 0 and Table.B = 0 and Table.C = 0 THEN "String1" WHEN Table.A = 1 and Table.B = 0 and Table.C IS NULL THEN "String2" WHEN Table.A = 1 and Table.B = 0 and Table.C = 1 THEN "String3" WHEN Table.A = 0 AND Table.B = 0 AND Table.C = 1 THEN "String4" WHEN Table.A = 0 AND Table.B = 1 AND Table.C = 1 "String5" ELSE "Invalid!" END AS Status FROM Table WHERE xyz
Allerdings bin ich immer noch der Meinung, daß das perfekt in in eine weitere Tabelle (notfalls auch View) paßt.
-
Hi Caspar,
Danke für deine Antwort.
Die Sache mit der Row verstehe ich wohl nicht so ganz. Meine Abfrage liefert nicht nur eine Ergebniszeile zurück, sondern mehrere.Das DB-Layout darf ich nicht verändern.
-
Wenn mehrere Row OK sind, dann isrt ja alles gut.
Das DB-Layout änderst Du doch auch mit einer eigenen Funktion. Solltest Du z.B. weitere Mandanten auf weiteren (bisher gleichen) DB's haben, so mußt Du auch dort die entsprechende Funktion einrichten.
-
Die Funktion einzurichten ist sehr viel einfacher, als ein bereits vorhandenes DB-Layout zu ändern und dabei vorhandene Daten konvertieren zu müssen.
Aber ich mache es jetzt mit dem Select, das ist schliesslich das, was ich von Anfang an wollte