将每日Parquet数据合并到Synapse外部表失败,请求排查
问题描述
我每天从数据源提取数据并存储为Parquet格式,已经在Synapse中创建了外部表,想要把每日新提取的数据更新到这个外部表。我通过Notebook创建临时表插入新数据,再尝试合并到原有数据,但操作没成功,相关SQL代码如下:
CREATE TABLE #TempTable ( DATE DATE, SMD INT, ERK VARCHAR(50), LK DATETIME, LDATE DATE, LG DATETIME, K DATETIME, G DATETIME, IZAR INT, BSL INT, PERS INT, WORK_TIME_HOURS DECIMAL(10, 2) ); BULK INSERT #TempTable FROM 'frr/ff_test/*.parquet' WITH ( DATA_SOURCE = 'PersData', FILE_FORMAT = 'ParquetFF' ); MERGE INTO [Gf].[Gon_test] AS target USING TempTable AS source ON target.smand = source.smand WHEN MATCHED THEN UPDATE SET target.DATE = source.DATE, target.LK = source.LK, target.LD = source.LD, target.LG = source.LG, target.K = source.K, target.G = source.G, target.IZAR = source.IZAR, target.BSL = source.SBSL, target.PERS = source.SPERS, target.WORK_TIME_HOURS = source.WORK_TIME_HOURS WHEN NOT MATCHED THEN INSERT ( DATE, SMAND, ERK, LK, LD, LG, KN, G, IZR, BSL, PERS, WORK_TIME ) VALUES ( source.DATE, source.AND, source.ERK, source.LK, source.LD, source.LG, source.K, source.G, source.IZAR, source.BSL, source.PERS, source.WORK_TIME ); DROP TABLE #TempTable;
问题排查与修正建议
代码里存在几个明显错误,加上Synapse外部表本身的操作限制,导致MERGE失败,具体如下:
1. 临时表引用错误
MERGE语句里写的是TempTable,但实际创建的是带#的临时表#TempTable,引用必须完全一致,否则会提示找不到表。
2. 字段名大量不匹配
从代码能看到多处字段对应错误:
- 临时表定义的是
SMD,但MERGE关联条件用的是smand/source.smand,两边字段名对不上 - UPDATE里
target.LD = source.LD,但临时表里只有LDATE没有LD;target.BSL = source.SBSL,临时表里是BSL不是SBSL;target.PERS = source.SPERS,临时表里是PERS而非SPERS - INSERT里
SMAND对应source.AND,临时表里根本没有AND字段,应该是SMD;KN对应source.K、IZR对应source.IZAR、WORK_TIME对应source.WORK_TIME这些都和临时表字段不匹配
3. Synapse外部表的MERGE限制
基于Parquet的外部表通常不支持MERGE操作(尤其是UPDATE),因为外部表本质是存储文件的映射,无法直接更新文件内容。替代方案:
- 先把外部表数据导入Synapse内部表,对内部表执行MERGE后,再按需导回外部存储
- 如果业务允许,采用「追加+定期去重」:先把新数据追加到外部表,再通过CTAS创建去重后的新外部表替换原有表
4. Parquet数据读取方式问题
Synapse中BULK INSERT对Parquet格式的支持有限,更可靠的方式是用OPENROWSET读取Parquet数据到临时表。
修正后的示例代码
-- 创建临时表 CREATE TABLE #TempTable ( DATE DATE, SMD INT, ERK VARCHAR(50), LK DATETIME, LDATE DATE, LG DATETIME, K DATETIME, G DATETIME, IZAR INT, BSL INT, PERS INT, WORK_TIME_HOURS DECIMAL(10, 2) ); -- 改用OPENROWSET读取Parquet数据到临时表 INSERT INTO #TempTable SELECT * FROM OPENROWSET( BULK 'frr/ff_test/*.parquet', DATA_SOURCE = 'PersData', FORMAT = 'PARQUET' ) AS [result]; -- 注意:如果Gon_test是外部表,MERGE不生效,此处假设已转为内部表 MERGE INTO [Gf].[Gon_test] AS target USING #TempTable AS source ON target.SMAND = source.SMD -- 需确认两边关联字段的实际对应关系,此处为示例 WHEN MATCHED THEN UPDATE SET target.DATE = source.DATE, target.LK = source.LK, target.LD = source.LDATE, target.LG = source.LG, target.KN = source.K, target.G = source.G, target.IZR = source.IZAR, target.BSL = source.BSL, target.PERS = source.PERS, target.WORK_TIME = source.WORK_TIME_HOURS WHEN NOT MATCHED THEN INSERT ( DATE, SMAND, ERK, LK, LD, LG, KN, G, IZR, BSL, PERS, WORK_TIME ) VALUES ( source.DATE, source.SMD, source.ERK, source.LK, source.LDATE, source.LG, source.K, source.G, source.IZAR, source.BSL, source.PERS, source.WORK_TIME_HOURS ); DROP TABLE #TempTable;
内容的提问来源于stack exchange,提问作者Mr_Unchained
相关产品推荐
相关产品推荐

