2010-09-10 14 views
8

stiamo sviluppando processi ETL e il nostro consulente ha utilizzato SQL "vecchio stile" quando si uniscono le tabelleSQL Joins: futuro dello standard ANSI SQL (dove vs join)?

select a.attr1, b.attr1 
from table1 a, table2 b 
where a.attr2 = b.attr2 

invece di utilizzare il join interno clausola di

select a.attr1, b.attr1 
from table1 as a inner join table2 as b 
    on a.attr2 = b.attr2 

mia domanda è che nel lungo periodo , c'è il rischio di usare il vecchio "where join"? Per quanto tempo questo tipo di join è supportato e mantenuto come standard ANSI? La nostra piattaforma è SQL Server e la mia causa principale è che in futuro questi "dove si unisce" non sono più supportati. Quando ciò accade, dobbiamo modificare tutti i nostri lavori ETL usando lo stile "inner join" dei join.

risposta

7

Dubito che "where joins" non sia mai supportato. Non è possibile non supportarli, perché sono basati su prodotti cartesiani e su semplici filtri. In realtà non sono join.

Ma ci sono molti motivi per utilizzare la sintassi di join più recente.Tra gli altri:

  • leggibilità
  • Maintainability
  • Più facile modifica outer join
4

Ci sono molti motivi per evitare i join impliciti. I più grandi sono:

  • Non può essere facilmente modificato in un join esterno.
  • È più facile dimenticare la condizione di join con un join implicito.
  • Se si mescolano entrambi i join impliciti ed espliciti si hanno problemi con la precedenza confusa. Ecco un esempio di alcune ore fa: MySQL Syntax error

Non credo che verranno rimossi in qualunque momento presto, ma ci sono molti altri motivi per smettere di usarli.

2

Fintanto che non usano *** = e = * per la loro sintassi di join (che è stata deprecated as of SQL Server 2008 R2), non riesco a vederlo andare via nel lungo periodo, ma come dice Mark Byers, lì ci sono molte ragioni per non farlo

La mia più grande preoccupazione sarebbe che se scrivono join come questo, che cosa fanno non è convenzionale?

8

Piuttosto che preoccuparsi di alcuni possibili rischi in futuro, perché non preoccuparsi del rischio che si sta affrontando in questo momento?

In aggiunta ai punti di Mark:

  • Il codice è più difficile da leggere (e capire quindi lo scopo del) quando il ON clausole sono scollegati (a volte da molte linee) dalle tabelle unite. Ciò aumenta la probabilità di errori durante la modifica del codice.
  • Determinare quale tipo di JOIN viene eseguito è più difficile - devi andare a navigare attraverso la clausola WHERE e sperare che ciò che vedi sia giusto.
  • Trovare le clausole JOIN mancanti è molto più difficile, aumentando il rischio di un join cartesiano involontario - quando si utilizza la sintassi ANSI, le clausole ON si allineano bene, rendendo questo banale.
3

entrambe le sintassi sono supportate dalle ultime versioni di SQL ISO (2003,2008). L'utilizzo di virgole per specificare un cross join nella clausola FROM è perfettamente standard SQL ed è supportato da tutti i prodotti SQL che ho trovato. Sembra altamente improbabile che possa mai o addirittura essere deprecato o desupportato in SQL.

-2

Se si è preoccupati che vengano rimossi dallo standard o dai prodotti SQL, non preoccuparsi. Non è probabile che accada mai.

Questo 'vecchio stile' di join è proprio questo: solo una questione di stile. Coloro che lo preferiscono giurano che ci sono situazioni in cui i join "vecchio stile" sono più facili da capire. Anche se non sono del tutto convinto di me stesso, una cosa è certa: il vecchio stile si incontrerà di volta in volta e il codice di reingegnerizzazione per adattarsi al tuo stile personale non è sempre appropriato. Pertanto, abituarsi allo stile e imparare a lavorare con esso.

+0

No, non sono solo una questione di stile, ci sono problemi molto reali con l'utilizzo di questo tipo di join. – HLGEM

+0

@HLGEM - lo dici solo perché non è di tuo gusto. – onedaywhen

+0

Np, sto dicendo che causa risultati di query errate e problemi di manutenzione. – HLGEM

0

La sintassi implicita di join di destra e di sinistra * = e = * è deprecata e, per una buona ragione, attualmente non restituisce risultati corretti in ogni momento. Se hanno usato questo, questi DEVONO essere corretti ora in quanto attualmente ti mettono a rischio di risultati errati. Questa non è un'opzione. L'altra sintassi continuerà a funzionare ma dovrebbe essere sostituita anche per diversi motivi. Innanzitutto è molto facile ottenere cross join accidentali che possono restituire risultati errati o che vengono risolti utilizzando distinti che possono creare problemi di prestazioni.

Un altro problema è la manutenzione. Se in seguito le persone aggiungono altri join alla query e iniziano a mescolare nuovamente i join impliciti ed espliciti, è possibile ottenere risultati errati e nemmeno saperli. È MOLTO MOLTO brutto lasciare questo tipo di codice scadente nel codice base. I join impliciti sono anche più difficili da comprendere e, poiché sono spesso scritti da sviluppatori che non comprendono i join, potrebbero non essere ciò di cui hai bisogno in ogni caso. E se c'è una cross join nella query, come fa il manutentore a sapere se si trattava di un bug (e di un cross join accidentale) o di un cross join intenzionale (a volte ne abbiamo davvero bisogno). Non accetterei questo codice come scritto. Insisterei sul fatto che l'incompetente che lo ha scritto, lo aggiusti senza alcun costo aggiuntivo.

1

È difficile discutere dell'eleganza o della bruttezza di una certa costruzione della sintassi. Lo vedi o non lo fai. La sintassi dell'unione separata da virgola riflette la caratteristica fondamentale di Algebra relazionale, che asserisce la forma normale per le query select-project-join. L'unico tipo di join che lo sfugge (e quindi, garantisce una sintassi dedicata) è l'outer join. Errori accidentali di uguaglianza mancante predicano che il rendering del join grafo disgiunto è solo una questione di quanto sia sofisticato il tuo strumento di programmazione SQL front-end (mostra il grafico dell'unione?).

Non è solo l'estetica. È comune che i database di produzione abbiano colonne come CREATED_ON o COMMENTI su più tabelle. In questo caso la sintassi NATURAL JOIN è chiaramente pericolosa.

Come Anthony Molinaro (autore del popolare "SQL Cookbook") lo eloquentemente: "Il vecchio stile è breve e dolce e perfetto. L'ANSI lo ha ridimensionato, e per le persone che si sono sviluppate da qualche tempo, è del tutto inutile ".

+1

Davvero non vedo come le stesse identiche condizioni, situate semplicemente in un posto diverso, siano "storditi". E con le nuove estensioni di SQL CROSS APPLY e OUTER APPLY, c'è ancora di più che non si può fare con i join vecchio stile. Ho paura di dire che l'argomento qui sembra proprio come un dinosauro aggrappato al suo club di pietra (anche se più potere a te se ti piace). Basta non chiamarlo stupido quando non lo è! Inoltre, non vedo come le colonne comuni a molte tabelle rappresentino un nuovo pericolo. Se non usi alias, sei nei guai in ogni caso. – ErikE

1

persone hanno avuto alcuni buoni punti, ma finora non ci sono due grandi che non sono stati menzionati:

  1. o meno il vecchio stile * = e = * outer join ha dato risultati corretti, essi inoltre non può denotare correttamente alcuni join. Considera la seguente query. Vogliamo mostrare tutti i clienti che non hanno effettuato un acquisto oltre $ 100:

    SELECT 
    FROM 
        Customer C 
        LEFT JOIN Order O ON C.OrderID = O.OrderID AND O.OrderTotal >= 100.0; 
    WHERE 
        O.OrderID IS NULL; 
    

    Cercare di esprimere il fatto che il vecchio modo ... se potete. Senza usare tabelle derivate.

  2. Per me il grande valore di utilizzare una corretta unirsi clausole è la separazione dello standard unirsi condizioni (che si sarebbero applicate in quasi ogni query che coinvolge queste due tabelle) dai filtri speciali per questo query che restituirà il desiderato righe:

    SELECT 
        C.FullName, 
        C.CustomerCode, 
        O.OrderDate, 
        O.OrderTotal, 
        OD.ExtendedShippingNotes 
    FROM 
        Customer C 
        INNER JOIN Order O ON C.CustomerID = O.CustomerID 
        INNER JOIN OrderDetail OD ON O.OrderID = OD.OrderID 
    WHERE 
        C.CustomerStatus = 'Preferred' 
        AND O.OrderTotal > 1000.0; 
    

    questa separazione significa che lo sviluppatore guardando la query non avere a che fare con un gruppo di disordine durante la scansione per distintivi di questa query. Se ha familiarità con le tabelle, può saltare interamente la clausola FROM e solo leggere la clausola WHERE per ottenere tutte le informazioni di cui ha bisogno. È più veloce. E se non ti interessa più veloce, anche quando esegui la scansione delle query con i tuoi occhi, non voglio lavorare con te.

    Ora per coloro che pensano che ci sia qualcosa di speciale nella posizione di ogni cosa quando si utilizza la sintassi JOIN, si sbaglia. La seguente query funziona altrettanto bene come quello superiore:

    SELECT 
        C.FullName, 
        C.CustomerCode, 
        O.OrderDate, 
        O.OrderTotal, 
        OD.ExtendedShippingNotes 
    FROM 
        Customer C 
        CROSS JOIN Order O 
        INNER JOIN OrderDetail OD 
         ON C.CustomerID = O.CustomerID 
         AND C.CustomerStatus = 'Preferred' 
         AND O.OrderTotal > 1000.0 
    WHERE 
        O.OrderID = OD.OrderID; 
    

    Questa interrogazione ha probabilmente anche lo stesso piano di esatta esecuzione. Sorpreso? Non essere. Proprio come la sintassi vecchio stile, l'ottimizzatore è quello che è responsabile di capire come unire le tue tabelle in base alle condizioni che dai. In realtà non importa dove sono le condizioni fintanto che non si riferiscono a una tabella che non è stata ancora menzionata.

Quindi qual è la grande differenza tra i due stili? Se pensate che la seconda query mixata sopra sia difficile da capire e sarebbe un modo pazzo di scrivere, allora, naturalmente, pensate che il vecchio stile di query sia zoppo. Perché, francamente, mettere tutte le condizioni a casaccio in un vecchio posto è disorganizzato. Il sistema organizzativo di JOIN ha senso. Se sei abituato al vecchio stile e non ti piace il nuovo stile, probabilmente è perché il cambiamento è spiacevole (per tutti noi). Ma una volta che lo usi per un po ', sono sicuro che crescerà su di te. Almeno, se così non fosse, non riesco a capire perché.

+0

Vorrei ribaltare la tua tesi. Quindi, ANSI ti fornisce un modo per strutturare meglio la tua query ma non ha modo di rafforzarla? Scommetto che alcuni sviluppatori approfitterebbero della creazione di pasticci (infatti, questo è il motivo per cui sono qui). Per quanto riguarda i join esterni, non ci sono argomenti in questo caso - questo join non è associativo, devi mettere parentesi per disambiguare il nesting, almeno. L'ANSI dovrebbe aver appena corretto il join esterno e lasciare da solo i derivati ​​cartesiani del join del prodotto. –

+0

@Tegiri Mi dispiace dire che non capisco davvero di cosa stai parlando. Né lo stile vecchio né lo stile ANSI si applicano a nulla. Quindi non c'è nessun problema lì. E puoi ancora usare le parentesi se vuoi. Oppure, puoi semplicemente spostare le clausole ON per simulare le parentesi e far rispettare l'ordine di join (e non c'è ambiguità). Inoltre, puoi ottenere tutti i prodotti cartesiani con "CROSS JOIN" o anche "INNER JOIN ON 1 = 1'. Quanto sei esperto con ANSI? – ErikE