Oracle Upsert预编译语句迁移至PostgreSQL的问题排查
Fixing Your PostgreSQL Upsert (Converted from Oracle MERGE)
Hey there, converting Oracle's MERGE to PostgreSQL's upsert syntax has a few gotchas, so let's break down what's off with your attempt first, then walk through the correct solution.
What's Wrong With Your Attempted Query
Let's go through the issues one by one:
- Broken
INSERTsyntax: You tried wrapping aSELECTsubquery insideVALUES(), which isn't valid in PostgreSQL. When inserting from a subquery, you need to useINSERT INTO ... SELECT ...directly—VALUES()is meant for explicit row values, not wrapping subqueries. - Misused aliases: You gave your subquery the alias
b, but then referencedain theDO UPDATEclause. PostgreSQL doesn't use table aliases likeahere for the target table in an upsert. Instead, we use the specialEXCLUDEDkeyword to access the row that would've been inserted if there was no conflict. - (Optional) Unnecessary
dualtable: While PostgreSQL does supportFROM dualfor Oracle compatibility, it's not required—you can select values directly without it, but we'll keep it in the fix since you wanted to use it.
Correct PostgreSQL Upsert Query (With dual Table)
Here's the properly converted version that matches your original Oracle MERGE behavior:
INSERT INTO DUMMY(id, name, size) SELECT ? AS id, ? AS name, ? AS size FROM dual ON CONFLICT(id) DO UPDATE SET id = EXCLUDED.id, name = EXCLUDED.name, size = EXCLUDED.size;
A Quick Explanation:
EXCLUDEDis your friend: This keyword refers to the row you tried to insert but that hit a conflict on theidcolumn. It replaces thebalias from your OracleMERGE—it's how you access the new values you want to update the existing row with.- Simplified Version (No
dual): If you don't need to keepdualfor compatibility, you can make this even cleaner:INSERT INTO DUMMY(id, name, size) VALUES(?, ?, ?) ON CONFLICT(id) DO UPDATE SET id = EXCLUDED.id, name = EXCLUDED.name, size = EXCLUDED.size; - Behavior Match: Both versions do exactly what your original Oracle
MERGEdid: if a row with the givenidexists, it updates all columns with the new values; if not, it inserts a new row.
内容的提问来源于stack exchange,提问作者yed2393
相关产品推荐
相关产品推荐

