UPSERT с Lead () и Lag () --PostgreSQL - PullRequest
0 голосов
/ 24 мая 2018

Я впервые работаю с LEAD() и LAG() с PostgreSQL и использую операторы case.Одно из моих утверждений case вообще не относится к значениям опережающих и запаздывающих значений, и, как предполагается, должно делать UPSERT.

UPSERT работал отлично, прежде чем я переключился на использование LEAD() и LAG() в другом операторе case.Кажется, я не могу найти на сайте 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.

Есть ли причина, по которой при использовании функций WINDOWPostgreSQL, что может привести к тому, что UPSERT не будет работать?

Это код, который выдает ошибку, я вообще не ссылаюсь на LEAD () или LAG () в операторе UPSERT CASE, но, похоже, это оператор SELECT с LEAD ()и 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;

Но когда я запускаю этот код без оператора SELECT с LEAD () и LAG () и без первого оператора 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; 

Я протестировал первый оператор case, который использует LEAD () и LAG () отдельно и работает, когда он сам по себе.

...