在数据库编程中,经常需要将临时表中的数据传递给存储过程,以便进行进一步的处理。本文将探讨几种实现这一功能的方法,并评估它们的优缺点。特别地,将关注并发调用的场景,以及如何确保临时表在不同调用中的数据隔离性。
在SQL中,有几种方法可以实现临时表数据的传递和处理。以下是一些常见的方法:
INSERT INTO
操作,可能会导致失败。接下来,将重点评估使用临时表的方法。
为了评估临时表是否在不同调用中保持独立,首先创建一个名为mytable
的表,并插入一些测试数据。
CREATE TABLE [dbo].[MyTable](
[col1] INT NOT NULL,
[col2] CHAR(5) NULL
) ON [PRIMARY]
INSERT INTO [MyTable] ([col1], [col2]) VALUES (1, 'A')
INSERT INTO [MyTable] ([col1], [col2]) VALUES (2, 'B')
INSERT INTO [MyTable] ([col1], [col2]) VALUES (3, 'C')
INSERT INTO [MyTable] ([col1], [col2]) VALUES (4, 'D')
然后,创建一个名为called_procedure
的子存储过程。在这个过程中,首先检查临时表是否存在,如果存在,则根据传递的参数插入数据。
IF EXISTS (
SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[called_procedure]') AND type IN (N'P', N'PC')
)
DROP PROCEDURE [dbo].[called_procedure]
GO
CREATE PROCEDURE Called_procedure
@par1 INT,
@par2 BIT AS
BEGIN
IF OBJECT_ID('tempdb..#mytemp') IS NOT NULL
BEGIN
INSERT INTO #mytemp SELECT * FROM Mytable WHERE col1 = @par1
END
END
GO
接下来,创建一个不创建临时表的父存储过程。在这个过程中,测试临时表是否在当前作用域中不存在。
IF EXISTS (
SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[caller_procedure1]') AND type IN (N'P', N'PC')
)
DROP PROCEDURE [dbo].[caller_procedure1]
GO
CREATE PROCEDURE Caller_procedure1 AS
BEGIN
EXEC Called_procedure 1, 0
IF OBJECT_ID('tempdb..#mytemp') IS NOT NULL
BEGIN
SELECT * FROM #mytemp
END
END
GO
然后,创建另一个父存储过程,这个过程中创建了自己的临时表,并在作用域结束时删除它。
IF EXISTS (
SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[caller_procedure2]') AND type IN (N'P', N'PC')
)
DROP PROCEDURE [dbo].[caller_procedure2]
GO
CREATE PROCEDURE Caller_procedure2
@par1 INT AS
BEGIN
CREATE TABLE #mytemp
(
col1 INT NOT NULL,
col2 CHAR(5) NULL
)
EXEC Called_procedure @par1, 0
SELECT * FROM #mytemp
END
GO
最后,同时执行以下查询,以测试并发调用的情况。
CREATE TABLE #mytemp (col1 int NOT NULL, col2 char(5) NULL)
Exec caller_procedure2 2
Exec caller_procedure2 4
Exec caller_procedure2 2
Exec caller_procedure2 4
drop table #mytemp
Exec caller_procedure1
在这个小练习中,可以看到如何将临时表传递给子存储过程,并返回处理后的数据。通过使用这种方法,可以编写多用途的存储过程,以提高代码的可重用性。