Come si può cancellare SQL usando una sotto query


15

Il seguente codice è stato aggiunto da uno dei nostri sviluppatori per eliminare i record duplicati dalla tabella:

DELETE  SubQuery

FROM
(
    SELECT  ID
            ,FK1
            ,FK2
            ,CreatedDateTime
            ,ROW_NUMBER() OVER(PARTITION BY FK1, FK2 ORDER BY CreatedDateTime) AS RowNumber

    FROM    Table
)
AS SubQuery

WHERE   RowNumber > 1

Durante la revisione del codice, ho ipotizzato che non avrebbe funzionato, tuttavia testarlo nel nostro ambiente di test (SQL 2014) mostra che funziona!

Come fa SQL a risolvere la query secondaria e a eliminare i record da table?

Risposte:


14

Quello subqueryche hai nel tuo codice è chiamato tabella derivata . Non è una tabella di base ma una tabella che "vive" durante il periodo di esecuzione della query. Come le viste (che sono anche chiamate tabelle visualizzate ) - e nelle versioni recenti CTE, che è un altro, quarto modo per "definire" una tabella all'interno di una query, sono simili a una tabella in molti modi. Puoi selectda loro, puoi usarli dentro fromo su di joinloro su altri tavoli (base o no!).

In alcuni DBMS (non tutti i DBMS lo hanno implementato allo stesso modo) queste tabelle / viste sono aggiornabili . E "aggiornabile" significa che possiamo anche update, insertdentro o deleteda loro.

Vi sono tuttavia delle restrizioni e questo è previsto. Immagina se subqueryfosse un join di 2 (o 17 tavoli). Cosa deletesignificherebbe allora? (da quali tabelle devono essere eliminate le righe?) Le viste aggiornabili sono una questione molto complicata . C'è un recente libro (2012), interamente su questo argomento, scritto da Chris Date, noto esperto di teoria relazionale: Visualizza aggiornamento e teoria relazionale .

Quando la tabella derivata (o vista) è una query molto semplice, come se avesse solo una tabella di base (possibilmente limitata da una WHERE) e no GROUP BY, allora ogni riga della tabella derivata corrisponde a una riga nella tabella di base sottostante, quindi è facile * per aggiornare, inserire o eliminare da questo.

Quando il codice all'interno della sottoquery è più complesso, dipende dal fatto che le righe della tabella / vista derivata possano essere tracciate / risolte in righe da una delle tabelle di base sottostanti.

Per SQL Server, si può leggere di più nel aggiornabili Visualizzazioni paragrafo in MSDN: CREATE VIEW.

Visualizzazioni aggiornabili

È possibile modificare i dati di una tabella di base sottostante tramite una vista, purché siano vere le seguenti condizioni:

  • Qualsiasi modifica, incluso UPDATE, INSERTe le DELETEistruzioni, devono fare riferimento a colonne da una sola tabella di base.

  • Le colonne che vengono modificate nella vista devono fare direttamente riferimento ai dati sottostanti nelle colonne della tabella. Le colonne non possono essere derivate in nessun altro modo, ad esempio attraverso:

  • Una funzione di aggregazione: AVG, COUNT, SUM, MIN, MAX, GROUPING, STDEV, STDEVP, VAR, e VARP.

  • Un calcolo. La colonna non può essere calcolata da un'espressione che utilizza altre colonne. Colonne che si formano in base alle operatori di insieme UNION, UNION ALL, CROSSJOIN, EXCEPT, e INTERSECT ammontano a un calcolo e non sono aggiornabili.

  • Le colonne in corso di modifica non sono interessati da GROUP BY, HAVINGo DISTINCTclausole.

  • TOPnon viene utilizzato da nessuna parte nel select_statement della vista insieme alla WITH CHECK OPTIONclausola.

Le restrizioni precedenti si applicano a qualsiasi subquery nella FROMclausola della vista, così come si applicano alla vista stessa. Generalmente, Motore di database deve essere in grado di tracciare in modo inequivocabile le modifiche dalla definizione della vista a una tabella di base.


In realtà deleteè più facile, meno complesso di update. SQL Server richiede solo le chiavi primarie o un altro modo per identificare quali righe della tabella di base devono essere eliminate. Per update, c'è una restrizione (piuttosto ovvia) aggiuntiva che non possiamo aggiornare una colonna calcolata. Puoi provare a modificare la tua query per effettuare un aggiornamento. L'aggiornamento CreatedDateTimeprobabilmente funzionerà RowNumbercorrettamente, ma il tentativo di aggiornare la colonna calcolata genererà un errore. Ed insertè ancora più complesso, poiché dovremmo fornire valori per tutte le colonne della tabella di base che non hanno un DEFAULTvincolo.


4

È facile vedere quando si esamina il piano di query. Nel tuo caso, il piano contiene solo un operatore Segment and Sequence Project aggiuntivo per gestire il numero di riga. Questo tipo di operazione funziona solo quando SQL Server può effettivamente risolvere la tabella sottostante.

L'eliminazione da sottoquery e CTE è pienamente supportata e molto efficiente, in particolare per la rimozione di duplicati. Mi sembra anche di ricordare di averlo usato su versioni precedenti di SQL Server.

Altro in un mio vecchio post sul blog .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.