J'ai une procédure stockée qui prend un paramètre d'entrée @CategoryKeys varchar
, et analyse son contenu dans une table temporaire, #CategoryKeys
.
-- create the needed temp table.
CREATE TABLE #CategoryKeys
(
CategoryKey SMALLINT
);
-- fill the temp table if necessary
IF Len(rtrim(ltrim(@CategoryKeys))) > 0
BEGIN
INSERT INTO #CategoryKeys
(CategoryKey)
SELECT value
FROM dbo.String_To_SmallInt_Table(@CategoryKeys, ',');
END
Si la table temporaire a des lignes, je voudrais passer la table dans une procédure stockée distincte. Comment pourrais-je créer un paramètre dans la procédure séparée pour contenir la table temporaire?
Lorsque vous créez une table #TEMP, la "portée" est plus grande que la procédure dans laquelle elle est créée.
Voici un exemple:
IF EXISTS
(
SELECT * FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_TYPE = N'PROCEDURE' and ROUTINE_SCHEMA = N'dbo' and ROUTINE_NAME = N'uspProc002'
)
BEGIN
DROP PROCEDURE [dbo].[uspProc002]
END
GO
CREATE Procedure dbo.uspProc002
AS
BEGIN
/* Uncomment this code if you want to be more explicit about bad "wiring" */
/*
IF OBJECT_ID('tempdb..#TableOne') IS NULL
begin
THROW 51000, 'The procedure expects a temp table named #TableOne to already exist.', 1;
end
*/
/* Note, I did not Create #TableOne in this procedure. It "pre-existed". An if check will ensure that it is there. */
IF OBJECT_ID('tempdb..#TableOne') IS NOT NULL
begin
Insert into #TableOne ( SurrogateKey , NameOf ) select 2001, 'uspProc002'
end
END
GO
IF EXISTS
(
SELECT * FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_TYPE = N'PROCEDURE' and ROUTINE_SCHEMA = N'dbo' and ROUTINE_NAME = N'uspProc001'
)
BEGIN
DROP PROCEDURE [dbo].[uspProc001]
END
GO
CREATE Procedure dbo.uspProc001 (
@Param1 int
)
AS
BEGIN
IF OBJECT_ID('tempdb..#TableOne') IS NOT NULL
begin
drop table #TableOne
end
CREATE TABLE #TableOne
(
SurrogateKey int ,
NameOf varchar(12)
)
Insert into #TableOne ( SurrogateKey , NameOf ) select 1001, 'uspProc001'
Select * from #TableOne
EXEC dbo.uspProc002
Select * from #TableOne
IF OBJECT_ID('tempdb..#TableOne') IS NOT NULL
begin
drop table #TableOne
end
END
GO
exec dbo.uspProc001 0
AYANT DIT QUE, S'IL VOUS PLAÎT, NE PAS ENCODER BEAUCOUP DE CELLES-CI. SON ÉQUIVALENT SQL D'UNE VARIABLE MONDIALE ET IL IS DIFFICILE À MAINTENIR ET À BUG PRONE.
Bien que la compréhension de la portée réponde au besoin direct, nous avons pensé qu'il pourrait être utile d'ajouter quelques options supplémentaires au mélange pour élaborer les suggestions des commentaires.
1. Passez XML dans la procédure stockée
Avec XML passé dans un paramètre, vous pouvez utiliser le XML directement dans vos requêtes SQL et rejoindre/appliquer à d'autres tables:
CREATE PROC sp_PassXml
@Xml XML
AS
BEGIN
SET NOCOUNT ON
SELECT T.Node.value('.', 'int') AS [Key]
FROM @Xml.nodes('/keys/key') T (Node)
END
GO
Ensuite, un appel à la procédure stockée pour tester:
DECLARE @Text XML = '<keys><key>1</key><key>2</key></keys>'
EXEC sp_PassXml @Text
Exemple de sortie d'une requête simple.
Key
-----------
1
2
2. Passez un paramètre table dans la procédure stockée
Tout d'abord, vous devez définir le type défini par l'utilisateur pour la variable de table à utiliser par la procédure stockée.
CREATE TYPE KeyTable AS TABLE ([Key] INT)
Ensuite, vous pouvez utiliser ce type comme paramètre pour le proc stocké (le READONLY
est requis car seul IN
est pris en charge et le tableau ne peut pas être modifié)
CREATE PROC sp_PassTable
@Keys KeyTable READONLY
AS
BEGIN
SET NOCOUNT ON
SELECT * FROM @Keys
END
GO
Le proc stocké peut ensuite être appelé avec une variable de table directement à partir de SQL.
DECLARE @Keys KeyTable
INSERT @Keys VALUES (1), (2)
EXEC sp_PassTable @Keys
Remarque: Si vous utilisez .NET, vous pouvez transmettre le paramètre SQL à partir d'un type DataTable correspondant au type défini par l'utilisateur.
Exemple de sortie de la requête:
Key
-----------
1
2