SQL 服务器:如果我 运行 具有 select 的相同存储过程同时进入相同的临时 table 会发生什么
SQL Server : what happens if I run the same stored procedure simultaneously that has a select into same temporary table
任何想法,如果我同时 运行 相同的存储过程(使用 jmeter)会发生什么,并且在该存储过程中有查询
SELECT INTO #temp
是否会在第一个存储过程完成后运行第二个存储过程?
或者临时文件table会被创建两次(听说SQL服务器中有本地临时文件table)?
抱歉这个愚蠢的问题,我在 Google 上找不到任何答案。
谢谢
临时 table 仅存在于创建它的范围内(以及该范围的 "subscopes"),并且仅在该范围的持续时间内存在。
因此,例如。如果您要 运行 以下内容,您将不会收到任何错误:
EXEC sys.sp_executesql N'CREATE TABLE #temp (ID int);';
EXEC sys.sp_executesql N'CREATE TABLE #temp (ID int);';
那是因为table、#temp
只会存在于"dynamic"语句的范围内,一旦完成就会消失。
另一方面,像下面这样的东西会失败(这是错误的,请看我在底部的编辑):
CREATE TABLE #temp (ID int);
EXEC sys.sp_executesql N'CREATE TABLE #temp (ID int);';
DROP TABLE #temp;
那是因为 "dynamic" 语句可以访问 "outer" 范围,所以会看到 #temp
已经存在并产生错误。
运行不可能在同一个连接中同时调用 2 个语句,因此您将无法同时调用同一个存储过程。这意味着两者将具有不同的范围,因此将引用它们自己的对象 #temp
,这是特定于它们的范围。
你可以用类似的想法再次测试这个。 运行 下面,然后打开一个新连接并再次 运行 它(在另一个完成之前)。您会注意到它们都成功了:
CREATE TABLE #temp (ID int);
WAITFOR DELAY '00:30'; --Waits 30 seconds
--While the WAITFOR happens, open the another connection and run all this SQL at the same time
DROP TABLE #temp;
旁注,全局临时 tables 的行为方式不同,但我在这里特别只引用临时 tables,而不是全局的。
编辑:看来我在内部范围上错了。你实际上得到了一些非常奇怪的行为。采取以下:
CREATE TABLE #temp (ID int);
INSERT INTO #temp VALUES(1);
EXEC sys.sp_executesql N'CREATE TABLE #temp (ID int); SELECT * FROM #temp;';
SELECT *
FROM #temp
DROP TABLE #temp;
这将 return 2 个数据集,一个没有行,一个有 1 行。但是,如果您删除了延迟语句中的 CREATE
,那么您会从两者中得到 1 行:
CREATE TABLE #temp (ID int);
INSERT INTO #temp VALUES(1);
EXEC sys.sp_executesql N'SELECT * FROM #temp;';
SELECT *
FROM #temp
DROP TABLE #temp;
这发生在 SQL Server 2019 上,但我确定我记得这种行为与以前的版本不同。也许我正在回忆(非常)旧的行为。
任何想法,如果我同时 运行 相同的存储过程(使用 jmeter)会发生什么,并且在该存储过程中有查询
SELECT INTO #temp
是否会在第一个存储过程完成后运行第二个存储过程?
或者临时文件table会被创建两次(听说SQL服务器中有本地临时文件table)?
抱歉这个愚蠢的问题,我在 Google 上找不到任何答案。
谢谢
临时 table 仅存在于创建它的范围内(以及该范围的 "subscopes"),并且仅在该范围的持续时间内存在。
因此,例如。如果您要 运行 以下内容,您将不会收到任何错误:
EXEC sys.sp_executesql N'CREATE TABLE #temp (ID int);';
EXEC sys.sp_executesql N'CREATE TABLE #temp (ID int);';
那是因为table、#temp
只会存在于"dynamic"语句的范围内,一旦完成就会消失。
另一方面,像下面这样的东西会失败(这是错误的,请看我在底部的编辑):
CREATE TABLE #temp (ID int);
EXEC sys.sp_executesql N'CREATE TABLE #temp (ID int);';
DROP TABLE #temp;
那是因为 "dynamic" 语句可以访问 "outer" 范围,所以会看到 #temp
已经存在并产生错误。
运行不可能在同一个连接中同时调用 2 个语句,因此您将无法同时调用同一个存储过程。这意味着两者将具有不同的范围,因此将引用它们自己的对象 #temp
,这是特定于它们的范围。
你可以用类似的想法再次测试这个。 运行 下面,然后打开一个新连接并再次 运行 它(在另一个完成之前)。您会注意到它们都成功了:
CREATE TABLE #temp (ID int);
WAITFOR DELAY '00:30'; --Waits 30 seconds
--While the WAITFOR happens, open the another connection and run all this SQL at the same time
DROP TABLE #temp;
旁注,全局临时 tables 的行为方式不同,但我在这里特别只引用临时 tables,而不是全局的。
编辑:看来我在内部范围上错了。你实际上得到了一些非常奇怪的行为。采取以下:
CREATE TABLE #temp (ID int);
INSERT INTO #temp VALUES(1);
EXEC sys.sp_executesql N'CREATE TABLE #temp (ID int); SELECT * FROM #temp;';
SELECT *
FROM #temp
DROP TABLE #temp;
这将 return 2 个数据集,一个没有行,一个有 1 行。但是,如果您删除了延迟语句中的 CREATE
,那么您会从两者中得到 1 行:
CREATE TABLE #temp (ID int);
INSERT INTO #temp VALUES(1);
EXEC sys.sp_executesql N'SELECT * FROM #temp;';
SELECT *
FROM #temp
DROP TABLE #temp;
这发生在 SQL Server 2019 上,但我确定我记得这种行为与以前的版本不同。也许我正在回忆(非常)旧的行为。