Подтвердить что ты не робот

Оператор обновления с использованием предложения

У меня есть script, который использует стек с предложениями для получения некоторого результата, а затем я хочу записать этот результат в таблицу. Я просто не могу опустить голову, может ли кто-нибудь указать мне в правильном направлении?

Здесь приведен упрощенный пример, который указывает, что я хочу сделать:

with comp as (
  select *, 42 as ComputedValue from mytable where id = 1
)
update  t
set     SomeColumn = c.ComputedValue
from    mytable t
        inner join comp c on t.id = c.id 

В реальной ситуации есть немало статей с предложениями о том, что все ссылки друг на друга, поэтому любые предложения, на самом деле использующие предложение with, были бы крайне предпочтительны при реорганизации его в вложенные подзапросы.

Спасибо заранее,

Герт-Ян

4b9b3361

Ответ 1

Если кто-то приходит сюда после меня, это ответ, который сработал у меня.

update mytable t
set z = (
  with comp as (
    select b.*, 42 as computed 
    from mytable t 
    where bs_id = 1
  )
  select c.computed
  from  comp c
  where c.id = t.id
)

Удачи,

ГДж

Ответ 2

Синтаксис WITH представляется действительным во встроенном представлении, например

UPDATE (WITH comp AS ...
        SELECT SomeColumn, ComputedValue FROM t INNER JOIN comp ...)
   SET SomeColumn=ComputedValue;

Но в быстрых тестах я всегда проигрывал с ORA-01732: data manipulation operation not legal on this view, хотя это удалось, если я переписал, чтобы исключить предложение WITH. Таким образом, рефакторинг может помешать возможности Oracle гарантировать сохранение ключей.

Однако вы должны иметь возможность использовать MERGE. Используя простой пример, который вы опубликовали, даже не требует предложения WITH:

MERGE INTO mytable t
USING (select *, 42 as ComputedValue from mytable where id = 1) comp
ON (t.id = comp.id)
WHEN MATCHED THEN UPDATE SET SomeColumn=ComputedValue;

Но я понимаю, что у вас более сложный подзапрос, который вы хотите отменить. Я думаю, что вы сможете сделать подзапрос в предложении USING произвольно сложным, включая несколько предложений WITH.

Ответ 3

Вы всегда можете сделать что-то вроде этого:

update  mytable t
set     SomeColumn = c.ComputedValue
from    (select *, 42 as ComputedValue from mytable where id = 1) c
where t.id = c.id 

Теперь вы можете также использовать с выражением внутри обновления

update  mytable t
set     SomeColumn = c.ComputedValue
from    (with abc as (select *, 43 as ComputedValue_new from mytable where id = 1
         select *, 42 as ComputedValue, abc.ComputedValue_new  from mytable n1
           inner join abc on n1.id=abc.id) c
where t.id = c.id