On 2 October 2014 22:37, Bruce Momjian <br...@momjian.us> wrote:

> OK, it is was just an idea I wanted to point out, and if it doesn't
> work, it more clearly cements that we need UPSERT _and_ MERGE.

It seems clear that having two different initial keywords is popular
because it provides clarity about which aspects of the commands will
be supported.

I like the idea of making the two commands as close as possible in
syntax, which will make it easier to program for and encourage
adoption.
The command name could easily be MERGE [CONCURRENTLY] since that uses
the same concept from earlier DDL syntax/keywords.

In UPSERT, we don't need the ON keyword at all. If we are altering the
syntax, then we can easily remove this.

IIRC it wasn't agreed that we needed to identify which indexes in the
upsert SQL statement itself, since this would be possible in other
ways and would require programmers to know which unique constraints
are declared.

All of the other syntax could easily remain the same, leaving us with
a command that looks like this...

MERGE CONCURRENTLY INTO foo USING VALUES ()
WHEN NOT MATCHED THEN
  INSERT
WHEN MATCHED THEN
 UPDATE

Since MERGE now supports DELETE and IGNORE as options, presumably we
would also want to support those for the UPSERT version also.
I think it would be useful to also support a mechanism for raising an
error, as DB2 allows.

More complex example of MERGE

MERGE INTO product AS T
      USING (SELECT sales.id, sum(sold) AS sold, max(catalog.name) as name
     FROM sales, catalog WHERE sales.id = catalog.id GROUP BY sales.id) AS S
        ON S.id = T.id
  WHEN MATCHED AND T.inventory = S.sold
               THEN DELETE
  WHEN MATCHED AND T.inventory < S.sold
               THEN SIGNAL SQLSTATE '78000' SET MESSAGE_TEXT =
'Oversold: ' || S.name
  WHEN MATCHED
               THEN UPDATE SET inventory = T.inventory - S.sold
  WHEN NOT MATCHED
              THEN INSERT VALUES(S.id, S.name, -S.sold);

Full example would be similar to this

MERGE CONCURRENTLY INTO product AS T
      USING VALUES ()
  WHEN MATCHED AND T.inventory = S.sold
               THEN DELETE
  WHEN MATCHED AND T.inventory < S.sold
               THEN SIGNAL SQLSTATE '78000' SET MESSAGE_TEXT =
'Oversold: ' || S.name
  WHEN MATCHED
               THEN UPDATE SET inventory = T.inventory - S.sold
  WHEN NOT MATCHED
              THEN INSERT VALUES(S.id, S.name, -S.sold);

-- 
 Simon Riggs                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to