Como o Entity SQL difere do Transact-SQL
Este artigo descreve as diferenças entre o Entity SQL e o Transact-SQL.
Suporte a herança e relações
O Entity SQL trabalha diretamente com esquemas conceituais de entidade e dá suporte a recursos do modelo conceitual, como a herança e relações.
Ao trabalhar com herança, geralmente é útil selecionar instâncias de um subtipo de uma coleção de instâncias de supertipo. O operador oftype no Entity SQL (semelhante ao oftype
em sequências de C#) oferece essa funcionalidade.
Suporte para coleções
O Entity SQL trata coleções como entidades de primeira classe. Por exemplo:
As expressões de coleção são válidas em uma cláusula
from
.As subconsultas
in
eexists
foram generalizadas para permitir quaisquer coleções.Um subconsulta é um tipo de coleção.
e1 in e2
eexists(e)
são os constructos do Entity SQL para executar essas operações.A operações de conjunto, como
union
,intersect
eexcept
, agora funcionam em coleções.As junções funcionam em coleções.
Suporte para expressões
O Transact-SQL tem subconsultas (tabelas) e expressões (linhas e colunas).
Para oferecer suporte a coleções e coleções aninhadas, o Entity SQL transforma tudo em uma expressão. O Entity SQL é mais combinável do que o Transact-SQL, cada expressão pode ser usada em qualquer lugar. As expressões de consulta sempre resultam em coleções dos tipos projetados e podem ser usadas em qualquer lugar em que uma expressão de coleção seja permitida. Para obter informações sobre expressões Transact-SQL que não têm suporte no Entity SQL, confira Expressões sem suporte.
Todos os itens a seguir são consultas válidas do Entity SQL:
1+2 *3
"abc"
row(1 as a, 2 as b)
{ 1, 3, 5}
e1 union all e2
set(e1)
Tratamento uniforme de subconsultas
Dada a sua ênfase em tabelas, o Transact-SQL realiza a interpretação contextual de subconsultas. Por exemplo, um subconsulta na cláusula from
é considerada um multiset (tabela). Mas a mesma subconsulta usada na cláusula select
é considerada uma subconsulta escalar. Da mesma forma, uma subconsulta usada no lado esquerdo de um operador in
é considerada uma subconsulta escalar, embora espere-se que o lado direito seja um subconsulta multiset.
O Entity SQL elimina essas diferenças. Uma expressão tem uma interpretação uniforme que não depende do contexto no qual é usada. O Entity SQL considera todas as subconsultas multiset. Se for desejado um valor escalar da subconsulta, o Entity SQL fornecerá o operador anyelement
que opera em uma coleção (neste caso, a subconsulta), e extrai um valor singleton da coleção.
Evitando coerções implícitas para subconsultas
Um efeito colateral relacionado ao tratamento uniforme de subconsultas é a conversão implícita de subconsultas em valores escalares. Especificamente, no Transact-SQL, um multiset de linhas (com um único campo) é convertido implicitamente em um valor escalar cujo tipo de dados é o do campo.
O Entity SQL não dá suporte a essa coerção implícita. O Entity SQL fornece o operador ANYELEMENT
para extrair um valor singleton de uma coleção, e uma cláusula select value
para evitar criar um wrapper de linha durante uma expressão de consulta.
Select Value: evitando o wrapper de linha implícito
A cláusula select em uma subconsulta do Transact-SQL cria implicitamente um wrapper de linha ao redor dos itens na cláusula. Isso indica que não podemos criar coleções de escalares ou objetos. O Transact-SQL permite uma coerção implícita entre um rowtype
com um campo e um valor singleton do mesmo tipo de dados.
O Entity SQL fornece a cláusula select value
para ignorar a construção de linha implícita. Somente um item pode ser especificado em uma cláusula select value
. Quando tal cláusula é usada, nenhum wrapper de linha é construído ao redor dos itens na cláusula select
, e uma coleção da forma desejada pode ser gerada, por exemplo, select value a
.
O Entity SQL também fornece o construtor de linha para construir linhas arbitrárias. select
utiliza um ou mais elementos da projeção e resulta em um registro de dados com campos:
select a, b, c
Correlação à esquerda e aliases
No Transact-SQL, as expressões em um determinado escopo (uma cláusula única, como select
ou from
) não podem referenciar expressões definidas anteriormente no mesmo escopo. Alguns dialetos do SQL (incluindo o Transact-SQL) oferecem suporte a formas limitadas delas na cláusula from
.
O Entity SQL generaliza as correlações à esquerda na cláusula from
e trata-as uniformemente. As expressões na cláusula from
podem referenciar as definições anteriores (definições à esquerda) na mesma cláusula sem a necessidade de sintaxe adicional.
O Entity SQL também impõe restrições adicionais em consultas que envolvem cláusulas group by
. As expressões na cláusula select
e na cláusula having
dessas consultas podem se referir apenas às chaves group by
através dos aliases. O constructo a seguir é válido no Transact-SQL, mas não está no Entity SQL:
SELECT t.x + t.y FROM T AS t group BY t.x + t.y
Para fazer isso no Entity SQL:
SELECT k FROM T AS t GROUP BY (t.x + t.y) AS k
Referenciando colunas (propriedades) de tabelas (coleções)
Todas as referências a colunas no Entity SQL devem ser qualificadas com o alias de tabela. O constructo a seguir (supondo-se que a
seja uma coluna válida da tabela T
) é válido no Transact-SQL, mas não no Entity SQL.
SELECT a FROM T
O formulário do Entity SQL é
SELECT t.a AS A FROM T AS t
Os aliases de tabela são opcionais na cláusula from
. O nome da tabela é usado como o alias implícito. O Entity SQL permite também a forma a seguir:
SELECT Tab.a FROM Tab
Navegação por objetos
O Transact-SQL usa a notação “.” para referenciar colunas de (uma linha de) uma tabela. O Entity SQL amplia essa notação (emprestada de linguagens de programação) para oferecer suporte à navegação pelas propriedades de um objeto.
Por exemplo, se p
for uma expressão do tipo Pessoa, a sintaxe do Entity SQL a seguir fará referência à cidade do endereço dessa pessoa.
p.Address.City
Nenhum suporte para *
O Transact-SQL dá suporte à sintaxe * não qualificada como um alias da linha inteira e à sintaxe * qualificada (t.*) como um atalho para os campos dessa tabela. Além disso, o Transact-SQL permite uma agregação count(*) especial, que inclui nulos.
O Entity SQL não dá suporte ao constructo *. As consultas do Transact-SQL do formulário select * from T
e select T1.* from T1, T2...
podem ser expressas no Entity SQL como select value t from T as t
e select value t1 from T1 as t1, T2 as t2...
, respectivamente. Além disso, essas construções manipulam a herança (substituibilidade do valor), embora as variantes select *
sejam restritas a propriedades de nível superior do tipo declarado.
O Entity SQL não dá suporte à agregação count(*)
. Use count(0)
em vez disso.
Alterações em group by
O Entity SQL dá suporte ao alias das chaves group by
. As expressões na cláusula select
e na cláusula having
devem fazer referência às chaves group by
através desses alias. Por exemplo, esta sintaxe do Entity SQL:
SELECT k1, count(t.a), sum(t.a)
FROM T AS t
GROUP BY t.b + t.c AS k1
... é equivalente ao seguinte Transact-SQL:
SELECT b + c, count(*), sum(a)
FROM T
GROUP BY b + c
Agregações baseadas em coleção
O Entity SQL dá suporte a dois tipos de agregações.
As agregações baseadas em coleção operam em coleções e geram o resultado agregado. Elas podem aparecer em qualquer lugar na consulta, e não requerem uma cláusula group by
. Por exemplo:
SELECT t.a AS a, count({1,2,3}) AS b FROM T AS t
O Entity SQL também dá suporte a agregações do tipo SQL. Por exemplo:
SELECT a, sum(t.b) FROM T AS t GROUP BY t.a AS a
Uso da cláusula ORDER BY
O Transact-SQL permite que cláusulas ORDER BY
sejam especificadas somente no bloco SELECT .. FROM .. WHERE
. No Entity SQL, você pode usar uma expressão ORDER BY
aninhada e ela pode ser colocada em qualquer lugar na consulta, mas a ordenação em uma consulta aninhada não é preservada.
-- 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
Identificadores
No Transact-SQL, a comparação de identificadores é baseada na ordenação do banco de dados atual. No Entity SQL, os identificadores não diferenciam maiúsculas de minúsculas e diferenciam acentos (ou seja, o Entity SQL distingue entre caracteres acentuados e não acentuados, por exemplo, 'a' não é igual a 'ấ'). O Entity SQL trata versões de letras que aparecem o mesmo mas é páginas diferentes de código como caracteres diferentes. Para saber mais, confira Conjunto de caracteres de entrada.
Funcionalidade Transact-SQL não disponível em Entity SQL
A funcionalidade do Transact-SQL a seguir não está disponível no Entity SQL.
DML
O Entity SQL não dá suporte para instruções DML (inserção, atualização, exclusão).
DDL
O Entity SQL não dá suporte para DDL na versão atual.
Programação imperativa
O Entity SQL não dá suporte para programação imperativa, ao contrário do Transact-SQL. Use, em vez disso, uma linguagem de programação.
Funções de agrupamento
O Entity SQL ainda não dá suporte para funções de agrupamento (por exemplo, CUBE, ROLLUP e GROUPING_SET).
Funções Analíticas
O Entity SQL (ainda) não dá suporte para funções analíticas.
Funções internas, operadores
O Entity SQL dá suporte a um subconjunto de operadores e funções internas do Transact-SQL. Esses operadores e funções provavelmente têm suporte com os principais provedores de repositório. O Entity SQL usa as funções específicas ao repositório declaradas em um manifesto do provedor. Além disso, o Entity Framework permite que você declare as funções de repositório internas e definidas pelo usuário existentes para que o Entity SQL use.
Dicas
O Entity SQL não oferece mecanismos para dicas de consulta.
Processando resultados de consulta em lotes
O Entity SQL não dá suporte a resultados de consulta em lotes. Por exemplo, a sintaxe do Transact-SQL a seguir é válida (enviando como um lote):
SELECT * FROM products;
SELECT * FROM categories;
No entanto, o Entity SQL equivalente não tem suporte:
SELECT value p FROM Products AS p;
SELECT value c FROM Categories AS c;
O Entity SQL dá suporte a apenas uma instrução de consulta que gera resultado por comando.