Как мне сделать обновление Oracle SQL из избранных? - PullRequest
1 голос
/ 04 апреля 2019

Я создал запрос на обновление таблицы из другой таблицы.Поле обновляется, как ожидается, на указанную дату.Проблема в том, что для других дат я теперь получаю значения 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 ]

1 голос
/ 04 апреля 2019

Вы можете добавить проверку 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

Я изменил 29.02.2009 на 28.02.2009 в вашемпример данных ...

Предположительно у вас действительно есть несколько идентификаторов в обеих таблицах, поэтому сопоставьте эти два столбца - вместо 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;
0 голосов
/ 05 апреля 2019

Ваш подход предполагает, что столбец 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, но не работает с ORA-30926: unable to get a stable set of rows in the source tables в дублированных ID s. .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...