首页 > 解决方案 > SQL 临时表已经存在,即使我用 OBJECT_ID('tempdb..##myTable') IS NULL 检查了它

问题描述

我需要使用现有的全局临时表或创建它们并在它们不存在时填充它们。

一张表的例子

BEGIN TRANSACTION
if OBJECT_ID('tempdb..##myTable') IS NULL
begin
    create table ##myTable (
        --stuff
    )
end
COMMIT TRANSACTION
BEGIN TRANSACTION
if (select count(*) from ##myTable) = 0
begin
    insert into ##myTable
    --select stuff
end
COMMIT TRANSACTION

有时它可以工作,有时会显示错误“表##myTable 已存在”。我是唯一一个使用这些全局临时表的人

标签: sql-server

解决方案


这是一个经典的比赛条件。多个会话可以同时执行if OBJECT_ID('tempdb..##myTable') IS NULL查询。如果表不存在,两者都会尝试创建表,只有一个会成功。

解决该问题的一种方法是使用应用程序锁在多个会话之间序列化代码块。例如:

SET XACT_ABORT ON; --best practice with explict T-SQL transactions
BEGIN TRANSACTION;
EXEC sp_getapplock 
      @Resource = 'create ##myTable'  
     ,@LockMode = 'Exclusive'   
     ,@LockOwner = 'Transaction';
if OBJECT_ID('tempdb..##myTable') IS NULL
begin
    create table ##myTable (
        --select stuff
    );
end;
COMMIT TRANSACTION; --also releases app lock

推荐阅读