我花了一整天时间研究为什么在从C#代码调用存储过程时无法创建临时表。
让我们假设一段C#代码:
public void GetDataByFilter(string item, string filter ...) {
...
// provide stored procedure in new SqlCommand object
sqlCommand.CommandType = CommandType.StoredProcedure;
sqlCommand.Parameters.Add("@val1", aValue1);
sqlCommand.Parameters.Add("@val2", aValue2);
...
while(sqlDataReader.Read()) { /* process info here */ }
}
和我的存储过程
ALTER PROCEDURE [dbo].[aProcedure]
@val1 VARCHAR(255),
@val2 VARCHAR(255),
...
AS
BEGIN
IF OBJECT_ID(N'tempdb..##aTempTable') IS NULL
CREATE TABLE tempdb..##aTempTable (
id1 INT,
id2 INT,
id3 VARCHAR(255),
...
)
ELSE
TRUNCATE TABLE tempdb..##aTempTable
-- insert information into this table
SELECT @paramList = ' /*list of parameters*/';
EXEC sp_executesql @sql, @paramList, ... parameters
END
在C#代码中,在另一个函数中,我提供了
sqlCommand.CommandText = "SELECT * FROM tempdb..##aTempTable";
但抛出了tempdb..##aTemTable
不存在的异常。
如果我在SSMS(Sql Server Management Studio)中执行存储过程,则会创建表。
此问题也适用于TRUNCATE TABLE
操作,而不仅仅是CREATE TABLE
。
我需要使用It is possible for created temporary table by a stored procedure to be used in another stored procedure?相应地将临时全局表用于不同的存储过程。
任何解决方案?
答案 0 :(得分:1)
我相信尽管可以做你正在描述的内容,但它不太实际,因为它假定了很多棘手的时间:会话打开连接A并运行proc来创建## temp表,只要连接B,C等需要能够访问临时表,该会话就会保持连接打开。
使用“永久”表的解决方案可能会更好,其中为每个“会话”添加一个具有唯一标识符(int或GUID)的行,该值由初始化调用返回(否则可以返回被检索或识别),并被会话的所有后续调用使用。
答案 1 :(得分:0)
正如我在previous answer中提到的那样(但由于你当时没有解释过你的场景,我没有说明)是任何嵌套范围都可以访问在一个范围内创建的任何临时表
因此,在您的C#中,您可以运行以下查询:
CREATE TABLE #aTempTable (
id1 INT,
id2 INT,
id3 VARCHAR(255),
...
);
然后:
[dbo].[aProcedure]
然后:
[dbo].[bProcedure]
然后:
SELECT * from #aTempTable
前提是所有这些查询都使用相同的SqlConnection
对象运行,并且连接始终保持打开状态。第一个和第四个查询仅在连接范围内运行。两个存储过程调用在嵌套范围内运行。
不需要全局临时表。 aProcedure
可以直接访问#aTempTable
(并且无需在任何地方为tempdb..
添加任何引用前缀。