我有两张这样的桌子。我想更新table_1.column_b 如果 table_1.column_a = table_2.column_a
TABLE_1
column_a | column_b
----------------------------
X1 | 0
X2 | 0
X3 | 0
X4 | 0
X5 | 0
TABLE_2
column_a
--------
X1
X2
X3
结果应该是:
TABLE_1
column_a | column_b
----------------------------
X1 | 1
X2 | 1
X3 | 1
X4 | 0
X5 | 0
答案 0 :(得分:1)
update table_1
set column_b =
(
select count(*)
from table_2 s
where table_1.column_a = s.column_a
)
/* oracle can bug out when a subquery returns nothing, i.e. Null */
where exists
(
select 1
from table_2 s
where table_1.column_a = s.column_a
)
;
有关存在的选择1的额外信息。这只是我倾向于添加的内容,以防万一。这是防御性的编程。
不完全确定需要它,在这种特殊情况下,因为我假设count(*)子查询将为上面表a中的X4和X5条目返回0。
假设您正在这样做...(选择中的1不是真正的下面并不重要,如果你有一个,它可以是table_2中的任何数字或数字列)。重要的是我们这次没有进行计数(*)因此X4和X5不会从table_2中得到任何东西。
update table_1
set column_b =
(select 1
from table_2 s
where table_1.column_a = s.column_a
)
在这种情况下,X4和X5将不会获得子查询结果,Oracle将尝试为table_1.column_b为这些行分配null。 如果该列设置为NOT NULL,则会出现错误。
通过添加查询末尾的where存在,您告诉Oracle不要尝试更新table_1,其中没有匹配的table_2行。所以这个更新null问题永远不会发生。
样板的基本思想是在需要更新列时首先验证更新子查询。然后重复条件作为查询结尾处存在的位置,以避免Oracle在子查询未返回任何内容的情况下尝试更新。
请注意,我可以在where子查询中保留count()。除了我只是寻找匹配行的存在而我实际上并不感兴趣的是计数(),所以我通过要求Oracle选择“更便宜”的结果集来优化一点。
如果您有多个具有不同子查询条件的列更新,那么这将无效。您必须将更新拆分为不同的查询。或者使用Oracle NVL(https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions105.htm)来捕获NULL并替换它们。
答案 1 :(得分:0)
这是一种可能的解决方案:
update table_1 a
set a.column_b = 1
where a.column_a in (select * from table_2);