sch*_*iju 3 sql oracle common-table-expression sql-update
我有一个表格,需要使用 Excel 电子表格中的一些数据进行更新。我正在考虑这样的查询:
WITH temp AS(
(SELECT 'abcd' AS oldvalue, 'defg' AS newvalue FROM dual) UNION
(SELECT .....) --About 300 lines of this, copied from Excel and then formatted into the SELECT statement
)
UPDATE mytable
SET name = (SELECT newvalue FROM temp WHERE mytable.name = temp.oldvalue)
Run Code Online (Sandbox Code Playgroud)
但Oracle似乎不喜欢在同一个查询中使用“WITH”和“UPDATE”语句。我收到一条错误消息“缺少 SELECT 关键字”。我发现我可以将临时表定义放在 SELECT 语句中,即
SET name = (SELECT newvalue FROM (
(SELECT 'abcd' AS oldvalue, 'defg' AS newvalue FROM dual) UNION
(SELECT .....)
) temp WHERE mytable.name = temp.oldvalue)
Run Code Online (Sandbox Code Playgroud)
但这是在查询中间定义这样一个表的代码非常非常混乱。我一想到这个就感到畏缩。必须有更好的方法来做到这一点。我应该设置一个全局临时表吗?或者我只是缺少一些简单的语法,可以使其以原始方式工作?
您可以在更新中使用 with 子句;你只需要在正确的地方做:
UPDATE mytable
SET name = (WITH temp AS((SELECT 'abcd' AS oldvalue, 'defg' AS newvalue FROM dual) UNION
(SELECT .....) --About 300 lines of this, copied from Excel and then formatted into the SELECT statement
)
SELECT newvalue
FROM temp
WHERE mytable.name = temp.oldvalue);
Run Code Online (Sandbox Code Playgroud)
但是,您可能只想更新临时子查询中存在的行,因此您需要一个额外的 where 子句:
UPDATE mytable
SET name = (WITH temp AS((SELECT 'abcd' AS oldvalue, 'defg' AS newvalue FROM dual) UNION
(SELECT .....) --About 300 lines of this, copied from Excel and then formatted into the SELECT statement
)
SELECT newvalue
FROM temp
WHERE mytable.name = temp.oldvalue)
WHERE EXISTS (WITH temp AS((SELECT 'abcd' AS oldvalue, 'defg' AS newvalue FROM dual) UNION
(SELECT .....) --About 300 lines of this, copied from Excel and then formatted into the SELECT statement
)
SELECT NULL
FROM temp
WHERE mytable.name = temp.oldvalue);
Run Code Online (Sandbox Code Playgroud)
或者,使用 MERGE 语句:
merge into mytable tgt
using (WITH temp AS((SELECT 'abcd' AS oldvalue, 'defg' AS newvalue FROM dual) UNION
(SELECT .....) --About 300 lines of this, copied from Excel and then formatted into the SELECT statement
)
SELECT mytable.rowid r_id,
temp.newvalue
FROM temp
inner join mytable on mytable.name = temp.oldvalue) src
on (tgt.rowid = src.r_id)
when matched then
update set tgt.name = src.newvalue;
Run Code Online (Sandbox Code Playgroud)
注意,您必须连接到合并语句的源查询中的实际表,因为您正在尝试更新正在连接的列,而您无法在合并语句中执行此操作 - 因此我已经切换了合并连接加入 mytable.rowid。
您必须测试这两个语句,看看哪一个对您的数据性能最佳。