我有一个存储过程,它接受一个输入参数@CategoryKeys varchar
,并将其内容解析为临时表#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
如果临时表有行,我想将表传递给一个单独的存储过程。我如何在单独的过程中创建一个参数来保存临时表?
答案 0 :(得分:23)
虽然理解范围界定了直接需求,但认为在混合中添加更多选项以阐述评论中的建议可能是有用的。
<强> 1。将XML传递到存储过程
将XML传递给参数,您可以直接在SQL查询中使用XML并加入/应用于其他表:
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
然后调用存储过程进行测试:
DECLARE @Text XML = '<keys><key>1</key><key>2</key></keys>'
EXEC sp_PassXml @Text
简单查询的示例输出。
Key
-----------
1
2
<强> 2。将表值参数传递给存储过程
首先,您必须为存储过程使用的表变量定义用户定义的类型。
CREATE TYPE KeyTable AS TABLE ([Key] INT)
然后,您可以将该类型用作存储过程的参数(READONLY
是必需的,因为只支持IN
并且无法更改表格。
CREATE PROC sp_PassTable
@Keys KeyTable READONLY
AS
BEGIN
SET NOCOUNT ON
SELECT * FROM @Keys
END
GO
然后可以直接从SQL使用表变量调用存储过程。
DECLARE @Keys KeyTable
INSERT @Keys VALUES (1), (2)
EXEC sp_PassTable @Keys
注意:如果您使用的是.NET,则可以从与用户定义类型匹配的DataTable类型传递SQL参数。
查询的示例输出:
Key
-----------
1
2
答案 1 :(得分:13)
创建#TEMP表时,“范围”大于其创建的过程。
以下是一个示例:
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
具有这种说法,请不要大量编写这些内容。它是全球变量的SQL等价物并且难以维持和保持平衡。
答案 2 :(得分:0)
使用临时表的存储过程
CREATE OR ALTER Procedure Engine.TestProcTempTable
AS
BEGIN
--DROP TABLE IF EXISTS #TestProcTempTable ;
SELECT * from #TestProcTempTable;
END
将放置数据创建到临时表中,供SP使用
DROP TABLE IF EXISTS #TestProcTempTable ;
select * into #TestProcTempTable from <TABLE_NAME>;
execute Engine.TestProcTempTable