为什么在从C#代码调用存储过程时无法创建全局临时表或截断它?

时间:2012-09-13 13:45:33

标签: c# sql sql-server-2005

我花了一整天时间研究为什么在从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?相应地将临时全局表用于不同的存储过程。

任何解决方案?

2 个答案:

答案 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..添加任何引用前缀。