【问题标题】:How to check correctly if a temporary table exists in SQL Server 2005?如何正确检查 SQL Server 2005 中是否存在临时表?
【发布时间】:2025-12-02 13:30:01
【问题描述】:

我有一个查询,我从表中插入一些值:

SELECT ID, NAME INTO #tmpTable1
FROM TableOriginal

第一次执行没问题,如果我在MSSMS(Microsoft Sql Server Management Studio)中按F5(运行),就会出现错误:

消息 2714,第 16 级,状态 6,第 4 行
数据库中已经有一个名为“#tmpTable1”的对象。

很好。我决定在将数据从TableOriginal 插入到#tmpTable1 之前检查一下:

IF OBJECT_ID('tempdb.#tmpTable1') IS NOT NULL  
  DROP TABLE #tmpTable1

不起作用,错误再次显示如上。

我在tempdb 数据库中看到了以下临时表名:

dbo.#tmpTable1__________________0000007

为什么?每次创建临时表(使用第一次查询)时,MSSMS中会自动生成表名?

如何删除现有的临时表来做一个具有新值的新表?

【问题讨论】:

    标签: sql sql-server sql-server-2005


    【解决方案1】:

    您非常接近 - 您需要在支票中使用两个点:

    IF OBJECT_ID('tempdb..#tmpTable1') IS NOT NULL  
                        ** 
                        |
                      use two dots here!
    

    基本上,这就是说:签入tempDB,我不在乎表在什么架构中

    正如 Joe 正确地说的:这不是 100% 正确的:它不会检查每个模式 - 它只会检查默认所有者的模式 - 通常是 dbo。所以这也可以:

    IF OBJECT_ID('tempdb.dbo.#tmpTable1') IS NOT NULL  
    

    如果您碰巧在默认所有者之外的架构中创建对象,那么您需要明确指定您所引用的架构。但是tempDB 中的临时表确实是在dbo 架构中创建的。

    【讨论】:

    • 大声笑,那个点也很重要:)。谢谢
    • @MichaelSwan:是的,这是 SQL Server 的三部分命名:db.schema.object - 如果您省略架构 - 您仍然需要点! :-)
    • @marc_s:我认为,..(双点)冷藏到默认所有者,即 dbo
    • @marc_s:如果我从 C# ASP.NET 调用,是否需要 DROP 表?还是用连接池,会自动去掉?
    • @Joe & marc 我已经添加了一个答案,因为我无法在评论中澄清架构问题。
    【解决方案2】:

    这不是问题的答案,只是想暂时发布一个关于在引用 #temp 表时放置 .dbo... 的位的回复。

    我找不到让#temp 表实际上由 dbo 以外的任何人拥有的方法。试试看:

    CREATE SCHEMA blat;
    GO
    
    CREATE TABLE blat.#pound(id INT);
    GO
    
    SELECT 
       OBJECT_ID('tempdb..#pound'), 
       OBJECT_ID('tempdb.dbo.#pound'), 
       OBJECT_ID('tempdb.blat.#pound');
    
    USE tempdb;
    GO
    
    SELECT [object_id], SCHEMA_NAME([schema_id]) 
      FROM sys.objects 
      WHERE name LIKE '#pound%';
    

    结果:

    -1222354987    -1222354987    -1222354987
    
    -1222354987    dbo
    

    这是在 SQL Server 2012 上进行的。我在 SQL Server 2005 上进行了测试,唯一的区别是 object_id 值为正。我也试过:

    • 实际存在于 tempdb 中的模式称为 blat
    • 由默认架构为blat的用户创建的表blat.#pound
    • 以上两者

    在所有三种情况下,都获得了与上述相同的结果。

    您也不能在不同的架构中创建两个同名的#temp 表:

    CREATE TABLE blat.#flab(id INT);
    CREATE TABLE dbo.#flab(id INT);
    

    结果:

    消息 2714,级别 16,状态 6
    数据库中已经有一个名为“#flab”的对象。

    这不是解析问题(就像许多#temp 表问题一样);您可以分别运行这两个语句并收到相同的错误。

    所以,这是一种冗长的说法,在解析#temp 表名时,您永远不需要指定架构,它将始终在dbo 下创建,并且至少在OBJECT_ID 下解析将忽略您指定的架构(OBJECT_SCHEMA_NAME 在#tempdb 的上下文中运行时也总是返回dbo,但在任何其他数据库中不运行)。如果您尝试在tempdb.sys.objects 中查询schema_id,所有赌注都将取消。

    【讨论】:

      【解决方案3】:
      CREATE TABLE #temptable (col1 int);
      GO
      INSERT INTO #temptable
      VALUES (10);
      GO
      SELECT * FROM #temptable;
      GO
      IF OBJECT_ID(N'tempdb..#temptable', N'U') IS NOT NULL 
      DROP TABLE #temptable;
      GO
      --Test the drop.
      SELECT * FROM #temptable;
      

      【讨论】:

        【解决方案4】:

        只要创建它的连接打开,以这种方式定义的临时表就会存在。通常不需要检查它是否存在或手动删除它,因为你可以完全控制你的连接,但如果你真的需要检查它,你可以检查 tempdb.dbo.#tempTable。

        【讨论】:

          【解决方案5】:

          IF OBJECT_ID('tempdb.dbo.#tmpTable1%') 不为空 :)

          【讨论】:

          • IF OBJECT_ID('tempdb.dbo.#tmpTable1') IS NOT NULL 但在服务器 2008 上是这样。 temp # 不需要检查,但 ## 需要防止在一个会话中重新创建...
          • 您为什么不用正确的代码更新您的帖子,而不是将更正放在 cmets 中?不是很明显。
          最近更新 更多