业务报错:unable to get a stable set of rows in the source table
问题现象
执行MERGE INTO将源表内容根据匹配条件对目标表做更新报错unable to get a stable set of rows in the source table。
现有目标表products和源表newproducts,以源表newproducts中product_id为1502为匹配条件,对目标表进行更新报错:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
CREATE TABLE products (product_id INTEGER,product_name VARCHAR2(60),category VARCHAR2(60)); INSERT INTO products VALUES (1501, 'vivitar 35mm', 'electrncs'),(1502, 'olympus is50', 'electrncs'),(1600, 'play gym', 'toys'); CREATE TABLE newproducts (product_id INTEGER,product_name VARCHAR2(60),category VARCHAR2(60)); INSERT INTO newproducts VALUES (1502, 'olympus camera', 'electrncs'),(1600, 'lamaze', 'toys'),(1502, 'skateboard', 'toy'); MERGE INTO products p USING newproducts np ON (p.product_id = np.product_id) WHEN MATCHED THEN UPDATE SET p.product_name = np.product_name, p.category = np.category WHERE np.product_id = 1502; ERROR: dn_6003_6004: unable to get a stable set of rows in the source tables |
原因分析
源表newproducts中product_id为1502的数据有两条,且参数behavior_compat_options缺省,因此MERGE INTO时匹配到多条数据报错。
MERGE INTO的作用是将源表内容根据匹配条件对目标表做更新或插入,当目标表匹配到多行满足条件时,GaussDB(DWS)有以下两种行为:
- 业务报错:unable to get a stable set of rows in the source table。
- 随机匹配一行数据,可能会导致实际与预期不符。
这两种行为由参数behavior_compat_options控制,当参数behavior_compat_options缺省的情况下,匹配到多行会报错,如果behavior_compat_options被设置为merge_update_multi,则不会报错,而是会随机匹配一行数据。
因此,当出现merge into的结果与预期不符的情况时,需查看该参数是否被设置,同时排查是否匹配了多行数据,并根据实际情况修改业务逻辑。
解决方案
- 方案一:设置参数behavior_compat_options为merge_update_multi。
当目标表匹配到多行满足条件时,该方案不会报错,而是会随机匹配一行数据,有数据遗漏风险。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
SET behavior_compat_options=merge_update_multi; MERGE INTO products p USING newproducts np ON (p.product_id = np.product_id) WHEN MATCHED THEN UPDATE SET p.product_name = np.product_name, p.category = np.category WHERE np.product_id = 1502; MERGE 1 SELECT * FROM products ; product_id | product_name | category ------------+----------------+----------- 1501 | vivitar 35mm | electrncs 1502 | olympus camera | electrncs 1600 | play gym | toys (3 rows)
- 方案二:修改MERGE INTO匹配条件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
MERGE INTO products p USING newproducts np ON (p.product_id = np.product_id) WHEN MATCHED THEN UPDATE SET p.product_name = np.product_name, p.category = np.category WHERE np.product_id != 1502; MERGE 1 SELECT * FROM products; product_id | product_name | category ------------+----------------+----------- 1501 | vivitar 35mm | electrncs 1502 | olympus camera | electrncs 1600 | lamaze | toys (3 rows)