webentwicklung-frage-antwort-db.com.de

SQL Server-Ausgabeparameterproblem

Ich verwende SQL Server 2008 Enterprise. Ich lerne den OUTPUT-Parameter der gespeicherten Prozedur von SQL Server. Beispielsweise hat die gespeicherte Prozedur sp_add_jobschedule einen OUTPUT-Parameter mit dem Namen schedule_id.

http://msdn.Microsoft.com/de-de/library/ms366342.aspx

Meine Verwirrung ist, es sieht so aus, als könnte der Parameter OUTPUT einen Eingabewert liefern und gibt auch einen Wert zurück. Hat das Verhalten des Parameters INPUT und OUTPUT? Darf kein INPUT-Wert für den OUTPUT-Parameter angegeben werden (damit er wie ein reines Ausgabeparameter-Verhalten aussieht)?

32
George2

Die Verwirrung ist bis zu einem gewissen Grad gerechtfertigt - und andere RDBMS wie Oracle verfügen über gespeicherte Prozedurparameter, die vom Typ IN (nur Eingabe), OUT (nur Ausgabe) oder INOUT (beide Arten) sein können. .

SQL Server ist hier etwas schlampig, da er den Parameter als OUTPUT bezeichnet. Dies bedeutet jedoch INPUT/OUTPUT. Im Grunde bedeutet dies lediglich, dass die gespeicherte Prozedur die Möglichkeit hat, einen Wert aus ihrem Aufruf in diesem Parameter zurückzugeben.

Also ja - obwohl er OUTPUT-Parameter heißt, handelt es sich wirklich eher um einen INPUT/OUTPUT-Parameter, und diese IN, INOUT, OUT-Dateien sind in SQL Server (in T-SQL) nicht vorhanden.

60
marc_s

Ich kann Ihnen ein kurzes Beispiel geben, wie Sie eine gespeicherte Prozedur mit Ausgabeparametern erstellen.

CREATE PROCEDURE test_proc

@intInput int,
@intOutput int OUTPUT

AS
set @intOutput = @intInput + 1 

go

Um diese Prozedur aufzurufen und dann den Ausgabeparameter zu verwenden, gehen Sie wie folgt vor:

declare @intResult int
exec test_proc 3 ,@intResult OUT
select @intResult

Sie sehen, dass Sie zuerst die Ausgangsvariable deklarieren sollten. Nach der Ausführung der gespeicherten Prozedur befindet sich der Ausgabewert in Ihrer Variablen. Sie können einen beliebigen Wert für Ihre Ausgabevariable festlegen. Nach der Ausführung der gespeicherten Prozedur wird jedoch genau angegeben, welche gespeicherte Prozedur zurückgegeben wird (unabhängig davon, welcher Wert in der Ausgabevariable enthalten war).

Zum Beispiel:

declare @intResult int
exec test_proc 3 ,@intResult OUT
select @intResult

Es wird 4 zurückkehren. Und:

declare @intResult int
set @intResult = 8
exec test_proc 3 ,@intResult OUT
select @intResult

Zurück auch 4.

19
Sergey Olontsev

Ja, Sie können einen OUTPUT-Parameter zum Übergeben und Abrufen von Werten verwenden (obwohl mir derzeit kein guter Grund dafür einfällt).

Hier ist ein triviales Beispiel, das dies demonstriert:

-- The stored procedure
CREATE PROCEDURE OutParamExample
    @pNum int OUTPUT
AS
BEGIN
    select @pNum
    set @pNum = @pNum + 5
END
GO

-- use a local variable to retrieve your output param value
declare @TheNumber int
set @TheNumber = 10

print @TheNumber
exec OutParamExample @TheNumber OUTPUT
print @TheNumber

Die Ergebnisse werden wie folgt aussehen:

10

-----------
10

(1 row(s) affected)

15

BEARBEITEN: OK, ich glaube, ich habe im zweiten Absatz ein "nicht" verpasst und die Frage, die Sie gestellt haben, möglicherweise nicht beantwortet. Wenn Sie einen strikten Ausgabeparameter wünschen (z. B. einen Rückgabecode), müssen Sie der als Ausgabeparameter übergebenen lokalen Variablen sicherlich kein value angeben. Sie müssen diese lokale Variable jedoch trotzdem deklarieren dass Sie auf den zurückgegebenen Wert außerhalb des Bereichs der Prozedur selbst zugreifen können.

Zum Beispiel:

declare @LocalNumber int
-- I don't have to assign a value to @LocalNumber to pass it as a parameter
exex OutParamExample @LocalNumber OUTPUT  
-- (assume SP has been altered to assign some reasonable value)

-- but I do have to declare it as a local variable so I can get to
-- the return value after the stored procedure has been called
print @LocalNumber
6
Matt

Zusätzlich zu dem, was andere oben gesagt haben, können OUTPUT-Parameter sowohl als INPUT als auch als OUTPUT fungieren. Es hängt jedoch von der gespeicherten Prozedur ab, den an sie übergebenen Wert zu verwenden.

Wenn die gespeicherten Prozeduren den für den OUTPUT-Parameter übergebenen Wert ignorieren (was normalerweise der Fall sein sollte), wird der INPUT-Wert trotzdem ignoriert.

Mit dem Code von Sergey kann ich den für @intOutput übergebenen Wert verwenden (falls erforderlich).

create PROCEDURE test_proc

@intInput int,
@intOutput int OUTPUT

AS
set @intOutput = @intOutput + 1 

go

Dies widerspricht jedoch dem Zweck des Parameters OUTPUT.
Um eine andere Ansicht zu erhalten, zwingt Sie der c # -Compiler, den Wert des Out-Parameters durch Zuweisung zu überschreiben (ohne den Ausgabeparameter zu verwenden).

z.B. Ich kann das nicht in c # machen. Hier handelt es sich nur um einen Out-Parameter (d. H. Den von dieser Funktion übergebenen Wert ignorieren).

static void dosomething(out int i)
{
    //i = 0;
    i = i + 1;
}
3
shahkalpesh

Die Frage ist - Warum möchten Sie die Eingabe von Informationen verbieten? Das macht überhaupt keinen Sinn. Betrachten Sie dieses einfache Beispiel:

CREATE PROCEDURE test (@param AS INT OUTPUT) AS
BEGIN
  SET @param = 100
END
GO

DECLARE @i INT
SET @i = 0

EXECUTE test @i OUTPUT
PRINT @i

DROP PROCEDURE test

Dies druckt

100

Sehen Sie - wie sollen Sie einen Wert out erhalten, wenn Sie nicht zuerst eine Variable in eingeben?

2
Tomalak

Denken Sie an OUTPUT-PARAMETER, die in Programmiersprachen als Referenz übergeben werden, es ist dasselbe. Das beste Beispiel, an das ich jetzt denken kann, ist die Rückgabe des Fehlercodes. Sie möchten etwas einfügen ... Wenn Sie den Rückkehrcode aus dem SP auswählen, müssen Sie ihn in Ihrem Code zurückholen. Wenn Sie den Parameter OUTPUT nicht haben, wird er bereits in Ihrem Parameter enthalten (ich meine mit C # -Befehle, PHP init gespeicherte proc-Methoden oder etwas anderes als das Erstellen von Strings

2

Eine zusätzliche Anmerkung zu einem Teil der ursprünglichen Frage:

"Darf" INPUT-Werte für den OUTPUT-Parameter (..) nicht angegeben werden? "

In SQLServer ist es möglich, einen Standardwert für einen OUTPUT-Parameter anzugeben (auf den eigentlich INOUT hingewiesen wurde). Betrachten Sie das folgende Beispiel, in dem Sie einen expliziten Wert angeben oder die Funktion selbst eine ID generieren lassen. 

CREATE PROCEDURE test (@id uniqueidentifier = NULL OUTPUT) AS
BEGIN
  IF @id IS NULL SET @id = NEWID()
  -- INSERT INTO xyz (...) VALUES (@id, ...)
  PRINT 'Insert with id: ' + CAST (@id as nvarchar(36))
END
GO

DECLARE @insertedId uniqueidentifier
EXECUTE test '00000000-0000-0000-0000-000000000000'
EXECUTE test @insertedId OUTPUT
PRINT @insertedId

DROP PROCEDURE test

Dies druckt

Insert with id: 00000000-0000-0000-0000-000000000000
Insert with id: 67AE3D27-8EAB-4301-B384-30EEA1488440
67AE3D27-8EAB-4301-B384-30EEA1488440
2
blueling

Zwei andere Dinge, die ich anmerken möchte, sind:

1) Sie können mehrere Parameter als OUTPUT übergeben.

2) Sie müssen die Parameter nicht mit OUTPUT aufrufen, wenn Sie die Ergebnisse nicht wünschen

CREATE PROCEDURE ManyOutputs @a int, @b int output, @c varchar(100) output, @d bit output
AS
BEGIN
    SET @b = @a + 11
    SET @c = 'The Value of A is ' + CAST(@a AS varchar(5)) + ', and the value of B is ' + CAST(@b AS varchar(5))
    IF (@a % 2 = 1)
        SET @d = 1
    ELSE
        SET @d = 0
END
GO

Aufruf dieser Routine:

DECLARE @bVal int
DECLARE @cVal varchar(100)
DECLARE @dVal bit

EXEC ManyOutputs 1, @bVal, @cVal, @dVal
SELECT @bVal AS bVal, @cVal as cVal, @dVal as dVal

Gibt NULL, NULL, NULL zurück

EXEC ManyOutputs 2, @bVal OUT, @cVal OUT, @dVal OUT
SELECT @bVal AS bVal, @cVal as cVal, @dVal as dVal

Gibt 13 zurück, "Der Wert von A ist 2 und der Wert von B ist 13", 0

EXEC ManyOutputs 3, @bVal, @cVal, @dVal
SELECT @bVal AS bVal, @cVal as cVal, @dVal as dVal

Gibt 13 zurück, "Der Wert von A ist 2 und der Wert von B ist 13", 0

(Das gleiche wie beim letzten Aufruf, da wir mit OUTPUT keine neuen Werte abgerufen haben, sodass die alten Werte beibehalten wurden.) 

EXEC ManyOutputs 5, @bVal OUT, @cVal OUT, @dVal OUT
SELECT @bVal AS bVal, @cVal as cVal, @dVal as dVal

Gibt 16 zurück, "Der Wert von A ist 5 und der Wert von B ist 16", 1

0
Dan