如何从select更新Oracle SQL?

时间:2019-04-04 14:11:54

标签: sql oracle sql-update

我创建了一个查询,用于从另一个表更新一个表。该字段正在按给定日期的期望进行更新。问题在于,对于其他日期,我现在在更新的列上获得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
)

2 个答案:

答案 0 :(得分: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;

答案 1 :(得分:0)

您的方法建议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语句解决方案有关,该解决方案对于ID中唯一的TABLEA可以正常工作,但无法解决{{1 }}在重复的ORA-30926: unable to get a stable set of rows in the source tables上。