Database
 sql >> Database >  >> RDS >> Database

Fondamenti di espressioni di tabella, parte 1

Questo articolo è il primo di una serie sui fondamenti delle espressioni di tabella in T-SQL. Mi concentrerò principalmente su quattro tipi di espressioni di tabelle con nome, note in T-SQL come tabelle derivate, espressioni di tabelle comuni (CTE), viste e funzioni con valori di tabella inline (TVF inline).

Sono stato ispirato a scrivere questa serie dal mio buon amico, Grant Fritchey, che conosco da molti anni. Come sottolineato ripetutamente da Grant, molti di coloro che utilizzano espressioni di tabella comuni in T-SQL pensano che SQL Server resti il ​​set di risultati della query interna e che la ragione di questa convinzione sia l'uso del termine tabella nel nome del costrutto. Quando questo argomento emerge nelle discussioni della comunità, spesso le persone sostengono che l'uso del termine tabella nel nome del costrutto è inappropriato poiché non è realmente una tabella. Ci sono anche suggerimenti per avviare una campagna di denominazione nella speranza di vedere un futuro cambio di nome per questo costrutto, almeno in T-SQL. Alcuni dei suggerimenti includono espressione di query , visualizzazione in linea , vista a livello di istruzione , e altri.

Forse questo sarà una sorpresa per alcuni, ma in realtà trovo l'uso del termine tabella in common table expression come molto appropriato. In effetti, trovo l'uso del termine espressione di tabella a seconda dei casi. Per me, il modo migliore per descrivere cos'è un CTE in T-SQL, è un'espressione di tabella denominata . Lo stesso vale per ciò che T-SQL chiama tabelle derivate (il costrutto del linguaggio specifico in contrasto con l'idea generale), viste e TVF inline. Sono tutte espressioni di tabella con nome.

Se puoi sopportarmi un po', fornirò il ragionamento per la mia visione delle cose in questo articolo. Mi è venuto in mente che sia la confusione sui nomi, sia la confusione sul fatto che ci sia un aspetto di persistenza nelle espressioni di tabella, possono essere chiarite con una migliore comprensione dei fondamenti del nostro campo di sistemi di gestione di database relazionali. Questi elementi fondamentali sono la teoria relazionale, il modo in cui SQL (il linguaggio standard) è correlato ad esso e il modo in cui il dialetto T-SQL utilizzato nelle implementazioni di SQL Server e del database SQL di Azure è correlato a entrambi.

Come punto di partenza, vuoi essere in grado di rispondere alle seguenti domande:

  • Che cosa significa l'indipendenza dei dati fisici principio nel modello relazionale significa?
  • Che cos'è una tabella in SQL e qual è la controparte nel modello relazionale?
  • Qual è la proprietà di chiusura dell'algebra relazionale?
  • Che cos'è un'espressione tabellare e qual è la controparte nel modello relazionale?

Una volta che sarai in grado di rispondere correttamente alle domande di cui sopra, molto probabilmente troverai l'uso del termine espressione di tabella denominata come appropriato per i suddetti costrutti (ciò che T-SQL chiama tabelle derivate, CTE, viste e TVF inline).

Non voglio sembrare di avere una comprensione molto profonda della teoria relazionale. La mia esperienza è T-SQL. Riconosco che c'è molto di più che non so sulla teoria relazionale di me, e che alcune cose che penso di sapere, semplicemente non lo sono. Quando leggo gli scritti di C. J. Dates sull'argomento, sento di scalfire a malapena la superficie di ciò che c'è da sapere e che potrei, e dovrei, sforzarmi di capirlo meglio. Riconosco e credo fermamente che una buona comprensione della teoria relazionale si traduca direttamente in una migliore comprensione di SQL e T-SQL e nella scrittura di codice T-SQL migliore, più accurato e più robusto. Per chiunque scelga i dati come carriera, consiglio di leggere SQL and Relational Theory:How to Write Accurate SQL Code 3rd Edition di CJ Date (O'Reilly 2015).

Nella prima parte di questa serie voglio stabilire una comprensione del mio uso dei termini espressione di tabella e espressione di tabella denominata , che è in accordo con l'uso di questo termine da parte di Date e sfortunatamente non in accordo con l'uso di questo termine da parte dello standard SQL. Per raggiungere questo obiettivo, fornirò un po' di background dalla teoria relazionale e dallo standard SQL. Ma come ho detto, consiglio di leggere il libro di Date per una copertura davvero dettagliata di questo argomento.

Inizierò spiegando cosa significa il principio di indipendenza dei dati fisici. Successivamente, spiegherò cos'è una tabella in SQL e la sua controparte nella teoria relazionale. Spiegherò quindi cosa significa la proprietà di chiusura dell'algebra relazionale. Una volta che hai un'idea ragionevole di cosa sia una tabella e cosa significhi la proprietà di chiusura, diventa abbastanza semplice capire cos'è un'espressione di tabella. La mia attenzione si sposterà quindi alle specifiche in T-SQL. Ho molto da dire sui fondamenti delle espressioni di tabella in T-SQL, sia in termini di trattamento concettuale che in termini di dettagli di implementazione, inclusa la rappresentazione fisica e le considerazioni sull'ottimizzazione delle query.

Trovo questo argomento affascinante e molto pratico una volta approfonditi i dettagli di implementazione. In effetti, ho così tanto da dire al riguardo che non sono sicuro di quante parti comporterà questa serie alla fine. Quello che posso dirti con un grande grado di sicurezza è che ci saranno più parti. Probabilmente più di uno e meno di 100. Nelle parti future analizzerò i singoli tipi di espressioni di tabelle con nome, le considerazioni sulla modifica, gli aspetti di inlining, gli aspetti di ordinamento, le correlazioni e altro ancora.

Nei miei esempi userò un database di esempio chiamato TSQLV5. Puoi trovare lo script che crea e popola questo database qui e il suo diagramma ER qui.

Indipendenza dei dati fisici

L'indipendenza dei dati fisici è un principio nella teoria relazionale che afferma che i dettagli di implementazione fisica dovrebbero essere nascosti o trasparenti all'utente che invia le query al sistema di gestione del database relazionale. Nelle query, gli utenti dovrebbero concentrarsi su cosa hanno bisogno di usare operazioni logiche basate sull'algebra relazionale, al contrario di come per ottenere i dati. Non dovrebbero preoccuparsi di come i dati sono strutturati, accessibili ed elaborati. Tali dettagli di implementazione fisica tendono a differire sostanzialmente tra le diverse implementazioni (prodotti RDBMS). Anche con lo stesso RDBMS, i dettagli dell'implementazione fisica a volte cambiano tra versioni e build diverse. L'idea alla base del principio di indipendenza dei dati fisici in teoria è quella di proteggere l'investimento dell'utente eliminando la necessità di rivedere le soluzioni quando si aggiorna l'RDBMS a una nuova versione o anche quando si migra da un RDBMS a un altro. Come probabilmente saprai bene, in pratica le cose non sono così semplici, ma questo è un argomento per una discussione diversa.

Cos'è un tavolo?

Se hai lavorato con T-SQL o qualsiasi altro dialetto di SQL per un po', sviluppi una comprensione intuitiva di cos'è una tabella. Il problema è che senza un po' di background di teoria relazionale, spesso la comprensione intuitiva non è molto accurata. Un errore tipico è che tendiamo intuitivamente a concentrarci sui dettagli di implementazione fisica. Ad esempio, quando stai pensando a cosa sia una tabella, stai pensando a una tabella come a una struttura logica (un insieme di righe) o stai pensando ai dettagli di implementazione fisica nella piattaforma che stai utilizzando (in SQL Server , pagine, estensioni, heap rispetto a indice cluster, indici non cluster e così via)? Come utente che scrive codice SQL per interrogare una tabella, seguendo il principio di indipendenza dei dati fisici, dovresti pensare alla tabella come a una struttura logica e lasciare che l'RDBMS si preoccupi dei dettagli di implementazione fisica. Quindi, facciamo un passo indietro e cerchiamo di capire cos'è un tavolo.

Una tabella è la controparte di SQL della struttura principale nella teoria relazionale:una relazione. Per mantenere le cose semplici e limitare l'ambito della mia copertura, non entrerò nella distinzione tra una variabile di relazione e un valore di relazione. Se segui la mia raccomandazione e leggi il libro di Date, avrai molto rapidamente un quadro chiaro di tali sottigliezze.

Una relazione ha un titolo e un corpo.

L'intestazione della relazione è un insieme di attributi . Nella teoria matematica degli insiemi, un insieme non ha ordine né duplicati. Dovresti identificare un attributo per nome e non per posizione. Di conseguenza, i nomi degli attributi devono essere univoci.

Riesci a identificare qual è la controparte di un attributo in SQL? Probabilmente hai intuito che si tratta di una colonna . Tuttavia, SQL ha effettivamente una nozione di ordine per le sue colonne in base al loro ordine di apparizione nell'istruzione CREATE TABLE. Ad esempio, ecco l'istruzione CREATE TABLE per la tabella Sales.Shippers nel database TSQLV5:

CREATE TABLE Sales.Shippers
(
  shipperid   INT          NOT NULL IDENTITY,
  companyname NVARCHAR(40) NOT NULL,
  phone       NVARCHAR(24) NOT NULL,
  CONSTRAINT  PK_Shippers  PRIMARY KEY(shipperid)
);

Interroga la tabella utilizzando il famigerato SELECT * , in questo modo:

SELECT * FROM Sales.Shippers;

Quando ho eseguito questa query nel mio sistema, ho ottenuto il seguente output:

shipperid  companyname    phone
---------- -------------- ---------------
1          Shipper GVSUA  (503) 555-0137
2          Shipper ETYNR  (425) 555-0136
3          Shipper ZHISN  (415) 555-0138

SQL garantisce che le colonne verranno restituite da sinistra a destra in base all'ordine di definizione. Spiegherò cosa succede con le righe a breve. SQL ti consente anche di fare riferimento alla posizione ordinale della colonna dall'elenco SELECT nella clausola ORDER BY, in questo modo (non che io stia raccomandando questa pratica, né Aaron Bertrand):

SELECT shipperid, companyname, phone
FROM Sales.Shippers
ORDER BY 2;

Questa query genera il seguente output:

shipperid  companyname    phone
---------- -------------- ---------------
2          Shipper ETYNR  (425) 555-0136
1          Shipper GVSUA  (503) 555-0137
3          Shipper ZHISN  (415) 555-0138

Il corpo di una relazione è un insieme di tuple . Ancora una volta, ricorda che un set non ha ordine né duplicati. Pertanto, una relazione deve avere almeno una chiave candidata che consente di identificare in modo univoco una tupla. La controparte SQL di una tupla è una riga . Tuttavia, in SQL non sei obbligato a definire una chiave in una tabella e, in caso contrario, puoi finire con righe duplicate. Anche se hai una chiave definita nella tabella, puoi ottenere righe duplicate restituite da una query sulla tabella. Ecco un esempio:

SELECT country FROM HR.Employees;

Questa query genera il seguente output:

country
--------
USA
USA
USA
USA
UK
UK
UK
USA
UK

Questa query non produce un risultato relazionale a causa della possibilità di righe duplicate. Mentre la teoria relazionale si basa sulla teoria degli insiemi, SQL si basa sulla teoria dei multiinsiemi. Un multiset (ovvero un superset o una borsa) può avere duplicati. SQL ti offre uno strumento per eliminare i duplicati con una clausola DISTINCT, in questo modo:

SELECT DISTINCT country FROM HR.Employees;

Questa query genera il seguente output:

country
--------
UK
USA

Ciò che SQL mantiene dalla teoria relazionale in termini di corpo della tabella è la proprietà senza ordine. A meno che tu non aggiunga una clausola ORDER BY nella query, non hai alcuna garanzia che il risultato avrà un ordine specifico tra le righe. Quindi, il corpo del risultato della query precedente è relazionale, almeno nel senso che non ha duplicati e non ha un ordine garantito.

Si supponga di eseguire una query su una tabella in SQL Server e di non includere una clausola ORDER BY nella query. Si prevede che SQL Server restituisca sempre le righe in un ordine specifico come comportamento garantito? Molte persone lo fanno. Molti pensano che recupererai sempre le righe in base all'ordine dell'indice cluster. Questo è un buon esempio di ignorare il principio di indipendenza dei dati fisici e fare ipotesi basate sull'intuizione e forse basate sul comportamento osservato in passato. Microsoft sa che una query SQL senza una clausola ORDER BY non garantisce alcun ordine tra le righe dei risultati, e quindi anche se a livello fisico i dati risiedono in una struttura di indice, SQL Server non deve elaborare i dati in indice ordine. Può scegliere, in determinate condizioni fisiche, di farlo, ma può scegliere di non farlo in altre condizioni fisiche. Ricorda inoltre che i dettagli dell'implementazione fisica possono cambiare tra le diverse versioni e build del prodotto. Se vuoi garantire che la query restituirà le righe dei risultati in un ordine specifico, l'unico modo per garantirlo è introdurre una clausola ORDER BY nella query più esterna.

Come probabilmente avrai capito, i progettisti di SQL non consideravano davvero una priorità seguire la teoria relazionale. E quello che ho descritto qui sono solo alcuni esempi. Ce ne sono molti di più. Come accennato in precedenza, il mio obiettivo in questo articolo è solo quello di fornire una base teorica sufficiente per chiarire la confusione che circonda le espressioni di tabella, prima di iniziare ad approfondire le specifiche di T-SQL negli articoli futuri.

Cos'è un'espressione di tabella?

L'algebra relazionale (l'algebra che definisce le operazioni sulle relazioni nella teoria relazionale) ha una chiusura proprietà. Ciò significa che un'operazione sulle relazioni produce una relazione. Un operatore relazionale opera su una o più relazioni come input e produce una singola relazione come output. La proprietà di chiusura consente di annidare le operazioni. Un espressione relazionale è un'espressione che opera sulle relazioni e restituisce una relazione. Un'espressione relazionale può quindi essere utilizzata laddove l'algebra relazionale si aspetta una relazione.

Se ci pensi, non è diverso dalle operazioni su numeri interi che producono un risultato intero. Supponiamo che la variabile @i sia una variabile intera. L'espressione @i + 42 restituisce un numero intero e quindi può essere utilizzata dove è previsto un numero intero, come in (@i + 42) * 2.

Dato che una tabella in SQL è la controparte di una relazione nella teoria relazionale, anche se non ha molto successo, un'espressione di tabella in SQL è la controparte di un'espressione relazionale. Come accennato in precedenza, utilizzo il termine espressione di tabella dopo l'uso di questo termine da parte di C. J. Dates. Lo standard SQL ha una serie di termini confusi, alcuni dei quali temo non siano molto appropriati. Ad esempio, lo standard SQL utilizza il termine espressione di tabella per descrivere specificamente un'espressione basata sulle clausole di query che iniziano con una clausola FROM obbligatoria e includendo opzionalmente le clausole WHERE, GROUP BY, HAVING e WINDOW (l'ultima non è supportata in T -SQL) ed escludendo la clausola SELECT. Ecco le specifiche dello standard:

7.4

Funzione
Specifica una tabella o una tabella raggruppata.

Formato

::=

[ ]
[ ]
[ ]
[ ]

È vero che il risultato di ciò che lo standard chiama un'espressione di tabella è considerato una tabella, ma non è possibile utilizzare tale espressione come query autonoma. La versione di Date del termine espressione di tabella è in realtà più vicina a ciò che lo standard SQL chiama espressione di query . Ecco le specifiche dello standard per ciò che chiama espressione di query:

7.17

Funzione
Specifica una tabella.

Formato
::=
[ ]
[ ] [ ] [ ]
::=
CON [ RICORSIVA ]
::=
[ { }… ]
::=
[ ]
AS [ ]
::=

::=

| UNION [ TUTTI | DISTINCT ]
[ ]
| EXCEPT [ TUTTI | DISTINCT ]
[ ]
::=

| INTERSECA [ TUTTI | DISTINCT ]
[ ]
::=

|
[ ] [ ] [ ]

::=

|
|
::=
TABLE
::=
CORRISPONDENTE [ BY ]
::=

::=
ORDINA PER
::=
OFFSET { ROW | ROWS }
::=
FETCH { FIRST | AVANTI } [ ] { RIGA | RIGHE } { SOLO | CON PARAGGI }
::=

|
::=

::=

::=
PERCENT

7.3

Funzione
Specifica un insieme di da costruire in una tabella.

Formato
::=
VALUES
::=
[ { }… ]
::=
VALUES
::=

[ { }… ]

Osserva che questa specifica include ciò che T-SQL chiama espressione di tabella comune, anche se lo standard non usa realmente questo termine, ma lo chiama semplicemente con elemento elenco . Osserva inoltre che la cosiddetta espressione di query non deve essere basata su una query, ma potrebbe essere basata su quello che viene chiamato un costruttore di valori di tabella (l'uso di una clausola VALUES per costruire un insieme di righe). Infine, anche se l'espressione di query dello standard è basata su un'espressione, restituisce una tabella e può essere utilizzata dove normalmente è prevista una tabella. Per questi motivi, trovo molto più appropriato l'uso del termine table expression da parte di Date.

Conclusione

Posso capire perché alcuni potrebbero trovare l'indugiare sulla denominazione e sulla terminologia un po' pedante e forse anche una perdita di tempo. Mi sento molto diverso, però. Credo che in qualsiasi campo, l'aspirazione a usare nomi propri e terminologia ti costringa a studiarne bene le basi e rifletta sulle tue conoscenze. Nella speranza che in questo articolo non sono riuscito ad alienarti abbastanza da non voler procedere con le parti imminenti della serie, a partire dall'articolo del prossimo mese, rivolgerò la mia attenzione al modo in cui i diversi tipi di nomi le espressioni di tabella vengono gestite tramite T-SQL in SQL Server e nel database SQL di Azure.