2009-06-16 13 views
6

Oracle consente di aggiornare i risultati di un'istruzione SELECT.Aggiornamento dei risultati di una istruzione SELECT

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

immagino che questo potrebbe essere usato per le colonne aggiornamento di una tabella in base al valore di una riga corrispondente in un'altra tabella.

Come viene chiamata questa funzione, può essere utilizzata in modo efficiente per aggiornamenti di grandi dimensioni, funziona quando SELECT unisce più tabelle e, in caso affermativo, come?

+2

C'è un exemple un aggiornamento di un join in un altro SO: http://stackoverflow.com/questions/975315/what-is-wrong-with-my-update-statement-with-a-join-in- oracle/975.674 # 975.674 - Per quanto riguarda l'efficienza: è probabilmente il modo più efficiente di aggiornare un insieme di righe –

+1

E 'generalmente chiamato vista l'aggiornamento. –

risposta

1

Grazie per i commenti, ho pensato che questo era standard Sql ... :(

Per Oracle è possibile scrivere un aggiornamento su un tavolo in cui si recuperano le informazioni con un join come:

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

Per Sql Server, è:

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

Se qualcuno conosce un modo per farlo che funziona su Oracle, Sql Server e MySql sarei interessato

.
+1

Sei sicuro che funzioni? In Oracle, viene visualizzato "ORA-00933: comando SQL non terminato correttamente" in "FROM"? – Thilo

+0

Utilizzando http://www.dpriver.com/pp/sqlformat.htm sembra funzionare per MSSQL, ma dà errori di sintassi per Oracle, MySQL o DB2 – Thilo

+0

-1 No non funziona in Oracle. Non sono nemmeno sicuro che sia standard SQL. –

1

Il modulo che hai citato non ha un nome specifico AFAIK. Sto semplicemente aggiornando il risultato di una dichiarazione selezionata.

C'è un'altra forma chiamata aggiornamento Correlated (con aggiornamento singolo o più colonne)

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

La forma più colonna

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

C'è anche una da cui anche il ritorno di valori chiamati Aggiorna con clausola di rinvio

E alcuni specifici s per gli aggiornamenti con tabelle nidificate. La cosa migliore è di controllare almeno questo due pagine

Oracle® Database SQL Language Reference SELECT

Oracle® Database SQL Language Reference UPDATE

4

non ho visto un nome formale per questo. Lo Oracle SQL Reference si riferisce semplicemente all'aggiornamento di una sottoquery. Tendo a considerarlo come una forma di "aggiornamento della vista", con la sottoquery in visualizzazione in linea.

Sì, funziona quando un numero di tabelle viene unito, ma soggetto all'aggiornamento delle regole di visualizzazione. Ciò significa che solo una delle tabelle di base della vista può essere aggiornata e questa tabella deve essere "salvata con la chiave" nella vista: vale a dire che le sue righe dovrebbero essere visualizzate una sola volta nella vista. Ciò richiede che qualsiasi altra tabella nella vista (sottoquery) sia referenziata tramite vincoli di chiave esterna sulla tabella da aggiornare.

Alcuni esempi possono essere d'aiuto. Utilizzo delle tabelle Oracle EMP e DEPT standard, con EMP.EMPNO definito come chiave primaria di EMP e EMP.DEPTNO definito come chiave esterna da DEPT.DEPTNO, allora questo aggiornamento è consentito:

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

Ma non è questo:

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

quanto riguarda le prestazioni: l'ottimizzatore sarà (deve) identificare la tabella di base da aggiornare durante l'analisi, e si unisce a altro tavolo viene ignorato dal momento che non hanno alcuna influenza sulla aggiornamento da eseguire - come dimostra questo uscita 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") 

(si noti che non è mai tabella DEPT accede anche se DEPT.DNAME appe ars nella sottoquery).

Problemi correlati