问答中心分类: SQLOracle SQL:用另一个表中的数据更新一个表
0
匿名用户 提问 1月 前

表格1:

id    name    desc
-----------------------
1     a       abc
2     b       def
3     c       adf

表 2:

id    name    desc
-----------------------
1     x       123
2     y       345

在 oracle SQL 中,我如何运行sql更新可以用表 2 更新表 1 的查询namedesc使用相同的id?所以我得到的最终结果是
表格1:

id    name    desc
-----------------------
1     x       123
2     y       345
3     c       adf

问题取自用另一张表的数据更新一张表,但专门针对oracle SQL。

p.campbell 回复 1月 前

您需要回到您的其他问题,不接受该答案,并明确说明您需要 Oracle PLSQL 语法。

p.campbell 回复 1月 前

@p.campbell,那不是我的问题…

p.campbell 回复 1月 前

我懂了。因此,您复制粘贴了问题正文,但进行了修改以包含 Oracle 位。

p.campbell 回复 1月 前

是的。这可能不是最好的例子,因为“desc”是一个保留字,但是哦,好吧。

6 Answers
0
Adrian 回答 1月 前

尝试这个:

MERGE INTO table1 t1
USING
(
-- For more complicated queries you can use WITH clause here
SELECT * FROM table2
)t2
ON(t1.id = t2.id)
WHEN MATCHED THEN UPDATE SET
t1.name = t2.name,
t1.desc = t2.desc;
jefissu 回复 1月 前

确实非常快,1159477 行在 15.5 秒内合并

sjngm 回复 1月 前

我希望在 2015 年之后访问这个问题的每个人都能注意到这个答案。请注意,如果table1table2是同一张桌子,只是照顾ON– 部分和WHERE– 条款SELECT-声明table2

arnehehe 回复 1月 前

我发现每次我需要进行另一次合并时,我都会不断地回到这个答案来寻找灵感。我可能会把它打印出来并装在墙上

davidwillianx 回复 1月 前

像魅力一样工作!谢谢!

Joseph Poirier 回复 1月 前

从表 2 中选择不同的 ID、FIELD1、FIELD1,其中 ID 不为空

Joseph Poirier 回复 1月 前

t1.name = CASE WHEN t2.name 为 NULL THEN t1.name ELSE t2.name END — 当 t2 中不存在任何值时,防止系统清空值。

Lukas 回复 1月 前

使用 MERGE INTO 的解决方案是我最喜欢的,因为它很容易与复杂的子选择而不是简单的表一起使用(t2 可能是带有条件的连接表,聚合……)。代码仍然可读并且处理速度很快。

gridtrak 回复 1月 前

在旧的 Oracle 10g2 中为我工作。

Roland 回复 1月 前

不知道 MERGE 是否是非标准的 Oracle 发明,但它的工作方式比试图强制 UPDATE 完成工作的方法抽象得多

Nicolaesse 回复 1月 前

与其他查询相比,这非常非常快。你能用 WITH 子句改进答案吗?谢谢!

Ak777 回复 1月 前

运行 MERGE 查询时会导致此错误的原因 – “ORA-30926:无法在源表中获得一组稳定的行”,因为我的源表/查询有多个键 ID。我在内部查询或 table2 查询中使用了 distinct select。merge into sa.table1 t1 using (select distinct userid, keylinkflag from table2)src on (t1.userid = src.userid) when matched then update set t1.keylinkflag = src.keylinkflag, t1.manual_linking_flag = 1, t1.link = null WHERE t1.keylinkflag is null;

Ak777 回复 1月 前

我解决了这个问题。这是由于数据重复造成的,我不得不进行分组并添加更多过滤器,以便为每个组合只选择一个。

0
Yahia 回答 1月 前

尝试

UPDATE Table1 T1 SET
T1.name = (SELECT T2.name FROM Table2 T2 WHERE T2.id = T1.id),
T1.desc = (SELECT T2.desc FROM Table2 T2 WHERE T2.id = T1.id)
WHERE T1.id IN (SELECT T2.id FROM Table2 T2 WHERE T2.id = T1.id);
David Balažic 回复 1月 前

这样做的缺点是 SELECT 语句重复了 3 次。在可能会破坏交易的复杂示例中。

0
Pau Karr 回答 1月 前
Update table set column = (select...)

从来没有为我工作过,因为 set 只需要 1 个值 – SQL 错误:ORA-01427:单行子查询返回多于一行。
这是解决方案:

BEGIN
For i in (select id, name, desc from table1) 
LOOP
Update table2 set name = i.name, desc = i.desc where id = i.id;
END LOOP;
END;

这就是您在 SQLDeveloper 工作表上运行它的确切方式。他们说这很慢,但这是在这种情况下对我有用的唯一解决方案。

Pau Karr 回复 1月 前

有人可以解释为什么这值得-2声誉吗?哈哈。

Alternator 回复 1月 前

我没有降价,但这不是一个好的解决方案。首先:如果子选择返回多个值,那么 for 循环将多次覆盖 table2 上的名称,用于某些/所有记录(不干净)。其次:没有 order by 子句,因此这将以不可预测的方式发生(即无序数据中的最后一个值获胜)。第三:它会慢得多。假设 for 循环的结果是预期的,则可以以某种受控方式重写原始子选择,以使每个记录仅返回 1 个值…最简单的人为方式是 (select min(name)…)

Robert Hyatt 回复 1月 前

这正是我所需要的。谢谢(+1)

Francis 回复 1月 前

如果您在子查询中获得多个值,您可能会重新考虑查询并将 DISTINCT 或 GROUP BY 与 MIN、MAX 一起使用。只是一个想法。

Ray K. 回复 1月 前

长话短说:如果你能避免它,永远不要在 T-SQL 语句中使用任何类型的 LOOP。就个人而言,如果没有 0.001% 的时间没有其他解决方案,我什至认为它甚至不应该是 T-SQL 中的可用函数。 T-SQL 被设计为基于集合的,因此它可以将整个数据集作为一个整体工作;它不应该用于逐行处理数据。

0
ant 回答 1月 前

这似乎是一个更好的答案,“in”子句允许连接的多个键

update fp_active set STATE='E', 
   LAST_DATE_MAJ = sysdate where (client,code) in (select (client,code) from fp_detail
  where valid = 1) ...

完整的例子在这里:http://forums.devshed.com/oracle-development-96/how-to-update-from-two-tables-195893.html– 来自网络存档,因为链接已失效。
关键在于在“in”之前的 where 子句中将要用作括号中的键的列放在括号中,并在括号中使用具有相同列名的 select 语句。在哪里 (第 1 列,第 2 列) 在 (选择 (第 1 列,第 2 列) 来自“我想要的集合”的表);

Dumbo 回复 1月 前

链接已过期。 (404)

0
Avila Theresa 回答 1月 前
BEGIN
For i in (select id, name, desc from table2) 
LOOP
Update table1 set name = i.name, desc = i.desc where id = i.id and (name is null or desc is null);
END LOOP;
END;