Compartilhar via


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 e exists foram generalizadas para permitir quaisquer coleções.

    Um subconsulta é um tipo de coleção. e1 in e2 e exists(e) são os constructos do Entity SQL para executar essas operações.

  • A operações de conjunto, como union, intersect e except, 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

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.

Confira também