2013-08-12 3 views
2

Интересно, что такое поведение Oracle в отношении подзапроса и выполнения предложения update и delete.Каков порядок выполнения предложений Oracle MERGE INTO с подзапросом

Интересно, если Oracle:

  1. выполняет подзапрос и для каждой строки, он выполняет обновление и УДАЛИТЬ положения
  2. выполняет подзапрос для обновления, а затем выполняет подзапрос для удаления
  3. 1) и 2), оптимизатор выбирает наилучшую стратегию
  4. Другое?

EDIT:

DB используется: Oracle 11.2.0.3.0 Я это довольно запрос

 
DROP TABLE T1; 
DROP TABLE IT1; 
DROP TABLE OT1; 

CREATE TABLE T1 (
    ID INTEGER, 
    V INTEGER, 
    PIVOT INTEGER 
); 

CREATE TABLE IT1 (
    ID INTEGER 
); 

CREATE TABLE OT1 (
    ID INTEGER, 
    FOO INTEGER, 
    NV INTEGER 
); 

INSERT INTO T1 (ID,V,PIVOT) VALUES (1,1,1); 
INSERT INTO T1 (ID,V,PIVOT) VALUES (2,1,1); 

INSERT INTO IT1 (ID) VALUES (1); 
INSERT INTO IT1 (ID) VALUES (2); 

INSERT INTO OT1 (ID,NV,FOO) VALUES (1,2,0); 
INSERT INTO OT1 (ID,NV,FOO) VALUES (2,2,0); 

commit; 


MERGE INTO T1 TARGET USING ( 
    SELECT DISTINCT T1.ID,T1.V, OT1.NV 
    FROM T1 
    INNER JOIN IT1 ON T1.ID = IT1.ID 
    LEFT OUTER JOIN OT1 ON OT1.ID = IT1.ID 
    WHERE T1.PIVOT = 1 or OT1.FOO=40) SRC 
ON (SRC.ID = TARGET.ID) 
WHEN MATCHED THEN 
UPDATE SET TARGET.V=SRC.NV 
DELETE WHERE TARGET.V=SRC.V; 

commit; 

Если элемент имеет новую версию, то элемент будет обновляться новая версия (предложение UPDATE). Если нет, элемент уничтожается (предложение DELETE). Удалить не должно быть

Это заявление не работает, как я ожидаю. Он удаляет все ссылки. Это было похоже на предложения delete, которые выполняют подзапрос с измененными данными.

Обратите внимание на OT1.FOO = 40, который здесь бесполезен, но, похоже, создает проблему. Если я добавлю order by к подзапросу (независимо от критерия заказа), инструкция работает правильно.

Спасибо,

Николя

+0

Проверьте это: - http://docs.oracle.com/cd/B28359_01/server.111/b28286/ statements_9016.htm –

+0

Я уже читал документ и не очень полезен о заказе –

ответ

0

Забыл ответить на этот вопрос.

Вопрос известен и должен быть исправлен с исправлением 11.2.0.4 (выпущено Q4 2013).

Oracle предлагает следующий временный обходной путь:

alter session set "_complex_view_merging"=false;" 

Или намек NO_MERGE

-1

Я не верю, что Oracle гарантирует порядок работы для составного оператора, как это. Я ожидаю, что сгенерированный план объяснения покажет, что такое точный порядок операций. Я использовал TOAD для анализа/настройки запросов, подобных этому в прошлом.

+1

Если заказ не гарантируется, план объяснений не поможет ни потому, что он может измениться в любое время. – usr

1

Стандарт SQL гарантирует три фазы:

  1. вычисляя новые значения для всех строк обновляются (только для чтения фазы)
  2. Изменений применяются все сразу
  3. Ограничений проверяются

Это означает, что все «подзапросы» логически выполняются до того, как произойдет первая запись. Это может быть реализовано с использованием разных форм физического плана, но это не касается вашей логики приложения.

+0

Если я подчиняюсь вам правильно, подзапрос возвращает всегда одни и те же данные, даже если есть обновление или удаление? –

+0

Да, он должен работать так, как если бы он работал с моментальным снимком базы данных. – usr

+0

Я не понимаю свою проблему. Я пропустил запрос, надеюсь, что он поможет –

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