1

当我从 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

我需要临时全局表才能相应地用于不同的存储过程 存储过程创建的临时表可以用于另一个存储过程吗?.

有什么解决办法吗?

4

2 回答 2

1

我相信虽然可以做你所描述的事情,但它不太实用,因为它假定了很多棘手的时间:一个会话打开连接 A 并运行 proc 来创建 ##temp 表,然后那个会话只要连接 B、C 等需要能够访问临时表,就保持连接打开。

使用“永久”表的解决方案会更好,其中为每个“会话”添加具有唯一标识符(int 或 GUID)的行,该值由初始化调用返回(或者可以以其他方式检索或标识),并由会话的所有后续调用使用。

于 2012-09-13T14:02:53.650 回答
0

正如我在之前的回答中提到的那样(但由于您当时没有解释您的场景,所以我没有详细说明)是在一个范围内创建的任何临时表都可以被任何嵌套范围访问。

因此,在您的 C# 中,您可以运行以下查询:

CREATE TABLE #aTempTable (
      id1 INT,
          id2 INT,
          id3 VARCHAR(255),
          ...
);

然后:

[dbo].[aProcedure]

然后:

[dbo].[bProcedure]

然后:

SELECT * from #aTempTable

前提是所有这些查询都使用同一个SqlConnection对象运行,并且连接始终保持打开状态。第一个和第四个查询仅在连接范围内运行。这两个存储过程调用在嵌套范围内运行。

不需要全局临时表。aProcedure可以简单地访问#aTempTable(并且不需要在任何地方对它的任何引用添加前缀tempdb..

于 2012-09-13T13:58:12.720 回答