将临时表中的记录添加到真实表后删除它们

时间:2011-02-16 17:12:28

标签: sql sql-server-2005 stored-procedures

我有一个asp.net程序,它将任务添加到我的临时表并执行一个存储过程,它接受这些任务并将它们放在我的实际表中,我想在添加它们之后删除它们,因为我的暂存桌子会快得太快。

这是我的存储过程代码

    INSERT INTO dashboardtasks
SELECT [tour], tourname, [taskname], [deptdate], [tasktype], [desc], [duedate], [compdate], [comments], [agent], [compby], [graceperiod], completed , canceled
FROM staggingtasks
WHERE NOT EXISTS(SELECT * 
                 FROM dashboardtasks 
                 WHERE (staggingtasks.tour=dashboardtasks.tour and
                       staggingtasks.taskname=dashboardtasks.taskname and 
staggingtasks.deptdate=dashboardtasks.deptdate and 
staggingtasks.duedate=dashboardtasks.duedate and
staggingtasks.tourname=dashboardtasks.tourname 

)
                 )




END

6 个答案:

答案 0 :(得分:3)

您可以从临时表中结合DELETE子句执行OUTPUT。和INSERT OUTPUT子句的结果进入主表,在一个原子语句中完成所有这些。

OUTPUT deleted.* into dashboardtasks 

虽然有some restrictions listed in BOL可能会使这种方法变得不可行。

output_table不能:

  • 已启用在其上定义的触发器。
  • 参加a的任何一方 外键约束。
  • 请检查 约束或启用规则。

查询的完整语法...

DELETE FROM staggingtasks
OUTPUT DELETED.[tour],
       DELETED.tourname,
       DELETED.[taskname],
       DELETED.[deptdate],
       DELETED.[tasktype],
       DELETED.[desc],
       DELETED.[duedate],
       DELETED.[compdate],
       DELETED.[comments],
       DELETED.[agent],
       DELETED.[compby],
       DELETED.[graceperiod],
       DELETED.completed,
       DELETED.canceled
INTO dashboardtasks
WHERE  NOT EXISTS(SELECT *
                  FROM   dashboardtasks
                  WHERE  ( staggingtasks.tour = dashboardtasks.tour
                           and staggingtasks.taskname = dashboardtasks.taskname
                           and staggingtasks.deptdate = dashboardtasks.deptdate
                           and staggingtasks.duedate = dashboardtasks.duedate
                           and staggingtasks.tourname = dashboardtasks.tourname
                         ))  

答案 1 :(得分:2)

使用与插入标准相同的删除声明,但现在使用 EXISTS 而不是 NOT EXISTS

这样的事情:

INSERT INTO dashboardtasks
SELECT [tour], tourname, [taskname], [deptdate], [tasktype], [desc], [duedate], [compdate], [comments], [agent], [compby], [graceperiod], completed , canceled
  FROM staggingtasks
 WHERE NOT EXISTS
  (
        SELECT * 
         FROM dashboardtasks 
         WHERE (
                        staggingtasks.tour=dashboardtasks.tour and
                      staggingtasks.taskname=dashboardtasks.taskname and 
                        staggingtasks.deptdate=dashboardtasks.deptdate and 
                        staggingtasks.duedate=dashboardtasks.duedate and
                        staggingtasks.tourname=dashboardtasks.tourname 
                    )
  )


DELETE FROM staggingtasks
 WHERE EXISTS
  (
        SELECT * 
         FROM dashboardtasks 
         WHERE (
                        staggingtasks.tour=dashboardtasks.tour and
                      staggingtasks.taskname=dashboardtasks.taskname and 
                        staggingtasks.deptdate=dashboardtasks.deptdate and 
                        staggingtasks.duedate=dashboardtasks.duedate and
                        staggingtasks.tourname=dashboardtasks.tourname 
                    )
  )

答案 2 :(得分:2)

请记住,删除会记录所有内容,以便日志可能会变得太大。如果您不关心临时表中的数据,请在插入后尝试TRUNCATE命令:

TRUNCATE TABLE staggingtasks

正如其他人所说的那样,您可能希望将其全部放入Transactions 以防万一。关于Truncate的优点是它很快,因为从表中清除的每条记录都不需要额外的日志记录。

答案 3 :(得分:1)

如果事情可能同时发生(特别是如果在其他过程发生时可插入交错的任务),那么现有的解决方案都不安全。

您需要将数据插入临时表,然后插入临时表中的数据,然后根据临时表中的记录从登台表中删除数据。这可确保您只删除插入的记录,而不是插入时添加的其他记录。当然,你应该把所有这些都放在交易中,如@Ardman所示。

此外,如果不指定要插入的字段,则不应进行插入。假设有人重新创建了表并重新排列了字段,那么插入将插入错误的字段(如果数据类型兼容)或失败。

SELECT [tour], tourname, [taskname], [deptdate], [tasktype], [desc], [duedate], [compdate], [comments], [agent], [compby], [graceperiod], completed , canceled 
INTO #TasksToInsert
FROM staggingtasks 
WHERE NOT EXISTS(SELECT * 
                FROM dashboardtasks 
                WHERE (staggingtasks.tour=dashboardtasks.tour 
                    AND staggingtasks.taskname=dashboardtasks.taskname 
                    AND staggingtasks.deptdate=dashboardtasks.deptdate 
                    AND staggingtasks.duedate=dashboardtasks.duedate 
                    AND staggingtasks.tourname=dashboardtasks.tourname)
                )

INSERT INTO dashboardtasks ([tour], tourname, [taskname], [deptdate], [tasktype], [desc], [duedate], [compdate], [comments], [agent], [compby], [graceperiod], completed , canceled )
SELECT [tour], tourname, [taskname], [deptdate], [tasktype], [desc], [duedate], [compdate], [comments], [agent], [compby], [graceperiod], completed , canceled 
FROM #TasksToInsert

DELETE FROM staggingtasks  
WHERE EXISTS   (SELECT *
                FROM #TasksToInsert          
                WHERE (staggingtasks.tour=#TasksToInsert.tour 
                        AND staggingtasks.taskname=#TasksToInsert.taskname 
                        AND staggingtasks.deptdate=#TasksToInsert.deptdate 
                        AND staggingtasks.duedate=#TasksToInsert.duedate 
                        AND staggingtasks.tourname=#TasksToInsert.tourname)
                )   

如果尚未投入生产,请修复StagingTasks的拼写错误。或者它会惹恼你的开发者多年!我还会考虑在dashboardTasks表中添加一个代理键,因为像你这样的多字段PK可能会导致性能问题,如果存在子表,则较小的int键不会。但仍然在自然键上做出一个独特的索引。

答案 4 :(得分:0)

您可以运行清除表格的DELETE语句

DELETE FROM myTable

我的建议是使用BEGIN TRYBEGIN CATCH,如果发生任何事情,您还没有从登台表中删除数据。

BEGIN TRY
    BEGIN TRAN
    INSERT statement....

    // All successful
    DELETE statement...

END TRY

BEGIN CATCH

    IF @@TRANCOUNT > 0
        ROLLBACK TRAN

END CATCH

IF @@TRANCOUNT > 0
    COMMIT TRAN

答案 5 :(得分:0)

您可以在一个存储过程中运行多个查询,因此,除非我遗漏了某些内容,否则您应该只能添加

DELETE staggingtasks WHERE <any criteria you need>
INSERT查询后

...