【问题标题】:Temp table does not exists even if connection is not closed即使连接没有关闭,临时表也不存在
【发布时间】:2020-12-26 22:50:29
【问题描述】:

我有以下代码:

using (var connection = new SqlConnection(constr))
{
    connection.Open();

    var createTempTables = new SqlCommand("[dbo].[p_CreateTempTable]", connection)
    {
        CommandType = CommandType.StoredProcedure
    };

    createTempTables.Parameters.Add(new SqlParameter("@Id", 2));
    createTempTables.ExecuteNonQuery();

    var actualCommand = new SqlCommand("[dbo].[p_Test]", connection)
    {
        CommandType = CommandType.StoredProcedure
    };

    var dt = new DataTable();

    dt.Load(actualCommand.ExecuteReader());
}

基本上,[dbo].[p_CreateTempTable] 从表中选择与 ID inut 匹配的行作为参数。然后,[dbo].[p_Test] 只选择临时表。据我了解,只要连接未关闭,临时表就应该持续存在,但我总是得到一个异常,说我的临时表不存在。为什么这不起作用?

注意:如果我改为使用在 C# 中创建临时表的文本命令,则程序运行没有问题。但是我想避免这样做,因为在创建临时表时会有更多的验证,而且由于应用程序是一个 WinForms,我想避免每次逻辑发生变化时重新编译。

【问题讨论】:

  • 你能显示 SQL 过程 p_CreateTempTable 吗?
  • 一个临时表只在它创建的范围内存在。我非常怀疑你的 2 个语句在不同的范围内运行。
  • 在过程完成执行时,在过程中创建的临时表超出范围。在您的代码中,dbo.p_Test 无法访问在 dbo.p_createTempTable 中创建的任何临时表。
  • @Vernou 这是一个简单的SELECT INTO 声明
  • 没关系,@RegularNormalDayGuy。

标签: c# sql-server temp-tables


【解决方案1】:

这里的基本问题是,在 SQL Server 中,临时表的生命周期绑定到创建它们的批处理和//或会话上下文。

这意味着如果您在存储过程中创建一个临时表,那么该临时表只能在该存储过程退出之前看到(如此有效,只有该存储过程调用的其他存储过程才能看到)。这是因为存储过程本身就是一个批处理上下文,所以如果它创建一个临时表,那么它就会绑定到该存储过程的批处理上下文。

解决这个问题只有两种方法,都很不方便:

  1. 使用直接命令(即不在存储过程中)在会话级别创建临时表,这意味着您必须在客户端代码(或配置设置)中包含命令。或者

  2. 改用全局临时表。全局临时表并不像普通临时表那样真正工作,它们将在批次和会话中持续存在,直到您明确删除它们,因此您可以在存储过程中创建它们并且它们将持续存在。但是,现在您必须担心与常规表相同的事情:如果表已经存在怎么办?如果有多个用户同时运行这个存储过程怎么办?与常规表相比,唯一的优势是创建和删除它们所需的权限更少。

【讨论】:

  • 是的,我虽然关于使用全局临时表,但也有多用户版本,所以如果每个用户都使用同一个临时表,它会增加更多的复杂性。我可能会选择选项 1。非常感谢您的回答!
  • @RegularNormalDayGuy 是的,没有简单的答案。对于选项 1,我使用的一个技巧是将创建表的命令存储在数据库的常规表中。然后您不必在客户端中维护这些命令。客户端代码只是从该表中读取一行并执行它以在会话级别创建临时表。
  • 这真的很聪明。我正在创建一个返回命令的过程,但我认为将这些命令存储在一个表中会更好,感谢您的提示
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多