过程是删除数据而不是插入

Ang*_*ge1 2 sql-server stored-procedures

我有一个程序如下:

create procedure MoveDailyData
    @date1 bigint
    as
    declare @datenow bigint
    set @datenow = datediff(S,'01/01/1970',getdate())
    if ((@datenow)-@date1)>=86400
    begin
     insert into FinalLogs(problem,channel_number,username,app_id,Is_On,logtype,viewing_channel,playtime,macaddress,wifimacaddress,seen,version,date) 
     select problem,channel_number,username,app_id,Is_On,logtype,viewing_channel,playtime,macaddress, wifimacaddress,seen,version,date from DayTempTable
     delete from DayTempTable where (@datenow-@date1)>=86400
     end
     else select 'Not Yet';
Run Code Online (Sandbox Code Playgroud)

该过程应将数据从 1 个临时表复制到最后一个(按每日计划),然后从临时表中删除该数据。相反,我注意到每隔几天,数据不会被复制,而只是从临时表中删除,因此我丢失了大量相关数据。该date列是一个bigint(日期另存为unix time)。在这个过程中我做错了什么吗?

Sol*_*zky 5

这里有几个问题:

  1. 没有显式的 BEGIN TRAN/COMMIT/ROLLBACK 周围,INSERT并将DELETE它们分组为一个原子操作。

  2. 没有 TRY / CATCH 结构来管理COMMITvs ROLLBACK.

  3. 为什么要使用 UNIX 时间而不是实际DATETIME值?

  4. 为什么没有WHERE条件SELECT喂食INSERT

  5. 但与所述问题最直接相关的是:整个DayTempTable表被删除,因为语句的WHERE条件DELETE是一个简单的布尔表达式并且不引用该表的任何字段。意思是,如果(@datenow-@date1)>=86400计算结果为true,则所有行都将被删除。否则,不会删除任何行。如果要删除行的子集,则需要实际过滤表 ;-)。

  6. 显式事务中INSERTthen的另一种方法DELETE是通过OUTPUT子句同时处理两个操作:

    DELETE tbl
    FROM   DayTempTable tbl
    OUTPUT DELETED.problem, DELETED.channel_number, DELETED.username, DELETED.app_id,
           DELETED.Is_On, DELETED.logtype, DELETED.viewing_channel, DELETED.playtime,
           DELETED.macaddress, DELETED.wifimacaddress, DELETED.seen, DELETED.version,
           DELETED.date
    INTO   FinalLogs (problem, channel_number, username, app_id, Is_On, logtype,
                      viewing_channel, playtime, macaddress, wifimacaddress, seen,
                      version, date)
    WHERE  (@datenow - tbl.[date_field]) >= 86400;
    
    Run Code Online (Sandbox Code Playgroud)

    然后您不需要显式事务(即 BEGIN TRAN / COMMIT / ROLLBACK),因为它是自动处理的。但是您仍然应该进行尝试/捕捉。

    更好的是将WHERE条件更改为一个简单的、可讨论的表达式:

    WHERE  tbl.[date_field] <= (@datenow - 86400);
    
    Run Code Online (Sandbox Code Playgroud)

此外,我不会使用术语“临时表”来指代该DayTempTable表,因为它实际上不是一个临时表(用单井号或双井号#作为前导字符表示)表名)。