it-swarm.com.de

Tabellenwertparameter als Ausgabeparameter für die gespeicherte Prozedur

Ist es möglich, den Parameter Table-Valued als Ausgabeparameter für die gespeicherte Prozedur zu verwenden?

Hier ist, was ich im 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
33
adopilot

Nein, leider sind Tabellenwertparameter schreibgeschützt und werden nur eingegeben. Dieses Thema wird im Allgemeinen sehr gut in Freigeben von Daten zwischen gespeicherten Prozeduren behandelt, in dem alle Alternativen vorgestellt werden. Meine Empfehlung wäre, eine #temp - Tabelle zu verwenden.

36
Remus Rusanu

Dies ist ein älterer Beitrag, der sich jedoch ganz oben befand, als ich nach "Tabellenwertparameter als Ausgabeparameter für gespeicherte Prozeduren" suchte. Nach meinem Verständnis können Sie einen tabellenwertigen Parameter nicht als Ausgabeparameter übergeben, aber ich würde mir vorstellen, dass das Ziel darin besteht, diesen tabellenwertigen Ausgabeparameter als tabellenwertigen Eingabeparameter in einer anderen Prozedur 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 Ausgabeparameter mit Tabellenwert zu erstellen.

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

Außerdem 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 Parameter mit Tabellenwert 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 Tabellenwert-Ausgabeparameter, aber es wird wahrscheinlich ähnliche Ergebnisse liefern, wie Sie es sich wünschen würden. 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
1
Andrew

zusätzlich zu die schön formulierte Antwort von remus einschließlich des von ihm bereitgestellten Links

So teilen Sie Daten zwischen gespeicherten Prozeduren

es gibt Situationen, in denen beim Speichern der Ergebnisse einer gespeicherten Prozedur in einer Tabelle die folgenden Fehlermeldungen angezeigt 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. Setzen Sie die Transaktion zurück.

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

zum Beispiel ein Tool, mit dem Sie von einem login alle AD-Gruppen, zu denen es gehört, und alle ihre Berechtigungen in allen Datenbanken auf einem Server unterscheiden können

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

und innerhalb der Prozedur überprüfe ich nach all den Berechnungen, wenn ich die endgültigen Daten zurückgebe (unter einem Beispiel), ob wir in eine Tabelle oder nur zurück auf den Bildschirm ausgeben, 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 diese jetzt angezeigt.

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

1