Snowflake使用INSERT ALL做多表去重插入的子查询报错问题咨询
问题根因
Snowflake的INSERT ALL语句的WHEN分支条件不支持逐行关联子查询,你前两次的写法触发了语法限制,分别导致编译错误和内部执行错误。你最后能运行的写法逻辑存在缺陷:只要CSV中存在任意一条不重复记录,就会将所有CSV记录全部插入,实际无法实现逐行去重的需求,后续插入重复主键时依然会报错。
解决方案
方案1:保留INSERT ALL实现多表并行插入(适配多表不同匹配逻辑需求)
提前将CSV数据和所有目标表的主键做关联判断,将判断结果作为字段传入INSERT ALL的上层逻辑,WHEN条件仅做简单的字段值判断即可,避免在WHEN中写子查询:
INSERT ALL -- 单表插入判断条件,可扩展多个不同表的WHEN分支 WHEN temp_exist_flag = 0 THEN INTO TEMP (PKEY, TITLE) VALUES (ID, TITLE_NAME) -- 示例:新增第二张表的插入分支,判断逻辑独立 WHEN table2_exist_flag = 0 AND ID > 100 THEN INTO TABLE2 (PKEY, CONTENT) VALUES (ID, TITLE_NAME) WITH csv_raw AS ( -- 第一步读取CSV源数据 SELECT $1 AS ID, $2 AS TITLE_NAME FROM @azure_stg/mti_test.csv (FILE_FORMAT=>'GENERIC_CSV_FORMAT') ), pre_check AS ( -- 第二步提前关联所有目标表,预计算每条记录是否需要插入对应表 SELECT c.ID, c.TITLE_NAME, -- 目标表TEMP的存在性判断:1=已存在,0=不存在 IFF(t.pkey IS NOT NULL, 1, 0) AS temp_exist_flag, -- 其他目标表的判断逻辑同理自定义 IFF(t2.pkey IS NOT NULL, 1, 0) AS table2_exist_flag FROM csv_raw c LEFT JOIN TEMP t ON c.ID = t.pkey LEFT JOIN TABLE2 t2 ON c.ID = t2.pkey -- 可加全局过滤条件,排除不需要处理的记录 WHERE c.ID IS NOT NULL ) SELECT ID, TITLE_NAME, temp_exist_flag, table2_exist_flag FROM pre_check;
该方案完全兼容你多表并行插入、各表匹配逻辑不同的需求,额外的排除逻辑可以在pre_check的关联条件、过滤条件中灵活添加。
方案2:单表插入用MERGE(更简洁)
如果仅处理单表插入,直接用Snowflake原生的MERGE语句即可实现存在性判断插入,语法更简洁:
MERGE INTO TEMP t USING ( SELECT $1 AS ID, $2 AS TITLE_NAME FROM @azure_stg/mti_test.csv (FILE_FORMAT=>'GENERIC_CSV_FORMAT') -- 额外排除逻辑直接在这里加过滤条件 WHERE $1 > 0 ) s -- 匹配逻辑可自定义 ON t.pkey = s.ID WHEN NOT MATCHED THEN INSERT (pkey, title) VALUES (s.ID, s.TITLE_NAME);
内容的提问来源于stack exchange,提问作者alim1990
相关产品推荐
相关产品推荐

