it-swarm.it

Parametro con valori di tabella come parametro di output per la procedura memorizzata

È possibile utilizzare il parametro con valori di tabella come parametro di output per la procedura memorizzata?

Ecco cosa voglio fare nel codice

/*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

No, purtroppo i parametri del valore della tabella sono di sola lettura e solo di input. Questo argomento in generale è trattato molto bene in Come condividere i dati tra le procedure memorizzate , che presenta tutte le alternative. La mia raccomandazione sarebbe di usare un #temp tavolo.

36
Remus Rusanu

Questo è un post più vecchio, ma era quasi all'inizio quando stavo cercando "Parametro a valori di tabella come parametro di output per la procedura memorizzata". Mentre intendo che non è possibile passare un parametro con valori di tabella come parametro di output, immagino che l'obiettivo sia utilizzare quel parametro di output con valori di tabella come parametro di input con valori di tabella in un'altra procedura. Mostrerò un esempio di come ho fatto questo lavoro.

Innanzitutto, crea alcuni dati con cui lavorare:

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'   )
;

Quindi, creare una procedura memorizzata per acquisire alcuni dei dati. Normalmente, questo è dove si sta tentando di creare un parametro di output con valori di tabella.

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

Inoltre, si desidera creare un tipo di dati (tipo di tabella) in cui i dati della prima procedura memorizzata possano essere passati come parametro di input per la procedura memorizzata successiva.

create type tblType as Table (id int)

Quindi, creare la seconda procedura memorizzata che accetterà il parametro con valori di tabella.

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

Certo, questo non è un vero parametro di output con valori di tabella, ma probabilmente produrrà risultati simili a quello che si sta cercando. Dichiarare il parametro con valori di tabella, riempirlo di dati eseguendo la procedura memorizzata al suo interno, quindi utilizzarlo come variabile di input per la procedura successiva.

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

oltre a la risposta ben messa da remus incluso il link che ha fornito

Come condividere i dati tra le procedure memorizzate

ci sono situazioni in cui vengono visualizzati i seguenti messaggi di errore quando si salvano i risultati di una procedura memorizzata in una tabella:

Non è possibile nidificare un'istruzione INSERT EXEC.

La transazione corrente non può essere impegnata e non può supportare operazioni che scrivono nel file di registro. Ripristina la transazione

e quando ciò accade sulle mie procedure memorizzate che sviluppo per uso personale

ad esempio uno strumento per dirmi da un login tutti i gruppi AD a cui appartiene e tutte le loro autorizzazioni in tutti i database in un server

Creo una tabella temporanea al di fuori della procedura e passo il suo nome come parametro

--===============
-- 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

e all'interno della procedura, dopo tutti i calcoli, quando sto restituendo i dati finali (sotto un esempio) controllo se stiamo uscendo da una tabella o appena torniamo allo schermo e creiamo lo script in modo dinamico.

            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)

Dopo di che hai sullo schermo le informazioni che ti servono, o se hai passato una tabella temporanea come parametro, ora avrà i dati.

questa è una soluzione che ho trovato, ma la uso solo per i miei lavori DBA altrimenti sarà considerata ad alto rischio per Sql Injection .

1