Я впервые работаю с 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 () отдельно и работает, когда он сам по себе.