2011-03-21 3 views
35

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

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

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 

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

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

Герт-Ян

+2

FYI: Вы не должны изменить название и вопрос, чтобы указать на то, что вы ответили сами. Просто добавьте свое решение в качестве своего собственного ответа и выберите его, если он лучший. –

+0

Хорошо, сделал это, не могу отметить это, как ответил еще. Благодаря! – gjvdkamp

+0

Я также искал ответа, и я нашел его здесь: http://stackoverflow.com/questions/7030699/oracle-sql-update-with-data-from-another-table – Bogdan

ответ

36

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

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 
) 

Успехов,

GJ

+3

Не будет ли это обновлять все строки? Если есть строки, где c.id <> t.id, они не будут установлены в нуль? Кто-нибудь знает, как поставить это предложение снаружи тоже? –

+0

Не используйте Oracle больше, и это было некоторое время назад. Попробуйте и сообщите нам ;-) IIRC это сработало для меня. – gjvdkamp

+0

@gjvdkamp это работает так же, как Санджай Намбиар сказал: обновление работает с выбранными строками, но все остальные строки, которые находятся вне «где», равны нулю. [2] Кто-нибудь знает способ поставить это предложение снаружи тоже? – robsonrosa

24

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

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

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

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.

+1

Привет, большое спасибо за ваши усилия, уже удалось запустить его. У операторов, которые я использую, есть довольно много уровней, которые вычисляют средние значения и stddevs, а затем использует, что никакие нормализованные (статистически) данные из других таблиц и т. Д. Не будут реальной болью для рефакторинга. В качестве примера можно привести только синтаксис обновления. – gjvdkamp

Смежные вопросы