UPSERT与Lead()和Lag() - PostgreSQL

时间:2018-05-24 16:10:44

标签: postgresql postgresql-10

我第一次使用PostgreSQL与LEAD()LAG()合作,并使用了case语句。我的一个案例陈述根本没有提到超前和滞后值,应该做UPSERT

在我更改为在不同的case语句中使用UPSERTLEAD()之前,LAG()工作正常。我似乎无法在PostgreSQL网站上找到任何可以说这两者无法一起使用的内容,但它会引发错误:

ERROR:  ON CONFLICT DO UPDATE command cannot affect row a second time
HINT:  Ensure that no rows proposed for insertion within the same command have duplicate constrained values.

使用PostgreSQL的WINDOW函数会导致UPSERT不起作用吗?

这是抛出错误的代码,我根本没有在UPSERT CASE语句中引用LEAD()或LAG(),但它似乎是带有LEAD()的SELECT语句和LAG()是造成这个问题的原因:

    FOR rec IN SELECT transactiontime, LEAD(transactiontime) OVER (PARTITION BY identification_number) AS leadtime, LAG(transactiontime) OVER (PARTITION BY identification_number) AS lagtime,
transactiondate, reasoncode, LEAD(reasoncode) OVER (PARTITION BY identification_number) AS leadcode, LAG(reasoncode) OVER (PARTITION BY identification_number) AS lagcode,
identification_number, last_name, first_name, middle_name, suffix
FROM current_working_trans LOOP
    code := rec.reasoncode; 
CASE
    WHEN ((rec.reasoncode = 'TRANSFER IN' AND rec.leadcode = 'TRANSFER OUT' AND (rec.leadtime::time < (rec.transactiontime::time + interval '1 minute'))) 
    OR (rec.reasoncode = 'CHANGE IN' AND rec.leadcode = 'CHANGE OUT' AND (rec.leadtime::time < (rec.transactiontime::time + interval '1 minute')))) THEN 
            UPDATE test_va_new_voter
                SET (sourceid, lastname, firstname, middlename, namesuffix) = 
            (rec.identification_number, rec.last_name, rec.first_name, rec.middle_name, rec.suffix) 
            FROM current_working_trans WHERE rec.identification_number = sourceid;

            DELETE FROM current_working_trans WHERE rec.transactiontime = transactiontime AND nvrareasoncode = rec.reasoncode;
            DELETE FROM current_working_trans WHERE rec.leadtime = transactiontime AND rec.leadcode = reasoncode;  

    WHEN code IN('NEW','REACTIVATE','REINSTATE', 'TRANSFER IN', 'CHANGE IN') THEN
                INSERT INTO test_voter
                (sourceid, lastname, firstname, middlename, namesuffix)
                SELECT rec.identification_number, rec.last_name, rec.first_name, rec.middle_name, rec.suffix    
                FROM current_working_trans
                ON CONFLICT (sourceid) 
                DO UPDATE  
                SET (lastname, firstname, middlename, namesuffix) =
                (SELECT rec.last_name, rec.first_name, rec.middle_name, rec.suffix);
            DELETE FROM current_working_trans WHERE reasoncode = rec.reasoncode AND transactiontime = rec.transactiontime; 
    END CASE;
END LOOP;

但是当我在没有带有LEAD()和LAG()且没有第一个CASE语句的SELECT语句的情况下运行此代码时,它可以工作:

FOR rec IN SELECT *
FROM current_working_trans LOOP
    code := rec.reasoncode; 
CASE
    WHEN code IN('NEW','REACTIVATE','REINSTATE', 'TRANSFER IN', 'CHANGE IN') THEN
                INSERT INTO test_voter
                (sourceid, lastname, firstname, middlename, namesuffix)
                SELECT rec.identification_number, rec.last_name, rec.first_name, rec.middle_name, rec.suffix    
                FROM current_working_trans
                ON CONFLICT (sourceid) 
                DO UPDATE  
                SET (lastname, firstname, middlename, namesuffix) =
                (SELECT rec.last_name, rec.first_name, rec.middle_name, rec.suffix);
            DELETE FROM current_working_trans WHERE reasoncode = rec.reasoncode AND transactiontime = rec.transactiontime; 
    END CASE;
END LOOP; 

我已经测试了第一个分别使用LEAD()和LAG()的case语句,并且它本身也是有效的。

0 个答案:

没有答案