0

我第一次使用 PostgreSQL,并使用 case 语句LEAD()LAG()我的一个案例陈述根本没有提到领先和滞后值,并且应该做一个UPSERT.

UPSERT在我改为在不同的 case 语句中使用LEAD()and之前,它工作得非常好。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() 和 LAG() 的 SELECT 语句是什么导致问题:

    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() 的 SELECT 语句且没有第一个 CASE 语句的情况下运行此代码时,它可以工作:

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 语句,并且它本身也可以工作。

4

0 回答 0