雪花合并插入和更新 table

snowflake incorporate insert and update to a table

我有如下三个雪花 tables(TEST1, TEST2, CONTROL)。

测试 1

create OR REPLACE table TEST1 (
  id varchar(100), 
  name varchar(100),
  address VARCHAR(64)
);    

INSERT INTO TEST1 values (100, 'ABC', null);
INSERT INTO TEST1 values (200, 'XYZ', null);
INSERT INTO TEST1 values (300, 'VBN', null);

测试 2

create OR REPLACE table TEST2 (
  id varchar(100), 
  name varchar(100),
  address VARCHAR(64)
);    

INSERT INTO TEST2 values (100, 'ABC', null);
INSERT INTO TEST2 values (200, 'FDS', null);

控制

create OR REPLACE table CONTROL (
  KEY_COLUMNS VARCHAR,
  TABLE_NAME_SOURCE VARCHAR,
  TABLE_NAME_TARGET VARCHAR
);    

INSERT INTO CONTROL values ('id,name,address', 'TEST2','TEST1');
  1. 我想根据 'TEST1' table.If 记录在 TEST2 中不存在,将插入和更新合并到 'TEST2',那么存储过程应该将行插入到来自测试 1

    的测试 2
  2. 如果TEST1有任何更新,应该在TEST2中捕获。

我的存储过程如下所示。我已经声明了来自控件 table 的变量。我的脚本完全可以正常插入。

对于更新,它应该将 KEY_COLUMNS 中指定的所有列从 TEST1 更新到 TEST2。我可以硬编码和更新(以粗体突出显示),但我想使用控件 table 中的 KEY_COLUMN 列,就像我为插入类似内容所做的那样 (WHEN MATCHED THEN update set target_columns = source_columns).

CREATE OR REPLACE PROCEDURE SP() 
    RETURNS string
    LANGUAGE SQL
    AS
    $$  
    DECLARE
           source_tbl STRING := (select TABLE_NAME_SOURCE from CONTROL);
           source_columns STRING;
           target_columns STRING;
           query1 STRING;
     BEGIN
          SELECT KEY_COLUMNS INTO :source_columns FROM CONTROL WHERE TABLE_NAME_SOURCE = :source_tbl;
          SELECT KEY_COLUMNS INTO :target_columns FROM CONTROL WHERE TABLE_NAME_SOURCE = :source_tbl;
          QUERY1 := 'MERGE INTO TEST2 AS A 
                    USING (
                      select '|| :source_columns ||' from TEST1) AS B 
                    ON A.ID=B.ID 
                    WHEN NOT MATCHED THEN INSERT ('|| :target_columns ||') 
                    values ('|| :source_columns ||')
                    **WHEN MATCHED THEN update set A.ID=B.ID, A.name=B.name, A.address=B.address**;';
           EXECUTE IMMEDIATE :QUERY1;

           RETURN :QUERY1;
      END;
      $$;
      
call SP();

预期的 TEST2 输出

您可以尝试使用从以下查询中获取的值构建您的更新语句合并字符串 -

SNOWFLAKE1#COMPUTE_WH@TEST_DB.PUBLIC>select * from control;
+-----------------+-------------------+-------------------+
| KEY_COLUMNS     | TABLE_NAME_SOURCE | TABLE_NAME_TARGET |
|-----------------+-------------------+-------------------|
| id,name,address | TEST2             | TEST1             |
+-----------------+-------------------+-------------------+
1 Row(s) produced. Time Elapsed: 0.156s
SNOWFLAKE1#COMPUTE_WH@TEST_DB.PUBLIC>select listagg(concat('A.',value,'=','B.',value),',') as set_upd from (select * fr
                                     om control, lateral split_to_table(control.key_columns,','));
+---------------------------------------------+
| SET_UPD                                     |
|---------------------------------------------|
| A.id=B.id,A.name=B.name,A.address=B.address |
+---------------------------------------------+
1 Row(s) produced. Time Elapsed: 0.185s

你想要一个新声明。

SELECT listagg(' A.'||s.value||'=B.'||s.value, ',') FROM CONTROL, TABLE(SPLIT_TO_TABLE(KEY_COLUMNS, ',')) s WHERE TABLE_NAME_SOURCE = 'TEST2';

给出:

LISTAGG(' A.'||S.VALUE||'=B.'||S.VALUE, ',')
A.id=B.id, A.name=B.name, A.address=B.address

这样你的SP就变成了:

CREATE OR REPLACE PROCEDURE SP() 
    RETURNS string
    LANGUAGE SQL
    AS
    $$  
    DECLARE
           source_tbl STRING := (select TABLE_NAME_SOURCE from CONTROL);
           source_columns STRING;
           target_columns STRING;
           update_sets STRING;
           query1 STRING;
     BEGIN
          SELECT KEY_COLUMNS INTO :source_columns FROM CONTROL WHERE TABLE_NAME_SOURCE = :source_tbl;
          SELECT KEY_COLUMNS INTO :target_columns FROM CONTROL WHERE TABLE_NAME_SOURCE = :source_tbl;
          SELECT listagg(' A.'||s.value||'=B.'||s.value, ',') INTO :update_sets FROM CONTROL, TABLE(SPLIT_TO_TABLE(KEY_COLUMNS, ',')) s WHERE TABLE_NAME_SOURCE = :source_tbl;;
          
          QUERY1 := 'MERGE INTO TEST2 AS A 
                    USING (
                      select '|| :source_columns ||' from TEST1) AS B 
                    ON A.ID=B.ID 
                    WHEN NOT MATCHED THEN INSERT ('|| :target_columns ||') 
                    values ('|| :source_columns ||')
                    WHEN MATCHED THEN update set '|| :update_sets ||';';
           EXECUTE IMMEDIATE :QUERY1;

           RETURN :QUERY1;
      END;
      $$;

哪个returns

SP
MERGE INTO TEST2 AS A USING ( select id,name,address from TEST1) AS B ON A.ID=B.ID WHEN NOT MATCHED THEN INSERT (id,name,address) values (id,name,address) WHEN MATCHED THEN update set A.id=B.id, A.name=B.name, A.address=B.address;