SnowFlake MERGE update/insert all columns
Asked Answered
D

2

11

Does snowflake support updating/inserting all columns with a syntax like UPDATE * or INSERT *

 MERGE INTO events 
 USING updates 
      ON events.eventId = updates.eventId
 WHEN MATCHED THEN 
      UPDATE *
 WHEN NOT MATCHED THEN 
       INSERT *  

similar to how Databricks does it: https://docs.databricks.com/spark/latest/spark-sql/language-manual/delta-merge-into.html

Or do we have to list out each column and its value ?

I am getting the error when I try the above

syntax error ... unexpected '*'.

and the docs dont help much: https://docs.snowflake.com/en/sql-reference/sql/merge.html

Thanks,

Diallage answered 28/5, 2021 at 21:40 Comment(1)
I'm fairly new to Snowflake, but I know it seeks to emulate Postgres syntax, although Postgres does not have a MERGE as Sql Server does. In any case, to me, the documentation seems pretty clear that you will need a SET clause for each column as is required by Postgres and Sql Server. It's a cool feature what Databricks offers, but that's the first time I've seen such syntax.Birdman
W
11

The UPDATE SET */INSERT * are SQL language extensions(not defined in SQL Standard).

Snowflake does not support that kind of syntax:

MERGE:

matchedClause ::=
  WHEN MATCHED [ AND <case_predicate> ] 
  THEN { UPDATE SET <col_name> = <expr> [ , <col_name2> = <expr2> ...] 
         | DELETE }[...]

notMatchedClause ::=
  WHEN NOT MATCHED [ AND <case_predicate> ] 
  THEN INSERT [ ( <col_name> [ , ... ] ) ] VALUES ( <expr> [ , ... ] )

You could vote for such feature at: https://community.snowflake.com/s/ideas

There is already an item called: "implicit update and insert support for MERGE INTO"

Woodworm answered 29/5, 2021 at 8:34 Comment(0)
S
3

I helped myself by generating the required SET and INSERT clauses from the source table (in the example: events) structure.

In Snowflake, you can achieve this by using DESCRIBE followed by SELECT * FROM TABLE(RESULT_SCAN(LAST_QUERY_ID()), see https://docs.snowflake.com/en/sql-reference/functions/result_scan.

Adjust to your own needs:

DESCRIBE TABLE events;
SELECT  'MERGE INTO events\n' ||
        'USING updates ON events.eventId = updates.eventId\n' || 
        'WHEN MATCHED THEN UPDATE SET\n' ||
        LISTAGG('\t' || "name" || '=updates.' || "name", ',\n') || '\n' ||
        'WHEN NOT MATCHED THEN\n' ||
        '\tINSERT (' || LISTAGG("name", ', ') || ')\n' ||
        '\tVALUES (' || LISTAGG('updates.' || "name", ', ') || ');'
        AS sql
FROM TABLE(RESULT_SCAN(LAST_QUERY_ID()));

Note: depending on your SQL editor / IDE, it might insert its own queries in between, so the query id you need is not necessarily the most recent one, but one or several before. For my setting (dbeaver) RESULT_SCAN(LAST_QUERY_ID(-2)) worked. Of course you can also look up the query id using the snowflake query history.

Saveloy answered 22/9, 2023 at 13:17 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.