Lakehouse Upsert 操作指南(MERGE INTO)

概述

在数据仓库中,经常需要根据源数据更新或插入目标表(即 Upsert 操作)。云器 Lakehouse 提供

MERGE INTO
MERGE INTO
语句,支持在一条 SQL 中同时处理匹配行的更新和不匹配行的插入。本指南按业务场景分类,帮助你快速掌握高效的数据合并方法。

涉及的 SQL 命令

命令用途适用场景
MERGE INTO ... WHEN MATCHED THEN UPDATE
MERGE INTO ... WHEN MATCHED THEN UPDATE
匹配时更新数据同步、状态更新
MERGE INTO ... WHEN NOT MATCHED THEN INSERT
MERGE INTO ... WHEN NOT MATCHED THEN INSERT
不匹配时插入新增数据写入
MERGE INTO ... WHEN MATCHED THEN DELETE
MERGE INTO ... WHEN MATCHED THEN DELETE
匹配时删除清理失效数据

前置准备

以下示例使用模拟的库存表

inventory
inventory
(目标表)和
daily_stock
daily_stock
(源表):

-- 创建目标表 CREATE TABLE IF NOT EXISTS inventory ( product_id INT, product_name STRING, stock INT, last_updated DATE ); -- 创建源表 CREATE TABLE IF NOT EXISTS daily_stock ( product_id INT, new_stock INT, update_date DATE ); -- 插入初始数据 INSERT INTO inventory VALUES (1, 'iPhone 15', 100, '2024-06-01'), (2, 'MacBook Pro', 50, '2024-06-01'); -- 插入每日库存数据 INSERT INTO daily_stock VALUES (1, 120, '2024-06-02'), -- 更新现有产品 (3, 200, '2024-06-02'); -- 新增产品


基础 Upsert

最常见的场景:根据主键匹配,存在则更新,不存在则插入。

-- 合并每日库存数据到库存表 MERGE INTO inventory AS target USING daily_stock AS source ON target.product_id = source.product_id WHEN MATCHED THEN UPDATE SET target.stock = source.new_stock, target.last_updated = source.update_date WHEN NOT MATCHED THEN INSERT (product_id, product_name, stock, last_updated) VALUES (source.product_id, 'New Product', source.new_stock, source.update_date);

结果验证

SELECT * FROM inventory ORDER BY product_id;

product_idproduct_namestocklast_updated
1iPhone 151202024-06-02
2MacBook Pro502024-06-01
3New Product2002024-06-02

条件更新

仅在满足特定条件时执行更新操作,避免无效写入。

-- 仅当新库存大于旧库存时才更新 MERGE INTO inventory AS target USING daily_stock AS source ON target.product_id = source.product_id WHEN MATCHED AND source.new_stock > target.stock THEN UPDATE SET target.stock = source.new_stock, target.last_updated = source.update_date WHEN NOT MATCHED THEN INSERT (product_id, product_name, stock, last_updated) VALUES (source.product_id, 'New Product', source.new_stock, source.update_date);

结果说明

  • product_id = 1
    product_id = 1
    :新库存 120 > 旧库存 120(上次已更新),不满足条件,不更新。
  • product_id = 3
    product_id = 3
    :不匹配,插入新记录。

仅插入新数据

忽略已存在的记录,仅插入源表中新增的数据(类似

INSERT IGNORE
INSERT IGNORE
)。

-- 仅插入不匹配的记录 MERGE INTO inventory AS target USING daily_stock AS source ON target.product_id = source.product_id WHEN NOT MATCHED THEN INSERT (product_id, product_name, stock, last_updated) VALUES (source.product_id, 'New Product', source.new_stock, source.update_date);


删除孤立数据

当源数据中标记为删除时,从目标表中移除对应记录。

-- 假设 daily_stock 中 stock = 0 表示下架 MERGE INTO inventory AS target USING daily_stock AS source ON target.product_id = source.product_id WHEN MATCHED AND source.new_stock = 0 THEN DELETE WHEN NOT MATCHED THEN INSERT (product_id, product_name, stock, last_updated) VALUES (source.product_id, 'New Product', source.new_stock, source.update_date);


多条件匹配

使用复杂的

ON
ON
条件进行匹配,适用于复合主键或业务逻辑匹配。

-- 按产品 ID 和日期匹配 MERGE INTO inventory AS target USING daily_stock AS source ON target.product_id = source.product_id AND target.last_updated < source.update_date WHEN MATCHED THEN UPDATE SET target.stock = source.new_stock, target.last_updated = source.update_date WHEN NOT MATCHED THEN INSERT (product_id, product_name, stock, last_updated) VALUES (source.product_id, 'New Product', source.new_stock, source.update_date);


清理测试数据

完成 Upsert 验证后,建议清理测试表:

-- 删除测试表 DROP TABLE IF EXISTS inventory; DROP TABLE IF EXISTS daily_stock;


注意事项

  1. 子句顺序
    WHEN MATCHED
    WHEN MATCHED
    必须在
    WHEN NOT MATCHED
    WHEN NOT MATCHED
    之前,否则语法报错。
  2. 唯一性要求
    ON
    ON
    条件应保证源表每行最多匹配目标表一行,否则可能产生非确定性结果。
  3. 动态表限制:Dynamic Table 不支持直接
    MERGE INTO
    MERGE INTO
    ,建议使用
    DELETE + INSERT
    DELETE + INSERT
    替代。
  4. 性能优化:确保
    ON
    ON
    条件中的列有索引或分区,可显著提升匹配效率。

相关文档

联系我们
预约咨询
微信咨询
电话咨询