0

私はPostgreSQL を初めて使用し、case ステートメントを使用していますLEAD()LAG()私のケースステートメントの1つは、リードとラグの値をまったく参照しておらず、UPSERT.

andを別の case ステートメントでUPSERT使用するように変更する前は、 は完全に正常に機能していました。これら 2 つを一緒に使用することはできませんが、エラーがスローされます。LEAD()LAG()

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