Обновление оператора с внутренним соединением в Oracle

246

У меня есть запрос, который отлично работает в MySQL, но когда я запускаю его в Oracle, я получаю следующую ошибку:

Ошибка SQL: ORA-00933: команда SQL не была закончена.
00933. 00000 -" Команда SQL не выполнена должным образом"

Запрос:

UPDATE table1
INNER JOIN table2 ON table1.value = table2.DESC
SET table1.value = table2.CODE
WHERE table1.UPDATETYPE='blah';
  • 0
    Когда я попытался настроить table2 в Oracle для проверки своего ответа, я обнаружил, что Oracle отклонил DESC как имя столбца.
  • 0
    Извините, я только что сократил оригинальное имя столбца, чтобы desc его явно не то, что в БД
Теги:
inner-join
ora-00933

14 ответов

331
Лучший ответ

Этот синтаксис недействителен в Oracle. Вы можете сделать это:

UPDATE table1 SET table1.value = (SELECT table2.CODE
                                  FROM table2 
                                  WHERE table1.value = table2.DESC)
WHERE table1.UPDATETYPE='blah'
AND EXISTS (SELECT table2.CODE
            FROM table2 
            WHERE table1.value = table2.DESC);

Или вы могли бы это сделать:

UPDATE 
(SELECT table1.value as OLD, table2.CODE as NEW
 FROM table1
 INNER JOIN table2
 ON table1.value = table2.DESC
 WHERE table1.UPDATETYPE='blah'
) t
SET t.OLD = t.NEW

(Это зависит от того, считается ли встроенное представление обновленным Oracle).

  • 1
    Я пишу аналогичный запрос, переносимый между dbms: oracle считает, что встроенное представление является обновляемым, но mysql не
  • 5
    Я сделал второй пример, но мне пришлось добавить псевдонимы к именам столбцов в select, а затем ссылаться на них по их именам в SET, но это сработало, спасибо
Показать ещё 13 комментариев
180

Использовать этот:

MERGE
INTO    table1 trg
USING   (
        SELECT  t1.rowid AS rid, t2.code
        FROM    table1 t1
        JOIN    table2 t2
        ON      table1.value = table2.DESC
        WHERE   table1.UPDATETYPE='blah'
        ) src
ON      (trg.rowid = src.rid)
WHEN MATCHED THEN UPDATE
    SET trg.value = code;
  • 2
    Работает отлично, но Oracle потребовал от меня сказать merge into table 1 t и т. Д.
  • 1
    Поздно на вечеринку, но это все еще хорошая нить. Мне нужно знать, правда ... я что-то пропустил? Мастер стол, "таблица1". В USING, table1 с псевдонимом t1. Таблица 2, с псевдонимом t2, но в ON, ссылки ...? Внешняя таблица1 - не t1 - это ссылка на внешнюю таблицу или тип? Таблица 2? Не т2? Je suis в замешательстве. Фанат лучших псевдонимов ...
Показать ещё 6 комментариев
17

Объединить с тем, где предложение работает для меня:

merge into table1
using table2
on (table1.id = table2.id)
when matched then update set table1.startdate = table2.start_date
where table1.startdate > table2.start_date;

Вам нужно предложение WHERE, потому что столбцы, указанные в предложении ON, не могут быть обновлены.

13
 UPDATE ( SELECT t1.value, t2.CODE
          FROM table1 t1
          INNER JOIN table2 t2 ON t1.Value = t2.DESC
          WHERE t1.UPDATETYPE='blah')
 SET t1.Value= t2.CODE
7

Как указано здесь, общий синтаксис для первого решения, предложенного Тони Эндрюсом:

update some_table s
set   (s.col1, s.col2) = (select x.col1, x.col2
                          from   other_table x
                          where  x.key_value = s.key_value
                         )
where exists             (select 1
                          from   other_table x
                          where  x.key_value = s.key_value
                         )

Я думаю, что это интересно, особенно если вы хотите обновить более одного поля.

  • 0
    Это не работает для меня. Он обновляет всю таблицу.
5

Не используйте некоторые из приведенных выше ответов.

Некоторые предлагают использовать вложенный SELECT, не делайте этого, он мучительно медленный. Если у вас есть много записей для обновления, используйте join, чтобы что-то вроде:

update (select bonus 
        from employee_bonus b 
        inner join employees e on b.employee_id = e.employee_id 
        where e.bonus_eligible = 'N') t
set t.bonus = 0;

См. эту ссылку для получения более подробной информации. http://geekswithblogs.net/WillSmith/archive/2008/06/18/oracle-update-with-join-again.aspx.

Кроме того, убедитесь, что на всех присоединяемых таблицах есть первичные ключи.

2

Он отлично работает оракул

merge into table1 t1
using (select * from table2) t2
on (t1.empid = t2.empid)
when matched then update set t1.salary = t2.salary
  • 0
    Можно установить несколько свойств, добавив запятую в конце этого. Мне нужно было сделать t1.First_Name = t2.FirstName, t1.Last_Name = t2.LastName для таблицы после сопоставления с ней в столбце «UserName» ( t1.UserName = t2.UserName ), чтобы получить их имя из таблицы с именем UserInfo ( select * from UserInfo) t2 ). База данных была такой, где она использовала UserName в качестве первичного ключа для UserInfo везде, вместо непосредственного размещения FirstName и LastName в таблице. Это исправлено!
  • 0
    Этот ответ ничего не добавляет к ответу, уже предоставленному Quassnoi за пять лет до вашего.
2

Этот следующий синтаксис работает для меня.

UPDATE
(SELECT A.utl_id,
    b.utl1_id
    FROM trb_pi_joint A
    JOIN trb_tpr B
    ON A.tp_id=B.tp_id Where A.pij_type=2 and a.utl_id is null
)
SET utl_id=utl1_id;
  • 0
    @JimGarrison Пожалуйста, отредактируйте этот ответ, чтобы я мог удалить свое понижение .... Я пытался использовать этот синтаксис, но он не обновлял мою таблицу. Я выяснил, почему - мой SET выполнял REPLACE и я пытался очистить определенную строку в столбце - оказалось, что Oracle обрабатывает '' как ноль, и это поле не может быть обнулено. Я думал, что синтаксис просто обновляет временную таблицу вместо реальной, но я ошибся.
1

Используя описание вместо desc для таблицы2,

update
  table1
set
  value = (select code from table2 where description = table1.value)
where
  exists (select 1 from table2 where description = table1.value)
  and
  table1.updatetype = 'blah'
;
  • 0
    почему вы хотите запустить два отдельных запроса на table2
0

Просто для полноты и из-за того, что мы говорим об Oracle, это также может быть сделано:

declare
begin
  for sel in (
    select table2.code, table2.desc
    from table1
    join table2 on table1.value = table2.desc
    where table1.updatetype = 'blah'
  ) loop
    update table1 
    set table1.value = sel.code
    where table1.updatetype = 'blah' and table1.value = sel.desc;    
  end loop;
end;
/
  • 0
    Это может сделать это, но это самый медленный путь.
0
UPDATE (SELECT T.FIELD A, S.FIELD B
FROM TABLE_T T INNER JOIN TABLE_S S
ON T.ID = S.ID)
SET B = A;

A и B - поля псевдонимов, вам не нужно указывать таблицу.

  • 1
    Привет, Дэн. Вы пишете на довольно старый вопрос, на который уже есть очень хорошие ответы. Можете ли вы объяснить, когда ваш вопрос предпочтительнее других решений?
  • 1
    Конечно, я видел ответ, где b = a были написаны с указанием имени таблицы (table1.B = table2.A), но указывать таблицу не нужно.
0
UPDATE IP_ADMISSION_REQUEST ip1
SET IP1.WRIST_BAND_PRINT_STATUS=0
WHERE IP1.IP_ADM_REQ_ID        =
  (SELECT IP.IP_ADM_REQ_ID
  FROM IP_ADMISSION_REQUEST ip
  INNER JOIN VISIT v
  ON ip.ip_visit_id=v.visit_id
  AND v.pat_id     =3702
  ); `enter code here`
0
UPDATE table1 t1
SET t1.value = 
    (select t2.CODE from table2 t2 
     where t1.value = t2.DESC) 
WHERE t1.UPDATETYPE='blah';
-3
update table1  a 
   set a.col1='Y' 
 where exists(select 1 
                from table2 b
               where a.col1=b.col1 
                 and a.col2=b.col2
             )

Ещё вопросы

Сообщество Overcoder
Наверх
Меню