C'è qualche logica dietro la mancanza di chiusura di SQL per le operazioni standard in lingue imperative?

4

C'è qualche ragione storica o pratica per cui SQL (o più specificamente T-SQL nel mio caso) non supporta la proprietà closure in molte aree in cui molte altre famiglie linguistiche come C fanno?

(Ovvero, la proprietà di chiusura come si vede in matematica, dove un numero reale di tempo un numero reale è sempre un numero reale, niente a che fare con le chiusure nei linguaggi funzionali.)

Esempi:

  • I set di risultati delle stored procedure non possono essere utilizzati in JOIN s, ma sono nello stesso formato tabella delle tabelle e delle viste effettive.
  • La grammatica costringe gli utenti a ordinare SELECT-FROM-WHERE e regole di ordinamento aggiuntive per GROUP BY , HAVING , ecc., anche se la maggior parte di queste operazioni può essere eseguita in qualsiasi ordine in modo logicamente coerente (come con LINQ in .NET).
  • Le espressioni booleane non possono essere utilizzate in modo intercambiabile con i valori di BIT . Quindi non è possibile utilizzare un'istruzione come SELECT NOT x.IsSomething e invece è necessario utilizzare un'espressione con CASE a lungo termine.
posta JamesFaix 16.06.2016 - 18:18
fonte

2 risposte

6

1)

Sql supporta la chiusura relazionale, il che significa che è possibile utilizzare le tabelle di base, i letterali di tabella, le viste, le sottoquery, le CTE, le variabili di tabella e le funzioni a valori di tabella in modo intercambiabile nelle query e annidarle arbitrariamente.

È anche possibile utilizzare il set di risultati da una stored procedure in una query, purché si esegua la query e carichi preventivamente il risultato in una tabella temporanea o in una variabile di tabella. Non puoi includere l' esecuzione di una stored procedure come parte di una query, per due motivi:

  1. Una stored procedure potrebbe non restituire nessuno o più set di risultati. Non è noto al momento della compilazione quali risultati verranno restituiti, quindi non è possibile generare un piano di query.
  2. Le procedure memorizzate possono avere effetti collaterali. Questo non può essere logicamente supportato come parte di una query. Voglio dire, la procedura potrebbe abbandonare la tabella a cui è unita, o potrebbe emettere un comando esterno per arrestare il database.

Una funzione con valori di tabelle multistato supporta alcune delle stesse logiche complesse delle stored procedure (variabili, condizionali ecc.) ma con i vincoli che non possono avere effetti collaterali e lo schema del set di risultati è definito staticamente. Per questo motivo le funzioni a valori di tabella possono essere utilizzate come sottoquery, al contrario delle stored procedure.

2)

Tu puoi utilizzare la proiezione, i filtri e il raggruppamento in ordine arbitrario, se nidifichi sottoquery. Having è solo zucchero di sintassi per filtrare una sottoquery con un raggruppamento. Ma la sintassi con sottoquery nidificate è certamente più ingombrante. Ciò è probabilmente dovuto al fatto che SQL è stato progettato per i non programmatori, quindi una semplice sintassi "inglese come" è stata preferita per una sintassi più "programmabile".

Order by può verificarsi solo come ultima clausola di una query, ma in realtà ciò è coerente con la chiusura relazionale. Poiché una relazione è per definizione non ordinata, non è possibile conservare l'ordine in un'operazione di relazioni. Quindi l'ordine deve essere l'ultima operazione sul set di risultati. (La clausola top è concettualmente dopo order by , anche se è la prima nella sintassi. Poiché prende in considerazione l'ordine, non è nemmeno un operatore relazionale)

Al contrario, Linq è più flessibile perché consente di ordinare operazioni arbitrariamente mescolate con la proiezione, il filtraggio e il raggruppamento. Ma questo perché Linq non è relazionale. Funziona su sequenze ordinate . L'ordine è chiuso su sequenze ordinate, ma non su relazioni.

In breve: SQL supporta l'algebra e la chiusura relazionale, la sintassi è piuttosto alquanto clunky per gli standard moderni.

3)

SQL ha una logica a tre valori , quindi un booleano è vero , falso o sconosciuto . Quindi non può essere mappato direttamente a un tipo di bit, sebbene possa teoricamente essere mappato su un bit nullable, con il valore sconosciuto che corrisponde a null .

Ma c'è un problema più profondo. Nelle espressioni scalari tsql e le espressioni booleane sono consentite in posizioni diverse nella sintassi e non sono intercambiabili. Quindi non c'è modo di ottenere comunque un risultato booleano come valore!

Lo standard SQL inizialmente non supportava i booleani come un tipo di prima classe e le espressioni booleane come intercambiabili con espressioni scalari, ma il supporto era stato introdotto in SQL: 1999. SQL Server ancora non supporta questo, ma non è più una limitazione fondamentale di SQL.

    
risposta data 16.06.2016 - 19:12
fonte
4

Is there some historical or practical reason why SQL (or more specifically T-SQL in my case) does not support the closure property in many areas where many other language families like C do?

La ragione storica è che Codd ha definito il concetto per la prima volta nel 1970 e non è stato trasformato in ciò che ora chiameremmo SQL fino al 1974. Molte delle cose che farebbero farlo in uno stile matematicamente chiudibile da fare in il software attuale veniva descritto per la prima volta in articoli accademici all'incirca nello stesso periodo. In altre parole, le persone non stavano pensando in quel modo. C non era ancora apparso, e il fatto che le cose potessero funzionare in quel modo in altre lingue ha avuto molto a che fare con il fatto che non hai filtrato, ordinato o raggruppato i risultati delle espressioni aritmetiche.

La ragione pratica è che SQL potrebbe essere implementato in un modo per portare a termine il lavoro senza tassare le risorse di calcolo disponibili durante quell'era. Come ho detto in un commento, SQL è ancora abbastanza potente per portare a termine il lavoro che molti sviluppatori non considerano la sintassi come un impedimento.

Informazioni sui reclami specifici:

Result sets from stored procedures cannot be used in JOINs, but the are in the same table format as actual tables and views.

SQL standard ISO ha una parte facoltativa (ISO 9075-4) che definisce stored procedure che non penso che nessuno implementi la lettera. Ciò rende le stored procedure e la capacità di trattare i risultati di una funzione come tabelle un'estensione soggetta ai limiti dell'implementazione. Ci sono altri database in grado di gestirlo senza battere ciglia.

Boolean expressions cannot be used interchangably with BIT values.

Ancora una volta, questa è una limitazione dell'implementazione. Non esiste un tipo BIT in ISO SQL come lo definisce Transact-SQL. BIT di T-SQL è un tipo intero che può rappresentare i valori 0 e 1 ; ISO SQL ha BIT(n) che rappresenta un array di bit di lunghezza n . ISO SQL-99 ha introdotto BOOLEAN , e non credo che Microsoft l'abbia mai implementato. T-SQL ha la nozione di un valore booleano consentito come parte della grammatica della query in posizioni molto specifiche, ma non è un tipo memorizzabile di prima classe. Questo è tutto ciò che Microsoft sta facendo.

...So a statement like SELECT NOT x.IsSomething cannot be used and instead a long-winded CASE expression needs to be used.

NOT (x.IsSomething = 1) sarebbe perfettamente equivalente a NOT x.IsSomething . Questo è un effetto collaterale del tipo BIT di T-SQL che è un intero molto breve e l'incapacità di SQL Server di eseguire il cast di un intero in un valore booleano basato sulla sua zero-ness o non-zero-ness. PostgreSQL, ad esempio, se ne prende cura automagicamente, ma Oracle non lo fa e ti fa affermare le tue intenzioni usando un operatore di confronto. Entrambi gli approcci hanno i loro pregi e problemi. Dovrei andare a scavare lo standard per vedere se ISO favorisce un comportamento rispetto all'altro.

The grammar constrains users to SELECT-FROM-WHERE ordering, and additional ordering rules for GROUP BY, HAVING, etc., even though most of those operations can be performed in any order in a logically consistent manner (such as with LINQ in .NET).

Non ho particolare familiarità con LINQ, ma uno sguardo superficiale alla documentazione dell'API per i provider sembra rivelare che internamente si occupa di tutte queste cose in gruppi nello stesso modo in cui lo fa SQL. Il fatto che tu possa comporre una query in qualsiasi ordine tu voglia è solo un bel rivestimento, e ci sono librerie là fuori che possono assemblare una query SQL allo stesso modo.

Ci sono, come rileva JacquesB nella sua risposta, modi per fare il genere di cose che stai cercando in SQL. Spetta a te se soddisfano i tuoi standard di purezza del design; la realtà pratica rimane che per la maggior parte delle persone, SQL ha completato il lavoro.

    
risposta data 17.06.2016 - 15:58
fonte

Leggi altre domande sui tag