Обновите результаты оператора SELECT - PullRequest
6 голосов
/ 16 июня 2009

Oracle позволяет обновлять результаты оператора SELECT.

UPDATE (<SELECT Statement>)
SET <column_name> = <value>
WHERE <column_name> <condition> <value>;

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

Как называется эта функция, может ли она эффективно использоваться для больших обновлений, работает ли она, когда SELECT объединяет несколько таблиц, и если да, то как?

Ответы [ 3 ]

5 голосов
/ 16 июня 2009

Я не видел официального названия для этого. Oracle SQL Reference просто ссылается на обновление подзапроса. Я склонен думать об этом как о форме «обновления представления», когда подзапрос находится во встроенном представлении.

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

Некоторые примеры могут помочь. Используя стандартные таблицы Oracle EMP и DEPT, где EMP.EMPNO определяется как первичный ключ EMP, а EMP.DEPTNO определяется как внешний ключ для DEPT.DEPTNO, тогда это обновление разрешено:

update (select emp.empno, emp.ename, emp.sal, dept.dname
        from   emp join dept on dept.deptno = emp.deptno
       )
set sal = sal+100;

Но это не так:

-- DEPT is not "key-preserved" - same DEPT row may appear
-- several times in view
update (select emp.ename, emp.sal, dept.deptno, dept.dname
        from   emp join dept on dept.deptno = emp.deptno
       )
set dname = upper(dname);

Что касается производительности: оптимизатор будет (должен) идентифицировать базовую таблицу, подлежащую обновлению во время синтаксического анализа, и присоединения к другой таблице будут игнорироваться, поскольку они не имеют никакого отношения к выполнению обновления - как показывает этот выход AUTOTRACE :

SQL> update (select emp.ename, emp.sal, dept.dname
  2              from   emp join dept on dept.deptno = emp.deptno
  3             )
  4      set sal = sal-1;

33 rows updated.


Execution Plan
----------------------------------------------------------
Plan hash value: 1507993178

------------------------------------------------------------------------------------
| Id  | Operation           | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT    |              |    33 |   495 |     3   (0)| 00:00:01 |
|   1 |  UPDATE             | EMP          |       |       |            |          |
|   2 |   NESTED LOOPS      |              |    33 |   495 |     3   (0)| 00:00:01 |
|   3 |    TABLE ACCESS FULL| EMP          |    33 |   396 |     3   (0)| 00:00:01 |
|*  4 |    INDEX UNIQUE SCAN| SYS_C0010666 |     1 |     3 |     0   (0)| 00:00:01 |
------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   4 - access("EMP"."DEPTNO"="DEPT"."DEPTNO")

(Обратите внимание, что таблица DEPT никогда не доступна, даже если в подзапросе присутствует DEPT.DNAME).

1 голос
/ 16 июня 2009

Форма, которую вы упоминаете, не имеет конкретного названия AFAIK. Просто обновляем результат оператора select.

Существует еще одна форма, которая называется Коррелированное обновление (с одиночным или многоколоночным обновлением)

UPDATE TABLE(<SELECT STATEMENT>) <alias>
SET <column_name> = (
  SELECT <column_name>
  FROM <table_name> <alias>
  WHERE <alias.table_name> <condition> <alias.table_name>
);

многоколонная форма

...
SET (<column_name_list>) = (
  SELECT <column_name_list>
...

Существует также метод, из которого также возвращается значение, называемое Обновление с возвращающим предложением

И некоторые особенности обновлений с вложенными таблицами. Лучше всего проверить хотя бы эти две страницы

Справочник по языку Oracle® Database SQL SELECT

Справочник по языку Oracle® Database SQL ОБНОВЛЕНИЕ

1 голос
/ 16 июня 2009

Спасибо за комментарии, я думал, что это стандартная Sql ...: (

Для Oracle вы можете записать обновление в таблицу, где вы извлекаете информацию с помощью объединения, например:

UPDATE (
    SELECT * 
    FROM table1 t1 
    LEFT JOIN table2 t2 ON t2.t1id = t1.ID
) SET t1.col1 = t2.col2

Для Sql Server это:

UPDATE t1
SET col1 = t2.col2
FROM table1 t1
LEFT JOIN table2 t2 on t2.t1id = t1.id

Если кто-нибудь знает способ сделать это, который работает на Oracle, Sql Server и MySql, я был бы заинтересован.

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