Ich habe eine gespeicherte Prozedur, die eine Reihe von Eingabe- und Ausgabeparametern enthält, da Werte in mehrere Tabellen eingefügt werden. In einigen Fällen wird der gespeicherte Prozess nur in eine einzelne Tabelle eingefügt (abhängig von den Eingabeparametern). Hier ist ein nachgebildetes Szenario zur Veranschaulichung.
Tabellen / Datenobjekte:
Person
Id
Name
Address
Name
Id
FirstName
LastName
Adresse
Id
Country
City
Angenommen, ich habe eine gespeicherte Prozedur, die eine Person einfügt. Wenn die Adresse nicht vorhanden ist, werde ich sie nicht zur Address
Tabelle in der Datenbank hinzufügen .
Wenn ich also den Code zum Aufrufen der gespeicherten Prozedur generiere, möchte ich den Address
Parameter nicht hinzufügen . Für INPUT
Parameter ist dies in Ordnung, da ich mit SQL Server Standardwerte angeben kann. Aber für den OUTPUT
Parameter, was mache ich in der gespeicherten Prozedur, um ihn optional zu machen, damit ich keinen Fehler erhalte ...
Prozedur oder Funktion 'Person_InsertPerson' erwartet den Parameter '@AddressId', der nicht angegeben wurde.
NULL
Sie sich entscheiden,@AddressId
wenn eine Adresse nicht existiert, ohne einen Zweig zu verwenden?"Antworten:
Sowohl Eingabe- als auch Ausgabeparameter können Standardeinstellungen zugewiesen werden. In diesem Beispiel:
CREATE PROCEDURE MyTest @Data1 int ,@Data2 int = 0 ,@Data3 int = null output AS PRINT @Data1 PRINT @Data2 PRINT isnull(@Data3, -1) SET @Data3 = @Data3 + 1 RETURN 0
Der erste Parameter ist erforderlich, und der zweite und dritte sind optional. Wenn sie nicht von der aufrufenden Routine festgelegt werden, werden ihnen die Standardwerte zugewiesen. Probieren Sie es und die folgende Testaufrufroutine in SSMS mit verschiedenen Werten und Einstellungen aus, um zu sehen, wie alles zusammenarbeitet.
DECLARE @Output int SET @Output = 3 EXECUTE MyTest @Data1 = 1 ,@Data2 = 2 ,@Data3 = @Output output PRINT '---------' PRINT @Output
quelle
@var INT OUTPUT = NULL
- die Syntax ist verwirrend.Ausgabeparameter und Standardwerte funktionieren nicht gut zusammen! Dies ist aus SQL 10.50.1617 (2008 R2). Lassen Sie sich nicht täuschen, wenn Sie glauben, dass dieses Konstrukt
SET
in Ihrem Namen auf magische Weise einen Wert hat (wie es mein Kollege getan hat)!Dieses "Spielzeug" SP fragt den
OUTPUT
Parameterwert ab, ob es sich um den Standardwert handelt oder nichtNULL
.CREATE PROCEDURE [dbo].[omgwtf] (@Qty INT, @QtyRetrieved INT = 0 OUTPUT) AS IF @QtyRetrieved = 0 BEGIN print 'yay its zero' END IF @QtyRetrieved is null BEGIN print 'wtf its NULL' END RETURN
Wenn Sie einen nicht initialisierten Wert (dh
NULL
) für das sendenOUTPUT
, sind Sie wirklichNULL
in den SP gelangt und nicht0
. Sinnvoll, für diesen Parameter wurde etwas übergeben.declare @QR int exec [dbo].[omgwtf] 1, @QR output print '@QR=' + coalesce(convert(varchar, @QR),'NULL')
Ausgabe ist:
Wenn wir eine explizite
SET
vom Anrufer hinzufügen, erhalten wir:declare @QR int set @QR = 999 exec [dbo].[omgwtf] 1, @QR output print '@QR=' + coalesce(convert(varchar, @QR),'NULL')
und die (nicht überraschende) Ausgabe:
Auch hier ist es sinnvoll, einen Parameter zu übergeben und SP hat keine explizite Aktion für
SET
einen Wert ausgeführt.Fügen Sie einen
SET
derOUTPUT
Parameter im SP hinzu (wie Sie es tun sollen), aber legen Sie nichts vom Aufrufer fest:ALTER PROCEDURE [dbo].[omgwtf] (@Qty INT, @QtyRetrieved INT = 0 OUTPUT) AS IF @QtyRetrieved = 0 BEGIN print 'yay its zero' END IF @QtyRetrieved is null BEGIN print 'wtf its NULL' END SET @QtyRetrieved = @Qty RETURN
Jetzt, wenn ausgeführt:
declare @QR int exec [dbo].[omgwtf] 1234, @QR output print '@QR=' + coalesce(convert(varchar, @QR),'NULL')
Die Ausgabe ist:
Dies ist das "Standard" -Verhalten für die
OUTPUT
Parameterbehandlung in SPs.Nun zum Plot Twist : Die einzige Möglichkeit, den Standardwert zum "Aktivieren" zu erhalten, besteht darin , den
OUTPUT
Parameter überhaupt nicht zu übergeben , was meiner Meinung nach wenig Sinn macht: Da er alsOUTPUT
Parameter eingerichtet ist, würde dies bedeuten, etwas "Wichtiges" zurückzugeben. das sollte gesammelt werden.declare @QR int exec [dbo].[omgwtf] 1 print '@QR=' + coalesce(convert(varchar, @QR),'NULL')
gibt diese Ausgabe:
Dies erfasst jedoch nicht die SP-Ausgabe, vermutlich zunächst den Zweck dieses SP.
IMHO ist diese Feature-Kombination ein zweifelhaftes Konstrukt, das ich als Code-Geruch betrachten würde (Puh !!)
quelle
OUTPUT
Parametern für die Eingabe? Warum nicht diese Eingabewerte als "reguläre" Parameter übergeben?OUTPUT
Parameter c / sh / aus zwei Gründen als schlechte Idee angesehen werden kann: 1. Ideologischer / Code-Geruch und 2. Praktische Gründe aufgrund des hier gefundenen Verhaltens. ¯ \ _ (ツ) _ / ¯Sieht so aus, als könnte ich dem
OUTPUT
Parameter einfach einen Standardwert hinzufügen, z.Scheint in Bezug auf die Lesbarkeit schlecht zu sein, da dies
AddressId
ausschließlich alsOUTPUT
Variable gedacht ist. Aber es funktioniert. Bitte lassen Sie mich wissen, wenn Sie eine bessere Lösung haben.quelle
Hinzufügen zu dem, was Philip gesagt hat:
Ich hatte eine gespeicherte Prozedur in meiner SQL Server-Datenbank, die wie folgt aussah:
Und ich habe es von meinem .net-Code wie folgt aufgerufen:
Ich habe eine System.Data.SqlClient.SqlException erhalten: Prozedur oder Funktion erwartet den Parameter '@current_phase', der nicht angegeben wurde.
Ich benutze diese Funktion auch irgendwo anders in meinem Programm und übergebe einen Parameter und behandle den ausgegebenen. Damit ich den aktuellen Aufruf nicht ändern musste, habe ich nur die gespeicherte Prozedur geändert, um den Ausgabeparameter ebenfalls optional zu machen.
So sieht es jetzt aus:
quelle
Da Sie eine gespeicherte Prozedur und keine SQL-Anweisung ausführen, müssen Sie den Befehlstyp Ihres SQL-Befehls auf Gespeicherte Prozedur setzen:
Von hier genommen .
Sobald Sie diesen Fehler behoben haben, können Sie die SQL-
nvl()
Funktion in Ihrer Prozedur verwenden, um anzugeben, was angezeigt werden soll, wenn ein NULL-Wert auftritt.Tut mir leid, dass ich die Frage nicht richtig beantwortet habe ... muss dich missverstanden haben. Hier ist ein Beispiel für nvl, das meiner Meinung nach etwas besser angesprochen werden könnte.
select NVL(supplier_city, 'n/a') from suppliers;
Die obige SQL-Anweisung würde 'n / a' zurückgeben, wenn das
supplier_city
Feld einen Nullwert enthält. Andernfalls würde dersupplier_city
Wert zurückgegeben.quelle