Est-il possible d'utiliser le paramètre Table-Valued comme paramètre de sortie pour la procédure stockée?
Voici ce que je veux faire en 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
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 couvert dans Comment partager des données entre des procédures stockées , qui présente toutes les alternatives. Ma recommandation serait d'utiliser un #temp
table.
Il s'agit d'un article plus ancien, mais il était proche du sommet lorsque je recherchais "Paramètre de valeur de table comme paramètre de sortie pour la procédure stockée". Bien que je comprenne que vous ne pouvez pas passer un paramètre de valeur de table en tant que paramètre de sortie, j'imagine que le but est d'utiliser ce paramètre de sortie de valeur de table comme paramètre d'entrée de valeur de table dans une autre procédure. Je vais montrer un exemple de la façon dont j'ai fait 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, c'est là que vous essayez de créer un paramètre de sortie table.
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) où les données de la première procédure stockée peuvent être passées 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 véritable paramètre de sortie de valeur table, mais il produira probablement des résultats similaires à ceux que vous recherchez. Déclarez votre paramètre table, remplissez-le de 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
en plus de la réponse joliment mise par remus y compris le lien qu'il a fourni
Comment partager des données entre des procédures stockées
il existe des situations où vous obtenez les messages d'erreur suivants lors de l'enregistrement des résultats d'une procédure stockée dans une table:
ne instruction INSERT EXEC ne peut pas être imbriquée.
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 d'un login
tous les groupes AD auxquels il appartient et 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 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 retourne les données finales (ci-dessous un exemple), je vérifie si nous sortons dans une table ou juste de retour à l'écran et créons le script dynamiquement.
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 les données maintenant.
c'est une solution que j'ai trouvée, mais je ne l'utilise que pour mes propres travaux DBA
sinon cela sera considéré comme à haut risque pour Sql Injection .