我第一次使用PostgreSQL与LEAD()
和LAG()
合作,并使用了case语句。我的一个案例陈述根本没有提到超前和滞后值,应该做UPSERT
。
在我更改为在不同的case语句中使用UPSERT
和LEAD()
之前,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()的SELECT语句和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;
但是当我在没有带有LEAD()和LAG()且没有第一个CASE语句的SELECT语句的情况下运行此代码时,它可以工作:
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语句,并且它本身也是有效的。