私は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 ステートメントをテストしました。