2009-06-16 10 views
6

Oracle pozwala aktualizować wyniki instrukcji SELECT.Zaktualizuj wyniki instrukcji SELECT

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

Przypuszczam, że można to wykorzystać do aktualizacji kolumn w jednej tabeli na podstawie wartości pasującego wiersza w innej tabeli.

Jak ta funkcja jest wywoływana, czy można ją efektywnie wykorzystać do dużych aktualizacji, czy działa, gdy SELECT łączy się z wieloma tabelami, a jeśli tak, to w jaki sposób?

+2

Istnieje przykład aktualizacji połączenia w innym języku SO: http://stackoverflow.com/questions/975315/what-is-wrong-with-my-update-statement-with-a-join-in- oracle/975674 # 975674 - Dotyczące wydajności: jest to prawdopodobnie najbardziej efektywny sposób aktualizowania zestawu wierszy. –

+1

Na ogół nazywa się aktualizację widoku. –

Odpowiedz

1

Dzięki za komentarze, myślałem, że to było standardem SQL ... :(

Dla Oracle można napisać aktualizacji na stole, gdzie można pobierać informacje z złączenia jak:

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

Dla SQL Server, to:

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

Jeśli ktoś zna sposób na to, że działa na Oracle, SQL Server i MySQL zrobić byłbym zainteresowany

.
+1

Czy na pewno to działa? W Oracle otrzymuję "ORA-00933: polecenie SQL nie zostało poprawnie zakończone" w "FROM"? – Thilo

+0

Korzystanie z http://www.dpriver.com/pp/sqlformat.htm wydaje się działać dla MSSQL, ale daje błędy składniowe dla Oracle, MySQL lub DB2 – Thilo

+0

-1 Nie działa w Oracle. Nie jestem pewien, czy jest to standardowy SQL. –

1

Wymieniony formularz nie ma nazwy AFAIK. Wystarczy zaktualizować wynik instrukcji select.

Jest jeszcze inna forma nazywa Skorelowana aktualizacja (z jednym lub wielokolumnowym aktualizacji)

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

wielokolumnowa forma

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

Istnieje również z którego również powrocie wartości nazywa Aktualizacja z klauzulą ​​zwrotu

A niektóre szczególne s dla aktualizacji z tabelami zagnieżdżonymi. Najlepiej jest sprawdzić przynajmniej tych dwóch stron

Oracle® Database SQL Language Reference SELECT

Oracle® Database SQL Language Reference UPDATE

4

nie widziałem formalną nazwę dla tego produktu. Oracle SQL Reference odnosi się tylko do aktualizacji podkwerendy. Mam tendencję do myślenia o tym jako o "aktualizacji widoku", z podzapytaniem w widoku liniowym.

Tak, działa po połączeniu wielu tabel, ale z zastrzeżeniem reguł aktualizacji widoku. Oznacza to, że tylko jedna z tabel podstawowych widoku może być aktualizowana, a ta tabela musi być "zachowana na klucz" w widoku: tzn. Jej wiersze powinny być wyświetlane tylko raz w widoku. Wymaga to, aby wszelkie inne tabele w widoku (podzapytanie) były przywoływane przez ograniczenia klucza obcego w tabeli, które mają być aktualizowane.

Niektóre przykłady mogą pomóc. Korzystanie ze standardowych tabel Oracle EMP i DEPT, przy czym EMP.EMPNO jest zdefiniowany jako klucz podstawowy EMP, a EMP.DEPTNO jest zdefiniowany jako klucz obcy dla DEPT.DEPTNO, to zmiana jest dozwolona:

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

Ale to nie jest:

-- 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); 

chodzi o wydajność: Optymalizator będzie (musi) identyfikować tabelę podstawową być aktualizowane podczas parsowania, i dołącza do druga tabela zostanie zignorowany, ponieważ nie mają one żadnego wpływu na aktualizację do wykonania - jak tego AUTOTRACE pokazy wyjściowych:

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") 

(Zauważ, że tabela DEPT nigdy nie jest dostępny, chociaż DEPT.DNAME appe ars w podzapytaniu).

Powiązane problemy