【问题标题】:Unable to drop a temporary table无法删除临时表
【发布时间】:2013-05-22 20:19:26
【问题描述】:

我有一个使用临时表的存储过程。问题是我尝试在不同的SELECT INTO 语句中多次使用临时表。当然,在发出下一条语句之前,我已经发出了DROP #TempTableName,然后发出了SELECT INTO 语句。显然这个 DROP 语句是不够的,因为下一个 SELECT INTO 语句抱怨对象 #TempTableName 已经存在 - SSMS 输出是:

消息 2714,级别 16,状态 1,过程 SYNC_SpreadMembers,第 23 行
数据库中已经有一个名为“#MM_SYNC_MEMBERS”的对象。

这是我的 T-SQL 代码:

CREATE PROCEDURE SYNC_SpreadMembers
AS
BEGIN
    BEGIN

        -- Member
        IF (OBJECT_ID('tempdb..#MM_SYNC_MEMBERS') IS NOT NULL) 
            DROP TABLE #MM_SYNC_MEMBERS;
        -- Imported members
        SELECT DISTINCT MemberInr INTO #MM_SYNC_MEMBERS FROM
            (
                SELECT DISTINCT DmInr AS MemberInr FROM MM_SYNC_EBOLIGWS WHERE NOT DmInr IS NULL
                UNION 
                SELECT DISTINCT AmInr AS MemberInr FROM MM_SYNC_EBOLIGWS WHERE NOT AmInr IS NULL
            ) MemberHeap
        ;                   
        DELETE #MM_SYNC_MEMBERS FROM #MM_SYNC_MEMBERS Sync INNER JOIN MM_Member Member ON Sync.MemberInr = Member.InteressentNr;
        INSERT INTO MM_Member(InteressentNr) SELECT MemberInr FROM #MM_SYNC_MEMBERS;
    END

    -- Hardcoded members
    DROP TABLE #MM_SYNC_MEMBERS;
    SELECT DISTINCT InteressentNr AS MemberInr INTO #MM_SYNC_MEMBERS FROM MM_SYNC_HardcodedMemberRoles;
    DELETE #MM_SYNC_MEMBERS FROM #MM_SYNC_MEMBERS Sync INNER JOIN MM_Member Member ON Sync.MemberInr = Member.InteressentNr;
    INSERT INTO MM_Member(InteressentNr) SELECT MemberInr FROM #MM_SYNC_MEMBERS;

    -- MemberRole
    -- Area Managers
    DELETE MM_MemberRole;
    INSERT INTO MM_MemberRole(MemberSid, RoleSid)
        SELECT DISTINCT Member.[Sid], (SELECT [Sid] FROM MM_Role WHERE Cipher LIKE 'AMA')
        FROM MM_SYNC_EBOLIGWS Sync
            INNER JOIN MM_Member Member ON Sync.AmInr = Member.InteressentNr
        WHERE Sync.AmInr IS NOT NULL
    ;
    -- Department Managers
    INSERT INTO MM_MemberRole(MemberSid, RoleSid)
        SELECT DISTINCT Member.[Sid], (SELECT Sid FROM MM_Role WHERE Cipher LIKE 'DM')
        FROM MM_SYNC_EBOLIGWS Sync
            INNER JOIN MM_Member Member ON Sync.DmInr = Member.InteressentNr
        WHERE Sync.DmInr IS NOT NULL
    ;

    -- Hardcoded Roles
    INSERT INTO MM_MemberRole(MemberSid, RoleSid)
        SELECT Member.Sid, Roles.Sid 
        FROM MM_SYNC_HardcodedMemberRoles HCR 
            INNER JOIN MM_Member Member ON HCR.InteressentNr = Member.InteressentNr
            INNER JOIN MM_Role Roles ON HCR.RoleCipher = Roles.Cipher
    ;
END
GO

【问题讨论】:

  • 我认为在存储过程完成执行之前不会将其删除。为什么不只使用几个临时表?
  • 是的,我做到了。但是,我仍然想知道为什么临时表没有被删除,因为我明确地这样做了。数据库引擎是否只是忽略临时表的删除?
  • 是的,另一种可能的解决方案是使用 CTE。有必要掉表吗?您也可以将其清除,然后在最后放下。
  • @BozhidarStoinev:基本上是这个:stackoverflow.com/a/9812563/128217

标签: sql-server tsql


【解决方案1】:

T-SQL 是一种非常简单的语言——它基本上会尽快编译当前作用域/批处理中的所有代码。在不同的时间(例如创建新表时)它会重新编译批处理。

在您第一次创建新的临时表后立即重新编译时实际上会引发错误。此时,当它尝试重新编译后面的语句并尝试创建具有相同名称的临时表时,它会产生错误。

它不会等着看正常的执行流程(包括控制流程)是否会防止在到达语句时发生错误。例如。这会产生类似的错误:

create table #Blah (ID int)
if 1 = 0
begin
    create table #Blah (Foo int)
end

即使我们可以看到它并知道实际上不会发生任何伤害

消息 2714,第 16 级,状态 1,第 4 行

数据库中已经有一个名为“#Blah”的对象。

【讨论】:

  • 现在解释一下。谢谢达米安!
【解决方案2】:

既然表在两次插入中都有相同的列,为什么不只创建一次表,而不是删除它:

 TRUNCATE TABLE #MM_SYNC_MEMBERS

【讨论】:

    【解决方案3】:

    临时表与连接绑定。所以当连接 删除,临时表被删除。

    所以它不会在存储过程的中间被丢弃。

    这将与它所在的实例相关联,它可以满足您的需求:

    DECLARE @TemporaryTable TABLE 
    (
          id int,
          name nvarchar(50)
    )
    

    额外: 也许您也可以看看 CTE,因为它可能是您问题的解决方案: http://msdn.microsoft.com/en-us/library/ms190766(v=sql.105).aspx

    【讨论】:

      【解决方案4】:

      为什么要全局创建#MM_SYNC_MEMBERS的结构,然后可以根据条件在temp中删除或插入数据。

      EX-

      创建表#Temp (名称 varchar(20))


      如果(条件1) 插入临时(或删除) 否则如果(条件2) 插入到温度 .........

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-13
        • 2011-12-17
        相关资源
        最近更新 更多