I am trying to run an UPSERT on a table Person like this:
BEGIN
    EXECUTE IMMEDIATE q'[
        MERGE INTO Person p
        USING (SELECT :x id, :y first_name, :z last_name FROM Dual) data
        ON (p.id = :x) -- note the repeated placeholder :x here
        WHEN MATCHED THEN
              UPDATE SET p.first_name = data.first_name, p.last_name = data.last_name
        WHEN NOT MATCHED THEN
              INSERT (id, first_name, last_name) VALUES (data.id, data.first_name, data.last_name)
    ]' USING 123, 'Foo', 'Bar';
END;
/
If I run the code as given above, Oracle throws a ORA-01008: not all variables bound ORA-06512: at line 2
According to the docs this is not supposed to happen at this point (inside an anonymous block). What am I doing wrong?
I know that I can work around this if I supply four arguments … USING 123, 'Foo', 'Bar', 123; and this works just fine, but obviously I don't want to repeat myself. Edit: as pointed out in the answers, ON (p.id = data.id) is another possible workaround.
The question is not how to work around this, it's more about understanding the cause of this error in this situation.
 
     
     
    