Paramètre à valeur de table en tant que paramètre de sortie pour la procédure stockée

33

Est-il possible d'utiliser le paramètre Table-Valued comme paramètre de sortie pour une procédure stockée?

Voici ce que je veux faire dans le code

/*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
adopter pilote
la source

Réponses:

35

Non, malheureusement, les paramètres de valeur de table sont en lecture seule et en entrée uniquement. Ce sujet en général est très bien traité dans Comment partager des données entre procédures stockées , qui présente toutes les alternatives. Ma recommandation serait d'utiliser une #temptable.

Remus Rusanu
la source
1

Ceci est une publication plus ancienne, mais c’était presque au sommet lorsque je recherchais "Paramètre à valeur de table comme paramètre de sortie pour une procédure stockée". Bien que je sache que vous ne pouvez pas passer un paramètre table-value en tant que paramètre de sortie, j'imagine que l'objectif est d'utiliser ce paramètre de sortie table-value en tant que paramètre d'entrée table-value dans une autre procédure. Je vais montrer un exemple de la façon dont j'ai réalisé ce travail.

Tout d’abord, créez des données avec lesquelles travailler:

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

Ensuite, créez une procédure stockée pour capturer certaines des données. Normalement, vous essayez de créer un paramètre de sortie table-value.

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

En outre, vous souhaiterez créer un type de données (type de table) dans lequel les données de la première procédure stockée peuvent être transmises en tant que paramètre d'entrée pour la procédure stockée suivante.

create type tblType as Table (id int)

Ensuite, créez la deuxième procédure stockée qui acceptera le paramètre table.

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

Certes, ce n'est pas un vrai paramètre de sortie table-valeur, mais il va probablement produire des résultats similaires à ce que vous recherchez. Déclarez votre paramètre table, remplissez-le avec les données en y exécutant la procédure stockée, puis utilisez-le comme variable d'entrée pour la procédure suivante.

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

en plus de la réponse bien posée de remus, y compris le lien qu'il a fourni

Comment partager des données entre des procédures stockées

Dans certains cas, vous obtenez les messages d'erreur suivants lors de l'enregistrement des résultats d'une procédure stockée dans une table:

Une instruction INSERT EXEC ne peut pas être imbriquée.

La transaction en cours ne peut pas être validée et ne peut pas prendre en charge les opérations écrivant dans le fichier journal. Annule la transaction

et lorsque cela se produit sur mes propres procédures stockées que je développe pour mon propre usage

par exemple un outil pour me dire à partir de logintous les groupes AD auxquels il appartient et de toutes leurs autorisations dans toutes les bases de données d'un serveur

Je crée une table temporaire en dehors de la procédure et passe son nom en tant que paramètre

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

et à l'intérieur de la procédure, après tous les calculs, lorsque je renvoie les données finales (sous un exemple), je vérifie si nous exportons dans une table ou juste à l'écran, et créons le script de manière dynamique.

            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)

Après cela, vous avez soit les informations dont vous avez besoin à l'écran, ou si vous avez passé une table temporaire en tant que paramètre, elle aura maintenant les données.

C’est une solution que j’ai trouvée, mais je ne l’utilise que pour mes propres travaux, DBAsinon cela sera considéré comme un risque élevé pour Sql Injection .

Marcello Miorelli
la source