Domanda

In ogni azienda in cui ho lavorato, ho scoperto che le persone stanno ancora scrivendo le loro query SQL nello standard ANSI-89:

select a.id, b.id, b.address_1
from person a, address b
where a.id = b.id

anziché lo standard ANSI-92:

select a.id, b.id, b.address_1
from person a
inner join address b
on a.id = b.id

Per una query estremamente semplice come questa, non c'è una grande differenza nella leggibilità, ma per le query di grandi dimensioni trovo che avere i miei criteri di join raggruppati con l'elenco fuori dalla tabella rende molto più facile vedere dove potrei avere problemi nella mia Unisciti e lasciami mantenere tutti i miei filtri nella mia clausola WHERE. Per non parlare del fatto che ritengo che i join esterni siano molto intuitivi rispetto alla sintassi (+) in Oracle.

Mentre provo ad evangelizzare l'ANSI-92 alle persone, ci sono dei benefici concreti in termini di prestazioni nell'uso dell'ANSI-92 rispetto all'ANSI-89? Lo proverei da solo, ma le configurazioni Oracle che abbiamo qui non ci permettono di usare EXPLAIN PLAN - non vorrebbe che le persone cercassero di ottimizzare il loro codice, vero?

È stato utile?

Soluzione

Secondo " Ottimizzazione delle prestazioni SQL " di Peter Gulutzan e Trudy Pelzer, dei sei o otto marchi RDBMS che hanno testato, non vi sono state differenze nell'ottimizzazione o nelle prestazioni dei join in stile SQL-89 rispetto a quelli in stile SQL-92. Si può presumere che la maggior parte dei motori RDBMS trasformi la sintassi in una rappresentazione interna prima di ottimizzare o eseguire la query, quindi la sintassi leggibile dall'uomo non fa alcuna differenza.

Cerco anche di evangelizzare la sintassi SQL-92. Sedici anni dopo l'approvazione, è tempo che le persone inizino a usarlo! E ora tutte le marche di database SQL lo supportano, quindi non c'è motivo di continuare a utilizzare la sintassi (+) orribile o * = Sintassi Microsoft / Sybase.

Per quanto riguarda il motivo per cui è così difficile spezzare la comunità di sviluppatori dell'abitudine SQL-89, posso solo supporre che ci sia una grande "base della piramide" dei programmatori che codificano per copia e amp; incolla, usando antichi esempi di libri, articoli di riviste o un'altra base di codice, e queste persone non imparano la nuova sintassi in modo astratto. Alcune persone corrispondono al modello e alcune persone imparano a memoria.

Tuttavia, vedo gradualmente le persone che usano la sintassi SQL-92 più frequentemente di prima. Risposte alle domande SQL online dal 1994.

Altri suggerimenti

Beh, lo standard ANSI092 include una sintassi piuttosto atroce. Natural Joins sono uno e la clausola USING è un altro. IMHO, l'aggiunta di una colonna a una tabella non dovrebbe violare il codice, ma un JOIN NATURALE si rompe in modo egregio. Il "migliore" il modo di rompere è per errore di compilazione. Ad esempio, se SELEZIONA * da qualche parte, l'aggiunta di una colonna potrebbe non essere compilata . Il prossimo modo migliore per fallire sarebbe un errore di runtime. È peggio perché i tuoi utenti potrebbero vederlo, ma ti dà ancora un bel avvertimento che hai rotto qualcosa. Se si utilizza ANSI92 e si scrivono query con join NATURAL, non si interromperà in fase di compilazione e non si interromperà in fase di esecuzione, la query inizierà improvvisamente a produrre risultati errati. Questi tipi di bug sono insidiosi. I rapporti vanno male, le informazioni potenzialmente finanziarie non sono corrette.

Per chi non ha familiarità con NATURAL Joins. Uniscono due tabelle per ogni nome di colonna esistente in entrambe le tabelle. Il che è davvero bello quando hai un tasto a 4 colonne e sei stanco di digitarlo. Il problema si presenta quando Table1 ha una colonna preesistente denominata DESCRIPTION e aggiungi una nuova colonna a Table2 denominata, oh non lo so, qualcosa di innocuo come, mmm, DESCRIPTION e ora stai unendo le due tabelle su un VARCHAR2 (1000) campo in formato libero.

La clausola USING può portare ad una totale ambiguità oltre al problema sopra descritto. In un altro SO post , qualcuno ha mostrato questo SQL ANSI-92 e ha chiesto aiuto per leggerlo.

SELECT c.* 
FROM companies AS c 
JOIN users AS u USING(companyid) 
JOIN jobs AS j USING(userid) 
JOIN useraccounts AS us USING(userid) 
WHERE j.jobid = 123

Questo è completamente ambiguo. Ho inserito una colonna UserID in entrambe le società e le tabelle degli utenti e non c'è alcun reclamo. Cosa succede se la colonna UserID nelle aziende è l'ID dell'ultima persona che ha modificato quella riga?

Sono serio, qualcuno può spiegare perché fosse necessaria tale ambiguità? Perché è integrato direttamente nello standard?

Penso che Bill abbia ragione sul fatto che esiste una grande base di sviluppatori che copia / incolla in questo modo attraverso la codifica. In effetti, posso ammettere che sono un po 'uno quando si tratta di ANSI-92. Ogni esempio che ho mai visto mostrava più join nidificati tra parentesi. Onestà, ciò rende nella migliore delle ipotesi difficile scegliere i tavoli nella sql. Ma poi un evangilista di SQL92 ha spiegato che in realtà forzerebbe un ordine di join. GESU '... tutti quei pasters di copia che ho visto ora stanno forzando un ordine di join - un lavoro che è il 95% delle volte meglio lasciato agli ottimizzatori specialmente una copia / paster.

Tomalak ha capito bene quando ha detto,

  

le persone non passano solo alla nuova sintassi   perché è lì

Deve darmi qualcosa e non vedo un lato positivo. E se c'è un lato positivo, i negativi sono un albatro troppo grande per essere ignorato.

Vengono in mente alcuni motivi:

  • le persone lo fanno per abitudine
  • le persone sono pigre e preferiscono il "vecchio stile" si unisce perché comportano meno digitazione
  • i principianti hanno spesso problemi ad avvolgere la testa attorno alla sintassi del join SQL-92
  • le persone non passano alla nuova sintassi solo perché è lì
  • le persone non sono consapevoli dei vantaggi della nuova sintassi (se si desidera chiamarla così), principalmente che consente di filtrare una tabella prima di eseguire un join esterno e non dopo quando tutto ciò che hai è la clausola WHERE.

Da parte mia, faccio tutti i miei join nella sintassi SQL-92 e converto il codice dove posso. È il modo più pulito, più leggibile e potente per farlo. Ma è difficile convincere qualcuno a usare il nuovo stile, quando pensano che li danneggi in termini di più lavoro di battitura senza cambiare il risultato della query.

In risposta a NATURAL JOIN e USING post sopra.

PERCHÉ vedresti mai la necessità di usarli? Non erano disponibili in ANSI-89 e sono stati aggiunti per ANSI-92 come quello che posso vedere solo come scorciatoia.

Non lascerei mai un join al caso e specificherei sempre la tabella / alias e ID.

Per me, l'unica strada da percorrere è ANSI-92. È più dettagliato e la sintassi non è gradita dai follower ANSI-89 ma separa ordinatamente i tuoi JOIN dai tuoi FILTERING.

Prima di tutto lasciatemi dire che in SQL Server la sintassi del join esterno (* =) non fornisce sempre risultati corretti. Ci sono momenti in cui lo interpreta come un cross join e non come un join esterno. Quindi, c'è un buon motivo per smettere di usarlo. E quella sintassi del join esterno è una funzionalità obsoleta e non sarà nella prossima versione di SQL Server dopo SQL Server 2008. Sarai comunque in grado di eseguire i join interni ma perché mai qualcuno vorrebbe? Sono poco chiari e molto più difficili da mantenere. Non si sa facilmente cosa fa parte del join e che cosa è in realtà solo la clausola where.

Uno dei motivi per cui credo che non dovresti usare la vecchia sintassi è che comprendere i join e cosa fanno e cosa non fanno è un passaggio fondamentale per chiunque scriverà codice SQL. Non si dovrebbe scrivere alcun codice SQL senza aver compreso a fondo i join. Se li capisci bene, probabilmente arriverai alla conclusione che la sintassi ANSI-92 è più chiara e più facile da mantenere. Non ho mai incontrato un esperto SQL che non abbia usato la sintassi ANSI-92 in preferenza alla vecchia sintassi.

La maggior parte delle persone che ho incontrato o con cui ho avuto a che fare con il vecchio codice, in realtà non capiscono i join e quindi si mettono nei guai durante l'interrogazione del database. Questa è la mia esperienza personale, quindi non sto dicendo che sia sempre vero. Ma come specialista dei dati, nel corso degli anni ho dovuto sistemare troppa spazzatura per non crederci.

Mi è stato insegnato ANSI-89 a scuola e ho lavorato nell'industria per alcuni anni. Poi ho lasciato il fantastico mondo di DBMS per 8 anni. Ma poi sono tornato e questo nuovo materiale ANSI 92 veniva insegnato. Ho imparato la sintassi Join On e ora in realtà insegno SQL e raccomando la nuova sintassi JOIN ON.

Ma il lato negativo che vedo è che le sottoquery correlate non sembrano avere senso alla luce dei join ANSI 92. Quando le informazioni di join sono state incluse in WHERE e le sottoquery correlate sono "unite" nel DOVE tutto sembrava giusto e coerente. Nella tabella ANSI 92 i criteri di join non sono in WHERE e la subquery "join" la sintassi sembra incoerente. D'altra parte, provando a "riparare" questa incoerenza probabilmente peggiorerebbe la situazione.

Non conosco la risposta con certezza .. questa è una guerra religiosa (albiet di grado inferiore rispetto a Mac-Pc o altri)

Un'ipotesi è che fino a poco tempo fa Oracle (e forse anche altri fornitori) non adottassero lo standard ANSI-92 (penso che fosse in Oracle v9 o giù di lì) e così, per gli sviluppatori DBA / Db che lavorano nelle aziende che stavano ancora utilizzando queste versioni (o che volevano che il codice fosse portabile su server che potrebbero utilizzare queste versioni, dovevano attenersi al vecchio standard ...

È davvero un peccato, perché la nuova sintassi del join è molto più leggibile e la vecchia sintassi genera risultati errati (errati) in diversi scenari ben documentati.

  • In particolare, i join esterni quando presenti sono predicati del filtro condizionale su colonne correlate non unite da tabella "esterna" lato del aderire.

Inerzia e praticità.

ANSI-92 SQL è come la digitazione a tocco. In qualche modo teorico un giorno potrebbe rendere tutto meglio, ma ora posso digitare molto più velocemente guardando i tasti con quattro dita. Avrei bisogno di andare indietro per andare avanti, senza alcuna garanzia che ci sarebbe mai stato un pagamento.

Scrivere SQL rappresenta circa il 10% del mio lavoro. Se ho bisogno di ANSI-92 SQL per risolvere un problema che ANSI-89 SQL non può risolvere, lo userò. (Lo uso in Access, in effetti.) Se usarlo tutto il tempo mi aiutasse a risolvere i miei problemi esistenti molto più velocemente, spenderei il tempo per assimilarlo. Ma posso estrarre SQL ANSI-89 senza mai pensare alla sintassi. Vengo pagato per risolvere i problemi: pensare alla sintassi SQL è una perdita del mio tempo e del denaro del mio datore di lavoro.

Un giorno, giovane Grasshopper, difenderai il tuo uso della sintassi SQL ANSI-92 contro i giovani che si lamentano che dovresti usare SQL3 (o qualsiasi altra cosa). E poi capirai. : -)

Avevo una query originariamente scritta per SQL Server 6.5, che non supportava la sintassi del join SQL 92, ovvero

select foo.baz
from foo
  left outer join bar
  on foo.a = bar.a

è stato invece scritto come

select foo.baz
from foo, bar
where foo.a *= bar.a

La query era in circolazione da un po 'di tempo e i dati rilevanti si erano accumulati per rendere la query troppo lenta, circa 90 secondi per il completamento. Quando si è verificato questo problema, avevamo eseguito l'aggiornamento a SQL Server 7.

Dopo essermi distratto con gli indici e altre uova di Pasqua, ho modificato la sintassi del join in modo che fosse conforme a SQL 92. Il tempo di query è sceso a 3 secondi.

C'è un buon motivo per cambiare.

Ripubblicato da qui .

Posso rispondere dal punto di vista di uno sviluppatore medio, conoscendo abbastanza SQL per capire entrambe le sintassi, ma continuando a cercare su Google l'esatta sintassi dell'inserzione ogni volta che ne ho bisogno ... :-P (non lo faccio SQL tutto il giorno, risolvendo solo alcuni problemi di tanto in tanto.)

Beh, in realtà, trovo la prima forma più intuitiva, senza creare una gerarchia apparente tra le due tabelle. Il fatto che io abbia imparato SQL con possibilmente vecchi libri, mostrando il primo modulo, probabilmente non aiuta ... ;-)
E il primo riferimento che trovo su una ricerca sql select in Google (che restituisce risposte per lo più francesi per me ...) mostra prima il modulo più vecchio (quindi spiega il secondo).

Dando solo alcuni suggerimenti su " why " domanda ... ^ _ ^ Dovrei leggere un buon libro moderno (DB agnostico) sull'argomento. Se qualcuno ha suggerimenti ...

Non posso parlare per tutte le scuole ma nella mia università quando stavamo facendo il modulo SQL del nostro corso, non insegnavano ANSI-92, insegnavano ANSI-89 - su un vecchio sistema VAX a quello! Non sono stato esposto all'ANSI-92 fino a quando non ho iniziato a scavare in Access dopo aver creato alcune query utilizzando il designer delle query e quindi scavando nel codice SQL. Comprendendo che non avevo idea di come stesse completando i join o delle implicazioni della sintassi, ho iniziato a scavare più a fondo per poterlo capire.

Dato che la documentazione disponibile non è esattamente intuitiva in molti casi e che le persone tendono ad attenersi a ciò che sanno e in molti casi non si sforzano di imparare più di quanto hanno bisogno per ottenere il loro lavoro fatto, è facile capire perché l'adozione sta impiegando così tanto tempo.

Certo, ci sono quegli evangelisti tecnici a cui piace armeggiare e capire e tende ad essere quei tipi che adottano il "nuovo". principi e prova a convertire il resto.

Stranamente, mi sembra che molti programmatori escano da scuola e smettano di avanzare; pensando che, poiché questo è ciò che è stato loro insegnato, è così che viene fatto. Solo quando ti togli i paraocchi ti rendi conto che la scuola aveva solo lo scopo di insegnarti le basi e darti abbastanza comprensione per imparare il resto da solo e che in realtà hai appena graffiato la superficie di ciò che c'è da sapere; ora tocca a te continuare quel percorso.

Certo, questa è solo la mia opinione basata sulla mia esperienza.

1) Modo standard per scrivere OUTER JOIN, contro * = o (+) =

2) ISCRIZIONE NATURALE

3) A seconda del motore di database, le tendenze ANSI-92 saranno più ottimali.

4) Ottimizzazione manuale:

Diciamo che abbiamo la prossima sintassi (ANSI-89):

(1)select * from TABLE_OFFICES to,BIG_TABLE_USERS btu
where to.iduser=tbu.iduser and to.idoffice=1

Potrebbe essere scritto come:

(2)select * from TABLE_OFFICES to
inner join BIG_TABLE_USERS btu on to.iduser=tbu.iduser
where to.idoffice=1

Ma anche come:

(3)select * from TABLE_OFFICES to
inner join BIG_TABLE_USERS btu on to.iduser=tbu.iduser and to.idoffice=1

Tutti (1), (2), (3) restituiscono lo stesso risultato, tuttavia sono ottimizzati in modo diverso, dipende dal motore del database ma la maggior parte di essi lo fa:

  • (1) spetta al motore di database decidere l'ottimizzazione.
  • (2) unisce entrambe le tabelle quindi esegue il filtro per ufficio.
  • (3) filtra i BIG_TABLE_USERS usando l'idoffice quindi unisce entrambe le tabelle.

5) Le query più lunghe sono meno complicate.

Ragioni per cui le persone usano ANSI-89 dalla mia esperienza pratica con programmatori e apprendisti vecchi e giovani e neolaureati:

  • Imparano SQL dal codice esistente che vedono (piuttosto che dai libri) e imparano ANSI-89 dal codice
  • ANSI-89 perché sta scrivendo meno
  • Non ci pensano e usano l'uno o l'altro stile e non sanno nemmeno quale di entrambi sia considerato nuovo o vecchio e non gliene frega niente
  • L'idea che il codice sia anche una comunicazione al prossimo programmatore che arriva mantenendo il codice non esiste. Pensano di parlare al computer e al computer non importa.
  • L'arte della "codifica pulita" è sconosciuto
  • La conoscenza del linguaggio di programmazione e di SQL in particolare è così scarsa che copiano e incollano ciò che trovano altrove
  • Preferenze personali

Personalmente preferisco ANSI-92 e cambio ogni query che vedo nella sintassi ANSI-89 a volte solo per capire meglio l'istruzione SQL a portata di mano. Ma mi sono reso conto che la maggior parte delle persone con cui lavoro non è abbastanza abile da scrivere join su molti tavoli. Codificano il meglio possibile e usano ciò che hanno memorizzato la prima volta che hanno incontrato un'istruzione SQL.

Oracle non implementa bene ANSI-92. Ho avuto diversi problemi, non ultimo perché le tabelle di dati in Oracle Apps sono così ben dotate di colonne. Se il numero di colonne nei tuoi join supera circa 1050 colonne (che è molto facile da fare in App), otterrai questo errore spurio che non ha assolutamente senso logico:

ORA-01445: cannot select ROWID from a join view without a key-preserved table.

Riscrivere la query per utilizzare la sintassi di join di vecchio stile fa scomparire il problema, il che sembra puntare il dito della colpa esattamente sull'implementazione dei join ANSI-92.

Fino a quando non ho riscontrato questo problema, sono stato un promotore costante di ASNI-92, a causa dei vantaggi nel ridurre la possibilità di un cross-join accidentale, che è fin troppo facile da fare con la sintassi vecchio stile.

Ora, tuttavia, trovo molto più difficile insistere su di esso. Indicano la cattiva implementazione di Oracle e dicono " Faremo a modo nostro, grazie "

Ecco alcuni punti che mettono a confronto SQL-89 e SQL-92 e chiariscono alcune idee sbagliate in altre risposte.

  1. NATURAL JOINS sono un'idea orribile. Sono impliciti e richiedono meta-informazioni sulla tabella. Nulla su SQL-92 richiede il loro uso, quindi semplicemente ignorali . Non sono rilevanti per questa discussione.
  2. USANDO è un'ottima idea, ha due effetti:
    1. Produce solo una colonna sul set di risultati da un equijoin.
    2. Fa rispettare una convenzione sana e sana. In SQL-89 c'erano persone che scrivevano la colonna id su entrambe le tabelle. Dopo esserti unito alle tabelle, questo diventa ambiguo e richiede un aliasing esplicito. Inoltre, gli id sul join avevano quasi certamente dati diversi. Se ti unisci una persona all'azienda, ora devi alias un id su person_id e un id su company_id , senza il quale il join produrrebbe due colonne ambigue. L'uso di un identificatore univoco globale per la chiave surrogata della tabella è la convenzione che lo standard premia con USING .
  3. La sintassi SQL-89 è un CROSS JOIN implicito. Un CROSS JOIN non riduce l'insieme, ma lo aumenta implicitamente. FROM T1, T2 è uguale a FROM T1 CROSS JOIN T2 , che produce un join cartesiano che di solito non è quello desiderato. Avere la selettività per ridurla a un condizionale WHERE distante significa che è più probabile che tu commetta errori durante la progettazione.
  4. SQL-89 , e SQL-92 espliciti JOIN hanno una precedenza diversa. JOIN ha una precedenza più alta. Ancora peggio, alcuni database come MySQL si sono sbagliati per molto tempo . . Quindi mescolare i due stili è una cattiva idea, e lo stile molto più popolare oggi è lo stile SQL-92

Un nuovo standard SQL eredita tutto dallo standard precedente, a.k.a. 'le catene della compatibilità'. Quindi lo stile di join "vecchio" / "separato da virgola" / "non qualificato" è una sintassi SQL-92 perfettamente valida.

Ora, sostengo che il NATURAL JOIN di SQL-92 sia l'unico join necessario. Ad esempio, sostengo che sia superiore a join interno perché non genera colonne duplicate - non più variabili di intervallo nelle clausole SELECT per chiarire le colonne! Ma non posso aspettarmi di cambiare ogni cuore e mente, quindi ho bisogno di lavorare con programmatori che continueranno ad adottare quelli che considero personalmente stili di unione legacy (e potrebbero anche riferirsi alle variabili di intervallo come "alias"!). Questa è la natura del lavoro di squadra e non funziona nel vuoto.

Una delle critiche al linguaggio SQL è che lo stesso risultato può essere ottenuto usando un numero di sintassi semanticamente equivalenti (alcuni usando l'algebra relazionale, altri usando il calcolo relazionale), dove la scelta del 'migliore' semplicemente scende allo stile personale. Quindi mi sento a mio agio con i join "vecchio stile" come lo sono con INNER . Se mi prenderei il tempo di riscriverli come NATURAL dipende dal contesto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top