Differenze tra Entity SQL e Transact-SQL

In questo articolo vengono illustrate le differenze tra Entity SQL e Transact-SQL.

Supporto di ereditarietà e relazioni

In Entity SQL vengono usati direttamente gli schemi di entità concettuali e sono supportate funzionalità del modello concettuale, quali l'ereditarietà e le relazioni.

Quando si usa l'ereditarietà, è spesso utile selezionare le istanze di un sottotipo da una raccolta di istanze di supertipi. Questa funzionalità viene fornita in Entity SQL dall'operatore oftype (simile a oftype nelle sequenze in C#).

Supporto per le raccolte

In Entity SQL le raccolte vengono considerate come entità di prima classe. Ad esempio:

  • Le espressioni della Collection sono valide in una clausola from.

  • Le sottoquery in e exists sono state generalizzate per consentire qualsiasi raccolta.

    Una sottoquery è un tipo di raccolta. e1 in e2 e exists(e) sono i construct di Entity SQL usati per eseguire queste operazioni.

  • Le operazioni Set, ad esempio union, intersect ed except, possono ora essere usate sulle raccolte.

  • I join funzionano sulle raccolte.

Supporto per le espressioni

In Transact-SQL sono presenti sottoquery (tabelle) ed espressioni (righe e colonne).

Per supportare le raccolte e le raccolte annidate, Entity SQL trasforma tutti gli elementi in espressione. Entity SQL offre una compatibilità migliore rispetto a Transact-SQL: ogni espressione può essere usata in qualunque posizione. Le espressioni di query restituiscono sempre raccolte dei tipi previsti e possono essere usate in qualunque posizione in cui è consentita un'espressione sulle raccolte. Per informazioni sulle espressioni Transact-SQL non supportate in Entity SQL, vedere Espressioni non supportate.

Le query seguenti sono tutte query Entity SQL valide:

1+2 *3  
"abc"  
row(1 as a, 2 as b)  
{ 1, 3, 5}
e1 union all e2  
set(e1)  

Modalità di gestione uniforme delle sottoquery

Vista l'enfasi posta sulle tabelle, in Transact-SQL viene eseguita l'interpretazione contestuale delle sottoquery. Una sottoquery nella clausola from viene ad esempio considerata come un multiset (tabella). La stessa sottoquery usata nella clausola select viene invece considerata come una sottoquery scalare. Analogamente, una sottoquery usata sul lato sinistro di un operatore in viene considerata come una sottoquery scalare, mentre sul lato destro è prevista una sottoquery multiset.

In Entity SQL vengono eliminate queste differenze. Un'espressione dispone di un'interpretazione uniforme che non dipende dal contesto in cui viene usata. Entity SQL considera tutte le sottoquery come sottoquery multiset. Se dalla sottoquery si desidera ottenere un valore scalare, Entity SQL fornisce l'operatore anyelement che opera su una raccolta, in questo caso la sottoquery, ed estrae un valore singleton dalla raccolta.

Eliminazione della presenza di coercizioni implicite per le sottoquery

Un effetto collaterale della modalità di gestione uniforme delle sottoquery è la conversione implicita delle sottoquery in valori scalari. In particolare, in Transact-SQL un multiset di righe (con un singolo campo) viene convertito in modo implicito in un valore scalare il cui tipo di dati è quello del campo.

Entity SQL non supporta questa coercizione implicita. Entity SQL fornisce un operatore ANYELEMENT per estrarre un valore singleton da una raccolta e una clausola select value per evitare di creare un wrapper di riga durante un'espressione di query.

SELECT VALUE: eliminazione della presenza del wrapper di riga implicito

Tramite la clausola SELECT in una sottoquery Transact-SQL viene creato in modo implicito un wrapper di riga intorno agli elementi della clausola. Questo implica che non si possono creare raccolte di scalari o oggetti. Transact-SQL consente una coercizione implicita tra un rowtype con un campo e un valore singleton dello stesso tipo di dati.

Entity SQL fornisce la clausola select value per ignorare la costruzione di riga implicita. Nella clausola select value è possibile specificare un solo elemento. Quando viene usata questa clausola, non viene costruito alcun wrapper di riga intorno agli elementi nella clausola select e può essere prodotta una raccolta della forma desiderata, ad esempio select value a.

Entity SQL fornisce inoltre il costruttore ROW per la costruzione di righe arbitrarie. select prende uno o più elementi nella proiezione e crea un record di dati con campi:

select a, b, c

Correlazione sinistra e utilizzo di alias

In Transact-SQL le espressioni in un determinato ambito (una singola clausola come select o from) non possono fare riferimento alle espressioni definite in precedenza nello stesso ambito. Alcuni dialetti di SQL (incluso Transact-SQL) supportano forme limitate di questi comportamenti nella clausola from.

In Entity SQL le correlazioni sinistre nella clausola from vengono generalizzate e trattate in modo uniforme. Le espressioni nella clausola from possono fare riferimento a definizioni precedenti (definizioni a sinistra) nella stessa clausola senza che sia necessaria sintassi aggiuntiva.

In Entity SQL vengono inoltre imposte restrizioni aggiuntive sulle query che implicano l'uso di clausole group by. Le espressioni nella clausola select e nella clausola having di tali query possono fare riferimento alle chiavi group by solo tramite i relativi alias. Il costrutto seguente è valido in Transact-SQL, ma non in Entity SQL:

SELECT t.x + t.y FROM T AS t group BY t.x + t.y

Per eseguire questa operazione in Entity SQL:

SELECT k FROM T AS t GROUP BY (t.x + t.y) AS k

Riferimento a colonne (proprietà) di tabelle (raccolte)

Tutti i riferimenti alle colonne in Entity SQL devono essere qualificati con l'alias di tabella. Il costrutto seguente (presupponendo che a sia una colonna valida della tabella T) è valido in Transact-SQL ma non in Entity SQL.

SELECT a FROM T

Il formato Entity SQL è

SELECT t.a AS A FROM T AS t

Gli alias di tabella sono facoltativi nella clausola from. Il nome della tabella viene usato come l'alias implicito. Entity SQL consente anche l'uso del formato seguente:

SELECT Tab.a FROM Tab

Transact-SQL usa la notazione "." per fare riferimento a colonne di (una riga di) una tabella. Entity SQL estende questa notazione (preso in prestito dai linguaggi di programmazione) per supportare la navigazione tra le proprietà di un oggetto.

Se, ad esempio, p è un'espressione del tipo Person, di seguito è riportata la sintassi Entity SQL che consente di fare riferimento alla città dell'indirizzo di tale persona.

p.Address.City

Mancanza di supporto per *

Transact-SQL supporta la sintassi * non qualificata come alias per l'intera riga e la sintassi * qualificata (t. *) come collegamento per i campi della tabella. In Transact-SQL è inoltre consentita un'aggregazione count(*) speciale che include i valori null.

Entity SQL non supporta il construct *. Le query Transact-SQL del form select * from T e select T1.* from T1, T2... possono essere espresse in Entity SQL rispettivamente come select value t from T as t e select value t1 from T1 as t1, T2 as t2.... Questi costrutti consentono inoltre di gestire l'ereditarietà (sostituibilità del valore), mentre le varianti select * sono limitate alle proprietà di primo livello del tipo dichiarato.

Entity SQL non supporta l'aggregazione count(*). Utilizzare invece count(0).

Modifiche a Group By

Entity SQL supporta l'uso di alias delle chiavi group by. Le espressioni nella clausola select e nella clausola having devono fare riferimento alle chiavi group by attraverso questi alias. Ad esempio, questa sintassi Entity SQL:

SELECT k1, count(t.a), sum(t.a)
FROM T AS t
GROUP BY t.b + t.c AS k1

...è equivalente alla sintassi Transact-SQL seguente:

SELECT b + c, count(*), sum(a)
FROM T
GROUP BY b + c

Aggregazioni basate sulle raccolte

Entity SQL supporta due tipi di aggregazioni.

Le aggregazioni basate sulle raccolte operano sulle raccolte e producono il risultato aggregato. Possono essere presenti in un punto qualsiasi nella query e non richiedono una clausola group by. Ad esempio:

SELECT t.a AS a, count({1,2,3}) AS b FROM T AS t

Entity SQL supporta inoltre aggregazioni di tipo SQL. Ad esempio:

SELECT a, sum(t.b) FROM T AS t GROUP BY t.a AS a

Utilizzo della clausola ORDER BY

Transact-SQL consente di specificare clausole ORDER BY solo nel blocco SELECT .. FROM .. WHERE in primo piano. In Entity SQL è possibile usare un'espressione ORDER BY annidata e posizionarla in un punto qualsiasi nella query, ma l'ordinamento in una query annidata non viene mantenuto.

-- The following query will order the results by the last name  
SELECT C1.FirstName, C1.LastName  
        FROM AdventureWorks.Contact AS C1
        ORDER BY C1.LastName  
-- In the following query ordering of the nested query is ignored.  
SELECT C2.FirstName, C2.LastName  
    FROM (SELECT C1.FirstName, C1.LastName  
        FROM AdventureWorks.Contact as C1  
        ORDER BY C1.LastName) as C2  

Identifiers

In Transact-SQL il confronto tra identificatori si basa sulle regole di confronto del database corrente. In Entity SQL gli identificatori non applicano mai la distinzione tra maiuscole e minuscole, mentre applicano la distinzione tra caratteri accentati e non accentati. In Entity SQL viene infatti applicata la distinzione tra caratteri accentati e non accentati, ad esempio 'a' è diverso da 'à'. In Entity SQL le versioni delle lettere che hanno lo stesso aspetto ma che provengono da tabelle codici diverse vengono gestite come caratteri differenti. Per altre informazioni, vedere Set di caratteri di input.

Funzionalità Transact-SQL non disponibili in Entity SQL

La funzionalità Transact-SQL seguente non è disponibile in Entity SQL.

DML
Entity SQL non fornisce attualmente supporto per le istruzioni DML (INSERT, UPDATE, DELETE).

DDL
Entity SQL non fornisce il supporto per DDL nella versione corrente.

programmazione imperativa
A differenza di Transact-SQL, Entity SQL non fornisce il supporto per la programmazione imperativa. Usare invece un linguaggio di programmazione.

Funzioni di raggruppamento
Entity SQL non fornisce ancora il supporto per le funzioni di raggruppamento (ad esempio CUBE, ROLLUP e GROUPING_SET).

Funzioni di analisi
Entity SQL non fornisce (ancora) il supporto per le funzioni analitiche.

Funzioni e operatori predefiniti
Entity SQL supporta un subset di funzioni e operatori predefiniti di Transact-SQL. Questi operatori e funzioni saranno supportati probabilmente dai provider dell'archivio principali. Entity SQL usa le funzioni specifiche dell'archivio dichiarate in un manifesto del provider. Entity Framework consente inoltre di dichiarare funzioni di archivio esistenti predefinite e definite dall'utente, che possono essere quindi usate da Entity SQL.

Hint
Entity SQL non fornisce meccanismi per gli hint per le query.

Invio in batch dei risultati di query
Entity SQL non supporta l'invio in batch dei risultati di query. Ad esempio, l'operazione Transact-SQL seguente (invio in batch) è valida:

SELECT * FROM products;
SELECT * FROM categories;

Non è tuttavia supportata l'espressione Entity SQL equivalente:

SELECT value p FROM Products AS p;
SELECT value c FROM Categories AS c;

Entity SQL supporta solo un'istruzione di query che restituisce un risultato per comando.

Vedi anche