基本 MERGE 示例
在此示例中,合并操作涉及两个表:
-
visits_daily
记录每日餐厅流量,并随着每次顾客到访而更新。此表中的数据每 24 小时刷新一次。 -
visits_history
存储顾客到访各个餐厅的历史记录(无限期累计)。
每天晚上,您都会将 visits_daily
的每日到访计数合并到 visits_history
。合并操作通过两种方式修改目标表:
-
更新现有顾客数据。
-
为首次到访的顾客插入新数据行。
一个 MERGE
语句将这两项操作作为单个 (upsert) 事务来执行。
源表和目标表
源表和目标表 visits_daily
和 visits_history
定义如下:
CREATE TABLE public.visits_daily
(
customer_id int,
location_name varchar(20),
visit_time time(0) DEFAULT (now())::timetz(6)
);
CREATE TABLE public.visits_history
(
customer_id int,
location_name varchar(20),
visit_count int
);
表 visits_history
包含三个顾客行,他们分别到访了 Etoile 和 LaRosa 两家餐厅:
=> SELECT * FROM visits_history ORDER BY customer_id, location_name;
customer_id | location_name | visit_count
-------------+---------------+-------------
1001 | Etoile | 2
1002 | La Rosa | 4
1004 | Etoile | 1
(3 rows)
到营业结束时,表 visits_daily
包含三行餐厅到访数据:
=> SELECT * FROM visits_daily ORDER BY customer_id, location_name;
customer_id | location_name | visit_time
-------------+---------------+------------
1001 | Etoile | 18:19:29
1003 | Lux Cafe | 08:07:00
1004 | La Rosa | 11:49:20
(3 rows)
表数据合并
以下 MERGE
语句将 visits_daily
数据合并到 visits_history
中:
-
对于匹配的顾客,
MERGE
会更新出现计数。 -
对于不匹配的顾客,
MERGE
会插入新行。
=> MERGE INTO visits_history h USING visits_daily d
ON (h.customer_id=d.customer_id AND h.location_name=d.location_name)
WHEN MATCHED THEN UPDATE SET visit_count = h.visit_count + 1
WHEN NOT MATCHED THEN INSERT (customer_id, location_name, visit_count)
VALUES (d.customer_id, d.location_name, 1);
OUTPUT
--------
3
(1 row)
MERGE
返回已更新和插入的行数。在本例中,返回值指定三个更新和插入项:
-
顾客
1001
第三次到访 Etoile -
新顾客
1003
首次到访新餐厅 Lux Cafe -
客户
1004
首次到访 La Rosa
如果现在查询表 visits_history
,结果集会显示合并(更新和插入)的数据。更新行和新行高亮显示: