我第一次使用 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 语句,并且它本身也可以工作。