Oracle无公共键时,如何按行号从另一表更新指定列?
Oracle 按行号匹配更新 table1 的 cst_id 字段
你的 MERGE 语句执行后出现「0 row merge」的原因是逻辑错误:你在 USING 子查询中获取的是 table2 的 ROWID,然后试图和 table1 的 ROWID 匹配。但 ROWID 是 Oracle 中表行的唯一标识符,不同表的 ROWID 完全无关联,自然无法匹配到任何行。
下面是两种正确的实现方法:
方法一:使用 MERGE 语句(推荐)
通过给两个表分别生成行号,再按行号关联更新:
MERGE INTO table1 t1 USING ( -- 给 table1 生成行号(按 item 排序保证与期望顺序一致) SELECT t1_rid, t1_rn, t2_cst_id FROM ( SELECT ROWID AS t1_rid, ROW_NUMBER() OVER (ORDER BY item) AS t1_rn FROM table1 ) t1_with_rn -- 关联 table2 按 age 排序后的行号,仅取匹配的前5行 JOIN ( SELECT cst_id AS t2_cst_id, ROW_NUMBER() OVER (ORDER BY age) AS t2_rn FROM table2 ) t2_with_rn ON t1_with_rn.t1_rn = t2_with_rn.t2_rn ) merged_data ON (t1.ROWID = merged_data.t1_rid) WHEN MATCHED THEN UPDATE SET t1.cst_id = merged_data.t2_cst_id;
方法二:使用 UPDATE 语句
通过子查询生成行号并关联:
UPDATE table1 t1 SET cst_id = ( -- 获取 table2 中对应行号的 cst_id SELECT t2.cst_id FROM ( SELECT cst_id, ROW_NUMBER() OVER (ORDER BY age) AS rn FROM table2 ) t2 WHERE t2.rn = ( -- 获取当前 table1 行的行号(按 item 排序) SELECT ROW_NUMBER() OVER (ORDER BY item) AS rn FROM table1 t1_sub WHERE t1_sub.ROWID = t1.ROWID ) ) -- 仅更新有对应行号的行,避免 table2 行数不足时更新为 NULL WHERE EXISTS ( SELECT 1 FROM ( SELECT ROW_NUMBER() OVER (ORDER BY age) AS rn FROM table2 ) t2 WHERE t2.rn = ( SELECT ROW_NUMBER() OVER (ORDER BY item) AS rn FROM table1 t1_sub WHERE t1_sub.ROWID = t1.ROWID ) );
关键说明
- 行号排序规则:
- 对
table2按age排序生成行号,与你原语句逻辑一致; - 对
table1用ORDER BY item保证行顺序与期望结果一致(book→copy→pen→tea→glass),若无需特定顺序,可改用ORDER BY NULL,但 Oracle 中该排序的行顺序不固定,建议指定明确字段。
- 对
- 行数匹配:由于
table2行数(7行)多于table1(5行),关联后仅会更新table1的5行,对应table2按age排序的前5条数据。
内容的提问来源于stack exchange,提问作者M_Gh
相关产品推荐
相关产品推荐

