执行MERGE INTO时报错‘DML操作检测到重复行’但未发现重复行
问题描述
我正在基于ID列对mytable执行MERGE INTO操作,SQL语句如下:
MERGE INTO mytable AS m USING ( SELECT CURRENT_TIMESTAMP::TIMESTAMP_LTZ AS col1, METADATA$FILENAME AS col2, METADATA$FILE_ROW_NUMBER AS col3, TO_DATE(REGEXP_SUBSTR(METADATA$FILENAME, '\\d{8}'), 'YYYYMMDD') AS col4, $1 AS col5, $2 AS col6 ... FROM @deve/20221005.csv (file_format => 'our_file_format') ) AS s ON m.Id = s.col6 WHEN MATCHED THEN UPDATE SET m.x = s.col1, m.y = s.col2, m.z = s.col3, m.w = s.col4, x1 = s.col5, m.Id = s.col6, ... WHEN NOT MATCHED THEN INSERT (x, y, z, w, x1, Id ... ) VALUES (s.col1, s.col2, s.col3, s.col4, s.col5, s.col6, ...);
我在Snowflake中检查了报错信息里的ID,发现mytable中仅存在1条该ID的记录,并非多条。请问出现该报错的其他原因是什么,以及有什么解决办法?
可能原因及解决办法
原因1:源数据集存在重复ID
MERGE INTO的“匹配到多条记录”报错,不一定是目标表mytable有重复,源查询(USING子句)的结果中同一个ID可能出现多次。比如导入的CSV文件里,$2(对应s.col6)存在重复值,导致源查询返回多条相同col6的记录,和目标表的单条记录匹配时,就会触发无法更新的错误。
解决办法:
- 先排查源数据是否有重复:执行以下SQL筛选报错ID的记录,确认重复情况:
SELECT col6, COUNT(*) FROM ( SELECT CURRENT_TIMESTAMP::TIMESTAMP_LTZ AS col1, METADATA$FILENAME AS col2, METADATA$FILE_ROW_NUMBER AS col3, TO_DATE(REGEXP_SUBSTR(METADATA$FILENAME, '\\d{8}'), 'YYYYMMDD') AS col4, $1 AS col5, $2 AS col6 ... FROM @deve/20221005.csv (file_format => 'our_file_format') ) WHERE col6 = '报错的ID值' GROUP BY col6 HAVING COUNT(*) > 1;
- 根据业务逻辑对源数据去重,比如保留每个ID的最后一行记录,修改USING子查询:
USING ( SELECT col1, col2, col3, col4, col5, col6 FROM ( SELECT CURRENT_TIMESTAMP::TIMESTAMP_LTZ AS col1, METADATA$FILENAME AS col2, METADATA$FILE_ROW_NUMBER AS col3, TO_DATE(REGEXP_SUBSTR(METADATA$FILENAME, '\\d{8}'), 'YYYYMMDD') AS col4, $1 AS col5, $2 AS col6, ROW_NUMBER() OVER(PARTITION BY col6 ORDER BY METADATA$FILE_ROW_NUMBER DESC) AS rn FROM @deve/20221005.csv (file_format => 'our_file_format') ) WHERE rn = 1 ) AS s
原因2:匹配条件存在隐式类型转换
如果mytable.Id和s.col6的数据类型不一致(比如一个是INT,一个是VARCHAR),Snowflake的隐式转换可能导致同一个ID被意外匹配多次,或者转换后出现不符合预期的匹配结果。
解决办法:
- 检查两者的数据类型:
-- 查看目标表Id列类型 SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'MYTABLE' AND COLUMN_NAME = 'ID'; -- 查看源数据col6的类型 SELECT $2, TYPEOF($2) FROM @deve/20221005.csv (file_format => 'our_file_format') LIMIT 10;
- 显式转换类型,确保匹配条件两边类型一致:
-- 假设Id是INT类型,将col6转为INT ON m.Id = CAST(s.col6 AS INT)
原因3:UPDATE子句修改了匹配条件字段
你的UPDATE语句中包含m.Id = s.col6,虽然匹配条件已经是m.Id = s.col6,但修改该字段属于冗余操作,还可能在Snowflake的执行逻辑中引发冲突,导致报错。
解决办法:
移除UPDATE子句中对m.Id的赋值:
WHEN MATCHED THEN UPDATE SET m.x = s.col1, m.y = s.col2, m.z = s.col3, m.w = s.col4, x1 = s.col5 ...
内容的提问来源于stack exchange,提问作者KristiLuna
相关产品推荐
相关产品推荐

