无法删除临时表

时间:2013-05-22 20:19:26

标签: sql-server tsql

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

  

Msg 2714,Level 16,State 1,Procedure SYNC_SpreadMembers,Line 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

4 个答案:

答案 0 :(得分:2)

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

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

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

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

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

  

Msg 2714,Level 16,State 1,Line 4

     

已经有一个名为'#Blah'在数据库中。

答案 1 :(得分:0)

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

 TRUNCATE TABLE #MM_SYNC_MEMBERS

答案 2 :(得分:0)

  

临时表绑定到连接。所以当连接是   丢弃,临时表被删除。

因此它不会被丢弃在存储过程的中间。

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

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

<强>附加: 也许你也可以看一下CTE,因为它可能是你问题的解决方案: http://msdn.microsoft.com/en-us/library/ms190766(v=sql.105).aspx

答案 3 :(得分:0)

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

EX -

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

如果(condtion1) 插入临时(或删除) 否则if(condition2) 插入临时 .........