Tabellenwertparameter als Ausgabeparameter für gespeicherte Prozeduren

33

Ist es möglich, einen Tabellenwert-Parameter als Ausgabeparameter für eine gespeicherte Prozedur zu verwenden?

Hier ist, was ich in Code tun möchte

/*First I create MY type */
CREATE TYPE typ_test AS TABLE 
(
     id int not null
    ,name varchar(50) not null
    ,value varchar(50) not null
    PRIMARY KEY (id)
)
GO


--Now I want to create stored procedu whic is going to send output type I created, 
--But it looks like it is inpossible, at least in SQL2008
create  PROCEDURE [dbo].sp_test
         @od datetime 
        ,@do datetime 
        ,@poruka varchar(Max) output
        ,@iznos money output 
        ,@racun_stavke  dbo.typ_test   READONLY --Can I Change READONLY with OUTPUT ?
AS
BEGIN
    SET NOCOUNT ON;

    /*FILL MY OUTPUT PARAMS AS I LIKE */


    end
Adopilot
quelle

Antworten:

35

Nein, Tabellenwertparameter können leider nur gelesen und eingegeben werden. Dieses Thema wird im Allgemeinen in Freigeben von Daten zwischen gespeicherten Prozeduren , in dem alle Alternativen aufgeführt sind, sehr gut behandelt . Meine Empfehlung wäre, eine #tempTabelle zu verwenden.

Remus Rusanu
quelle
1

Dies ist ein älterer Beitrag, der sich jedoch fast oben befand, als ich nach "Tabellenwert-Parameter als Ausgabeparameter für gespeicherte Prozeduren" suchte. Nach meinem Verständnis können Sie keinen Tabellenwert-Parameter als Ausgabeparameter übergeben. Ich würde mir jedoch vorstellen, dass das Ziel darin besteht, diesen Tabellenwert-Ausgabeparameter in einer anderen Prozedur als Tabellenwert-Eingabeparameter zu verwenden. Ich werde ein Beispiel dafür zeigen, wie ich diese Arbeit gemacht habe.

Erstellen Sie zunächst einige Daten, mit denen Sie arbeiten möchten:

create table tbl1
(
id int,
fname varchar(10),
gender varchar(10)
);
create table tbl2
(
id int,
lname varchar(10)
);
insert into tbl1
values
(1,'bob'  ,'m'),
(2,'tom'  ,'m'),
(3,'sally','f')
;
insert into tbl2
values
(1,'jones'   ),
(2,'johnson' ),
(3,'smith'   )
;

Erstellen Sie als Nächstes eine gespeicherte Prozedur, um einige der Daten zu erfassen. Normalerweise versuchen Sie hier einen tabellenwertigen Ausgabeparameter zu erstellen.

create procedure usp_OUTPUT1
 @gender varchar(10)
as
Begin
    select id from tbl1 where gender = @gender
End

Darüber hinaus möchten Sie einen Datentyp (Tabellentyp) erstellen, in dem die Daten der ersten gespeicherten Prozedur als Eingabeparameter für die nächste gespeicherte Prozedur übergeben werden können.

create type tblType as Table (id int)

Erstellen Sie als Nächstes die zweite gespeicherte Prozedur, die den Tabellenwertparameter akzeptiert.

create procedure usp_OUTPUT2
@tblType tblType readonly  --referencing the type created and specify readonly
as
begin
 select lname from tbl2 where id in (select id from @tblType)
end

Zugegeben, dies ist kein echter tabellenwertiger Ausgabeparameter, aber er wird wahrscheinlich ähnliche Ergebnisse liefern wie Sie. Deklarieren Sie Ihren tabellenwertigen Parameter, füllen Sie ihn mit Daten, indem Sie die gespeicherte Prozedur ausführen, und verwenden Sie ihn dann als Eingabevariable für die nächste Prozedur.

Declare @tblType tblType 
insert into @tblType execute usp_OUTPUT1 'm'
execute usp_OUTPUT2 @tblType
Andrew
quelle
1

neben der nett gestellten antwort von remus inklusive des von ihm zur verfügung gestellten links

Freigeben von Daten zwischen gespeicherten Prozeduren

Es gibt Situationen, in denen die folgenden Fehlermeldungen angezeigt werden, wenn die Ergebnisse einer gespeicherten Prozedur in einer Tabelle gespeichert werden:

Eine INSERT EXEC-Anweisung kann nicht verschachtelt werden.

Die aktuelle Transaktion kann nicht festgeschrieben werden und unterstützt keine Vorgänge, die in die Protokolldatei schreiben. Machen Sie die Transaktion rückgängig

und wenn dies auf meinen eigenen gespeicherten Prozeduren geschieht, die ich für meinen eigenen Gebrauch entwickle

Zum Beispiel ein Tool, mit dem ich von loginallen zugehörigen AD-Gruppen und deren Berechtigungen in allen Datenbanken auf einem Server erfahren kann

Ich erstelle eine temporäre Tabelle außerhalb der Prozedur und übergebe ihren Namen als Parameter

--===============
-- this way below it works, by passing a temp table as a parameter
--===============

                if OBJECT_ID('tempdb.dbo.#my_table') IS NOT NULL
                   DROP TABLE #my_table

                CREATE TABLE #my_table(
                    db nvarchar(128)   COLLATE Latin1_General_CI_AS  NULL,
                   permission_type nvarchar(128)   COLLATE Latin1_General_CI_AS  NULL,
                    login_  nvarchar(128)   COLLATE Latin1_General_CI_AS  NULL,
                    role_  nvarchar(128)   COLLATE Latin1_General_CI_AS  NULL,
                    Obj    nvarchar(517)   COLLATE Latin1_General_CI_AS  NULL,
                    Permission nvarchar(128)   COLLATE Latin1_General_CI_AS  NULL,
                    script nvarchar(1008)  COLLATE Latin1_General_CI_AS  NULL
                ) 

                exec sp_GetLoginDBPermissionsX 
                    @Login='my_loginname', 
                    @debug=0,
                    @where_to_save ='#my_table'

                select *
                from #my_table

Nach all den Berechnungen überprüfe ich bei der Rückgabe der endgültigen Daten (unter einem Beispiel), ob die Ausgabe in einer Tabelle oder nur auf dem Bildschirm erfolgt, und erstelle das Skript dynamisch.

            select @sql = case when @where_to_save IS not null then 
            '
            insert into ' + @where_to_save + '(db,Permission_Type,login_,role_,obj,Permission,script) '
            else '' end + 
'
        SELECT 
            J.db,
            J.Permission_Type,
            J.login_,
            J.role_,
            J.Obj,
            J.Permission,
            J.script
        FROM #tablewithpermissions J
        WHERE J.login_ IN ( SELECT  L1.LOGIN_FROM COLLATE Latin1_General_CI_AS FROM #logins L1)
           OR J.role_ IN  ( SELECT  L1.LOGIN_FROM COLLATE Latin1_General_CI_AS FROM #logins L1)
       ORDER BY J.DB, J.[permission_order]
'
        --print(@sql)

        EXEC(@SQL)

Danach haben Sie entweder die Informationen, die Sie auf dem Bildschirm benötigen, oder wenn Sie eine temporäre Tabelle als Parameter übergeben haben, werden die Daten jetzt angezeigt.

Dies ist eine Lösung, die ich gefunden habe, aber ich verwende sie nur für meine eigenen Werke, DBAda dies sonst als hohes Risiko für SQL Injection angesehen wird .

Marcello Miorelli
quelle