DATA BRANCH PICK¶
对具有兼容显式主键的表,把源表中指定的行拣取(cherry-pick)到目标表,无需合并整张表的差异。两张表可以共享 data-branch lineage,也可以是没有 LCA 的独立表。
语法说明¶
DATA BRANCH PICK 在两张具有兼容显式主键的表之间拷贝一个行子集。两张表可以属于同一 data-branch lineage,也可以是没有公共祖先的独立表。它复用 DATA BRANCH DIFF / DATA BRANCH MERGE 的差异计算能力,把作用范围限定到指定的键集或快照窗口,再把 INSERT / DELETE 变更写入目标表。源表使用隐藏 fake PK 时会报错 DATA BRANCH PICK requires a table with a primary key;其他主键不匹配情况会由 schema 兼容性检查拒绝。
该语句适用于选择性同步场景,例如:把单条新数据从测试分支推到主分支、把某次修复回合到另一条分支,或只传播两个快照之间发生的变更。
语法结构¶
DATA BRANCH PICK source_table [{ SNAPSHOT = 'snapshot_name' }]
INTO destination_table
[BETWEEN SNAPSHOT snapshot_from AND snapshot_to]
[KEYS ( key_list | subquery )]
[WHEN CONFLICT conflict_option]
KEYS (...) 和 BETWEEN SNAPSHOT ... AND ... 至少要出现一个。
KEYS 子句¶
key_list ::= expr [, expr ...]
| ( col1_val, col2_val [, ...] ) [, ( ... ) ...]
subquery ::= SELECT ... FROM ...
冲突处理选项¶
conflict_option:
FAIL -- 默认,遇到冲突时报错并终止。
| SKIP -- 保留目标行原值,丢弃本次拣取的 DELETE + INSERT。
| ACCEPT -- 用源行覆盖目标行(删除旧行,插入源行)。
语法释义¶
参数 |
说明 |
|---|---|
|
拣取的源表,可带 |
|
接收拣取数据的已存在目标表。主键和映射列必须与源表兼容,但不要求 schema 完全相同。不允许在目标表上加快照选项。 |
|
要拣取的主键值字面量列表。单列主键时每项为标量;复合主键时每项为 |
|
产出主键值的子查询。复合主键时子查询的列顺序必须与主键列顺序一致,且不允许产出 |
|
将拣取范围限定为半开区间 |
|
当拣取键在目标表已有不同值时报错终止,是省略时的默认行为。 |
|
保留目标表原行,丢弃该键的拣取(不执行 DELETE 或 INSERT)。 |
|
用源表行覆盖目标表行(先删后写)。 |
使用说明¶
要求兼容的显式主键。 源表和目标表都必须具有兼容的显式主键,否则
DATA BRANCH PICK会被拒绝。源表使用隐藏 fake PK 时会报错DATA BRANCH PICK requires a table with a primary key;其他主键不匹配情况会由 schema 兼容性检查拒绝。目标端快照被拒绝。 在
destination_table上加{SNAPSHOT = ...}将报错destination snapshot option is not supported for DATA BRANCH PICK。事务限制。
PICK既拒绝显式BEGIN事务,也拒绝autocommit=0的会话;实际错误为DATA BRANCH MERGE/PICK is not supported in transactions。源表快照选项与
BETWEEN互斥。 同时使用source_table{SNAPSHOT = ...}和BETWEEN SNAPSHOT a AND b将报错BETWEEN SNAPSHOT and source table snapshot option cannot be used together。至少需要一个圈定子句。 同时省略
KEYS与BETWEEN SNAPSHOT将报错DATA BRANCH PICK requires a KEYS or BETWEEN SNAPSHOT clause。默认冲突策略是 FAIL。 未指定
WHEN CONFLICT时,遇到第一个冲突键即中止,并对剩余键不再处理。源中不存在的键视为空操作。 列表中的键如果不在源表(或在
BETWEEN SNAPSHOT窗口内不在源端变更集中),该行被静默跳过。KEYS 子查询约束。 子查询返回列数必须与主键列数一致(单列 PK 返回 1 列,复合 PK 返回 N 列);每行被强转为 PK 类型,不支持的类型报错
KEYS subquery column type X is not supported for primary-key coercion,NULL值报错KEYS subquery returned NULL, but DATA BRANCH PICK primary keys cannot be NULL。复合主键。 复合 PK 的字面量键必须是元组,列数不匹配将报错
KEYS tuple has N elements but composite primary key has M columns。权限。 调用者需要源表的
SELECT、目标表的SELECT以及目标表的INSERT、UPDATE、DELETE;KEYS子查询读取的表也要求SELECT。Schema 兼容性。 源/目标 schema 不要求完全相同。存在显式主键时,可以支持历史 schema 映射和 target-only 列,但映射列的类型、属性、NULL 约束、生成列定义和主键定义必须兼容;不兼容会在应用变更前被拒绝。
示例¶
DROP DATABASE IF EXISTS data_branch_pick_demo;
CREATE DATABASE data_branch_pick_demo;
USE data_branch_pick_demo;
-- 示例 1:从独立源表拣取指定行。
CREATE TABLE t1 (a INT, b INT, PRIMARY KEY(a));
INSERT INTO t1 VALUES (1,1),(3,3),(5,5);
CREATE TABLE t2 (a INT, b INT, PRIMARY KEY(a));
INSERT INTO t2 VALUES (1,1),(2,2),(4,4);
-- 只拣取 pk=2 的行。
DATA BRANCH PICK t2 INTO t1 KEYS(2);
SELECT * FROM t1 ORDER BY a ASC;
-- 继续拣取;源中不存在的键会被忽略。
DATA BRANCH PICK t2 INTO t1 KEYS(4);
DATA BRANCH PICK t2 INTO t1 KEYS(99);
SELECT * FROM t1 ORDER BY a ASC;
DROP TABLE t1;
DROP TABLE t2;
-- 示例 2:WHEN CONFLICT SKIP / ACCEPT 处理冲突。
CREATE TABLE t0 (a INT, b INT, PRIMARY KEY(a));
INSERT INTO t0 VALUES (1,1),(2,2);
DATA BRANCH CREATE TABLE t1 FROM t0;
INSERT INTO t1 VALUES (3,30);
DATA BRANCH CREATE TABLE t2 FROM t0;
INSERT INTO t2 VALUES (3,40);
-- 两个分支都插入了 pk=3 但值不同;默认 FAIL 模式下会报错中止。
-- Expected-Success: false
DATA BRANCH PICK t2 INTO t1 KEYS(3);
-- SKIP 保留 t1 的 (3,30)。
DATA BRANCH PICK t2 INTO t1 KEYS(3) WHEN CONFLICT SKIP;
SELECT * FROM t1 ORDER BY a ASC;
-- ACCEPT 用 t2 的 (3,40) 覆盖。
DATA BRANCH PICK t2 INTO t1 KEYS(3) WHEN CONFLICT ACCEPT;
SELECT * FROM t1 ORDER BY a ASC;
DROP TABLE t0;
DROP TABLE t1;
DROP TABLE t2;
-- 示例 3:通过 KEYS 子查询拣取。
CREATE TABLE t1 (a INT, b INT, PRIMARY KEY(a));
INSERT INTO t1 VALUES (1,1);
CREATE TABLE t2 (a INT, b INT, PRIMARY KEY(a));
INSERT INTO t2 VALUES (1,1),(2,2),(3,3),(4,4),(5,5);
-- 只拣取偶数键对应的行。
DATA BRANCH PICK t2 INTO t1 KEYS(SELECT a FROM t2 WHERE a % 2 = 0);
SELECT * FROM t1 ORDER BY a ASC;
DROP TABLE t1;
DROP TABLE t2;
-- 示例 4:复合主键的元组字面量键。
CREATE TABLE t0 (id INT, name VARCHAR(20), val INT, PRIMARY KEY(id, name));
INSERT INTO t0 VALUES (1,'alice',10),(2,'bob',20);
DATA BRANCH CREATE TABLE t1 FROM t0;
DATA BRANCH CREATE TABLE t2 FROM t0;
INSERT INTO t2 VALUES (4,'dave',40),(5,'eve',50),(6,'frank',60);
-- 拣取三条新行中的两条。
DATA BRANCH PICK t2 INTO t1 KEYS((4,'dave'),(6,'frank'));
SELECT * FROM t1 ORDER BY id, name;
DROP TABLE t0;
DROP TABLE t1;
DROP TABLE t2;
-- 示例 5:按快照时间窗口拣取变更。
DROP SNAPSHOT IF EXISTS sp1;
DROP SNAPSHOT IF EXISTS sp2;
CREATE TABLE t0 (a INT, b INT, PRIMARY KEY(a));
INSERT INTO t0 VALUES (1,1),(2,2),(3,3);
DATA BRANCH CREATE TABLE t1 FROM t0;
CREATE SNAPSHOT sp1 FOR ACCOUNT sys;
INSERT INTO t1 VALUES (4,4),(5,5);
CREATE SNAPSHOT sp2 FOR ACCOUNT sys;
INSERT INTO t1 VALUES (6,6),(7,7);
-- 仅拣取在 sp1 与 sp2 之间发生的变更(pk=4,5);sp2 之后的 pk=6,7 不拣取。
DATA BRANCH PICK t1 INTO t0 BETWEEN SNAPSHOT sp1 AND sp2;
SELECT * FROM t0 ORDER BY a ASC;
-- BETWEEN 可以与 KEYS 组合,取时间窗口与键集合的交集。
DATA BRANCH PICK t1 INTO t0 BETWEEN SNAPSHOT sp1 AND sp2 KEYS(5);
SELECT * FROM t0 ORDER BY a ASC;
DROP SNAPSHOT sp1;
DROP SNAPSHOT sp2;
DROP TABLE t0;
DROP TABLE t1;
DROP DATABASE data_branch_pick_demo;
注意事项¶
DATA BRANCH PICK虽然不是整表快照拷贝,但语句本身具有原子性。使用默认的WHEN CONFLICT FAIL时,任意键冲突都会中止整条语句,之前或之后键的修改都不会保留;SKIP应用非冲突键并保留冲突键的目标行;ACCEPT对冲突键应用源端结果。同时提供
BETWEEN SNAPSHOT和KEYS时,实际拣取集合是两者的交集。拣取一个在目标表存在但在源表不存在的键,为空操作。拣取一个在源表被删除、目标表未变更的键,会把 DELETE 传播到目标表。
WHEN CONFLICT FAIL的错误信息会指出该主键在源端和目标端的冲突操作;INSERT/INSERT只是其中一种形式。