如何从 select 进行 Oracle SQL 更新?
Posted
技术标签:
【中文标题】如何从 select 进行 Oracle SQL 更新?【英文标题】:How do I do an Oracle SQL update from select? 【发布时间】:2019-04-04 14:11:53 【问题描述】:我创建了一个查询,用于从另一个表更新一个表。该字段在给定日期按预期更新。问题是对于其他日期,我现在在我更新的列上获得 NULL 值。如何只为特定日期设置新值而不影响其他日期?
表 A:
| ID | VALUE | ADD_TIME |
-------------------------------------
| 1 | -5 |1/11/2019 10:45:11 am |
表 B:
|AS_OF_DATE| ID | VALUE |
-------------------------
|2/29/2019 | 1 | -4 |
|1/31/2019 | 1 | -4 |
|12/31/2018| 1 | -4 |
期望的输出:
|AS_OF_DATE| ID | VALUE |
-------------------------
|2/29/2019 | 1 | -4 |
|1/31/2019 | 1 | -4 |
|12/31/2018| 1 | -5 |
电流输出:
|AS_OF_DATE| ID | VALUE |
-------------------------
|2/29/2019 | 1 | |
|1/31/2019 | 1 | |
|12/31/2018| 1 | -5 |
我的查询:
update TABLEB
set VALUE =
(
select VALUE from TableA
where ID = '1'
and TABLEB.AS_OF_DATE < TABLEA.ADD_TIME
)
【问题讨论】:
TABLEA
只有一行?比简单的添加 WHERE b.AS_OF_DATE < (select ADD_TIME from TABLEA)
到 UPDATE
请检查您的数据类型:2/29/2019
是无效日期;)
【参考方案1】:
您可以添加exists()
检查,这样不匹配的行就不会更新:
update TABLEB
set VALUE =
(
select VALUE from TABLEA
where ID = '1'
and TABLEB.AS_OF_DATE < TABLEA.ADD_TIME
)
where exists
(
select VALUE from TABLEA
where ID = '1'
and TABLEB.AS_OF_DATE < TABLEA.ADD_TIME
)
1 row updated.
select * from tableb;
AS_OF_DAT ID VALUE
--------- ---------- ----------
28-FEB-19 1 -4
31-JAN-19 1 -4
31-DEC-18 1 -5
我在您的示例数据中将 2/29/2019 更改为 2/28/2019...
假设您确实在两个表中都有多个 ID,因此请在第二列上关联 - 而不是 WHERE ID = '1'
(可能应该是 WHERE ID = 1
!)使用 WHERE TABLEB.ID = TABLEA.ID
。
您也可以使用合并而不是更新,例如:
merge into tableb b
using tablea a
on (a.id = b.id and b.as_of_date < a.add_time)
when matched then update set b.value = a.value;
或
merge into tableb b
using tablea a
on (a.id = b.id)
when matched then update set b.value = a.value
where b.as_of_date < a.add_time;
【讨论】:
谢谢!是的,我有多个 ID,并将对此进行更新。现在,我只是想让一个工作。我很感激:)【参考方案2】:您的方法表明,ID
列是TABLEA
的主键。
请检查这是不是真的,否则你应该注意以下结构:
set VALUE =
(
select VALUE from Table A
where ID = '1'
and TABLE B.AS_OF_DATE < TABLE A.ADD_TIME
)
如果子查询返回多于一行,您将立即看到
ORA-01427: single-row subquery returns more than one row
对于支持TABLEA
的主键,您可以使用原始查询的简单扩展(添加WHERE
谓词):
update TABLEB
set VALUE =
(
select VALUE from TableA
where ID = '1'
and TABLEB.AS_OF_DATE < TABLEA.ADD_TIME
)
where TABLEB.AS_OF_DATE < (select ADD_TIME from TABLEA where ID = '1')
注意,重复行问题与其他答案中提出的MERGE
语句解决方案相关,该解决方案对于TABLEA
中的唯一ID
工作正常且优雅,但在重复ORA-30926: unable to get a stable set of rows in the source tables
上失败ID
s .
【讨论】:
以上是关于如何从 select 进行 Oracle SQL 更新?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 oracle pl sql 中的包主体内的 select 语句中捕获特定列
Oracle SQL If语句使用select进行比较[重复]