Структура для SQL оператора MERGE в снежинке? - PullRequest
1 голос
/ 26 февраля 2020

В соответствии со снежинкой документы для оператора слияния, я думаю, что следующий запрос будет работать:

MERGE INTO TEST_TABLE AS T 
USING
    (SELECT * FROM (VALUES ('name1', 56.0), ('name2', 29.0))) AS S (USERNAME, BALANCE)
ON T.USERNAME = S.USERNAME
WHEN NOT MATCHED THEN
    INSERT
        (USERNAME, BALANCE)
    VALUES
        (S.USERNAME, S.BALANCE)
WHEN MATCHED THEN
    UPDATE SET
        USERNAME = S.USERNAME, BALANCE = S.BALANCE;

Однако я получаю ошибку

SQL compilation error: error line 4 at position 16
invalid identifier 'S.USERNAME'

Я также попытался наложить псевдоним исходных данных с помощью оператора WITH, например, такого:

WITH S (USERNAME, BALANCE) AS (
    SELECT * FROM (VALUES ('name1', 56.0), ('name2', 29.0))
)
MERGE INTO TEST_TABLE AS T 
USING S
ON T.USERNAME = S.USERNAME
.
.
.

, но это приводит к другой ошибке

SQL compilation error:
syntax error line 4 at position 0 unexpected 'MERGE'.

Может кто-нибудь помочь мне лучше понять и документы, и что я делаю не так?

Ответы [ 3 ]

0 голосов
/ 27 февраля 2020

Есть несколько небольших отличий, но я считаю, что это должно сработать.

 WITH S (USERNAME, BALANCE) AS (
     SELECT USERNAME, BALANCE 
     FROM (VALUES ('name1', 56.0), ('name2', 29.0)) AS S (USERNAME, BALANCE)
 )
 MERGE TEST_TABLE AS T 
 USING S
 ON T.USERNAME = S.USERNAME
 WHEN MATCHED THEN
 UPDATE
 SET T.USERNAME = S.USERNAME
    ,T.BALANCE = S.BALANCE
 WHEN NOT MATCHED BY TARGET THEN
 INSERT (USERNAME, BALANCE)
 VALUES (S.USERNAME, S.BALANCE);
0 голосов
/ 27 февраля 2020

Как вы обнаружили, Snowflake некорректно обрабатывает псевдонимы столбцов для псевдонимов таблиц .

Сравнить (не с вашей ошибкой)

SELECT o.one
FROM (SELECT 1) o(one);

с (работает успешно)

SELECT o.one
FROM (SELECT 1 AS one) o;

Я подозреваю, что если вы развернете SELECT * в именованный список столбцов и измените AS S (USERNAME, BALANCE) на просто AS S, тогда запрос будет скомпилирован.

0 голосов
/ 27 февраля 2020

Вот некоторый код, который у нас есть, который запускается в производство:

MERGE INTO ${db_name~}.${schema~}.AGGREGATION_WATERMARK dst
USING ${db_name~}.${schema~}.EVENT_WATERMARK src ON dst.unit_id = src.unit_id
WHEN NOT MATCHED THEN INSERT (unit_id, time) VALUES (src.unit_id, src.time)
WHEN MATCHED AND src.time < dst.time THEN UPDATE
    SET dst.time = src.time,
    dst._update_time_utc = TO_TIMESTAMP_NTZ(CURRENT_TIMESTAMP);

Может быть, имя столбца не работает для MERGE, но если вы измените внутренний суб-выбор из:

SELECT * FROM (VALUES ('name1', 56.0), ('name2', 29.0))

чтобы назвать столбцы там, например:

SELECT temp.* FROM VALUES ('name1', 56.0), ('name2', 29.0) temp (USERNAME, BALANCE)

тогда, когда вы добавите псевдоним к S, он должен работать?

SELECT * FROM (SELECT temp.* FROM VALUES ('name1', 56.0), ('name2', 29.0) temp (USERNAME, BALANCE)) S;

внешний select * просто там чтобы показать, что работает вне содержания MERGE USING

...