Entity SQL 与 Transact-SQL 有何不同

本文介绍 Entity SQL 和 Transact-SQL 之间的不同。

继承和关系支持

Entity SQL 直接使用概念实体架构并支持诸如继承和关系等概念模型功能。

使用继承时,从父类型实例集合中选择子类型的实例通常是有用的。 Entity SQL 中的 oftype 运算符(类似于 C# Sequences 中的 oftype)提供了此功能。

集合支持

Entity SQL 将集合视为第一类实体。 例如:

  • 集合表达式在 from 子句中有效。

  • inexists 子查询已被一般化,以允许使用任何集合。

    子查询是一种集合。 e1 in e2exists(e) 是执行这些运算的 Entity SQL 构造。

  • 集运算(例如 unionintersectexcept)现在对集合执行运算。

  • 联接对集合执行运算。

对表达式的支持

Transact-SQL 具有子查询(表)和表达式(行和列)。

为了支持集合和嵌套集合,Entity SQL 使所有内容成为表达式。 Entity SQL 比 Transact-SQL 更具组合性 - 每个表达式都可以在任何位置使用。 查询表达式总是产生投影类型的集合,并且可以在允许使用集合表达式的任何地方使用。 有关 Entity SQL 不支持的 Transact-SQL 表达式的信息,请参阅不支持的表达式

以下是所有有效的 Entity SQL 查询:

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

子查询统一处理

虽然 Transact-SQL 将重点放在表上,但它对子查询执行上下文解释。 例如,from 子句中的子查询被视为多集(表)。 但是,select 子句中使用的同一子查询被视为标量子查询。 同样,在 in 运算符左侧使用的子查询被视为标量子查询,而位于其右侧的子查询应为多集子查询。

Entity SQL 消除了这些差异。 表达式具有不依赖于使用它的上下文的统一解释。 Entity SQL 将所有子查询都视为多集子查询。 如果需要从子查询获取标量值,则 Entity SQL 会提供对集合(在此情况下为子查询)进行运算的 anyelement 运算符,并从集合中提取单一实例值。

避免对子查询执行隐式强制转换

与统一处理子查询相关的一个副作用是将子查询隐式转换为标量值。 具体而言,在 Transact-SQL 中,行多集(具有单个字段)将被隐式转换为数据类型与该字段相同的标量值。

Entity SQL 不支持这种隐式强制。 Entity SQL 提供 ANYELEMENT 运算符从集合中提取单一实例值,并提供 select value 子句以避免在查询表达式中创建行包装器。

Select Value:避免隐式行包装

Transact-SQL 子查询中的 select 子句在该子句中的项周围隐式创建一个行包装器。 这意味着我们无法创建标量或对象的集合。 Transact-SQL 允许在具有一个字段的 rowtype 与相同数据类型的单一实例值之间进行隐式强制转换。

Entity SQL 提供了 select value 子句,以跳过隐式行构造。 在 select value 子句中只能指定一个项。 在使用这样的子句时,不会对 select 子句中的项构造行包装器,并且可生成所需形状的集合,例如:select value a

Entity SQL 还提供了用于构造任意行的行构造函数。 select 接受投影中的一个或多个元素,并生成含有字段的数据记录,如下所示:

select a, b, c

左相关与别名化

在 Transact-SQL 中,给定作用域(像 selectfrom 这样的单个子句)中的表达式不能引用在同一作用域中先前定义的表达式。 SQL 的一些分支(包括 Transact-SQL)确实在 from 子句中支持这些表达式的有限形式。

Entity SQL 在 from 子句中对左相关进行了一般化,并且对它们进行了统一处理。 from 子句中的表达式无需使用额外的语法,即可引用同一子句中先前的定义(位于左侧的定义)。

Entity SQL 还对涉及 group by 子句的查询施加了额外的限制。 此类查询的 select 子句和 having 子句中的表达式只能通过其别名引用 group by 关键字。 下面的构造在 Transact-SQL 中有效,但在 Entity SQL 中无效:

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

若要在 Entity SQL 中执行此操作:

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

引用表(集合)的列(属性)

Entity SQL 中的所有列引用都必须用表别名限定。 以下构造(假定 a 是表 T 的有效列)在 Transact-SQL 中有效,但在 Entity SQL 中无效。

SELECT a FROM T

Entity SQL 形式为

SELECT t.a AS A FROM T AS t

表别名在 from 子句中是可选的。 表名称被用作隐式别名。 Entity SQL 还允许使用以下形式:

SELECT Tab.a FROM Tab

Transact-SQL 使用“.”表示法来引用表的(某行的)列。 Entity SQL 扩展了这一表示法(借用自编程语言),为通过对象的属性导航提供支持。

例如,如果 p 是 Person 类型的表达式,则下面是用于引用此人地址所在城市的 Entity SQL 语法。

p.Address.City

不支持 *

Transact-SQL 支持使用非限定性 * 语法作为整个行的别名,并且支持使用限定性 * 语法 (t.*) 作为该表字段的快捷方式。 此外,Transact-SQL 允许使用一种特殊的 count(*) 聚合,其中包括 Null。

Entity SQL 不支持 * 构造。 形式为 select * from Tselect T1.* from T1, T2... 的 Transact-SQL 查询在 Entity SQL 中可以分别表示为 select value t from T as tselect value t1 from T1 as t1, T2 as t2...。 此外,这些构造还处理继承(值可替换性),同时将 select * 变体限制到所声明类型的顶级属性。

Entity SQL 不支持 count(*) 聚合。 请改用 count(0)

对 Group By 的更改

Entity SQL 支持 group by 键别名。 select 子句和 having 子句中的表达式必须通过这些别名引用 group by 关键字。 例如,此 Entity SQL 语法:

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

...等效于以下 Transact-SQL:

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

基于集合的聚合

Entity SQL 支持两种聚合。

基于集合的合计对集合进行运算,并且产生合计结果。 它们可以出现在查询中的任何位置,并且不需要 group by 子句。 例如:

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

Entity SQL 还支持 SQL 样式的聚合。 例如:

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

ORDER BY 子句用法

Transact-SQL 允许仅在最顶层 SELECT .. FROM .. WHERE 块中指定 ORDER BY 子句。 在 Entity SQL 中,可以使用嵌套的 ORDER BY 表达式,并且可以将其放置在查询中的任何地方,但不会保留嵌套查询中的排序。

-- 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  

标识符

在 Transact-SQL 中,标识符比较基于当前数据库的排序规则。 在 Entity SQL 中,标识符始终不区分大小写但区分重音(即,Entity SQL 区分重音字符和非重音字符;例如,“a”不等于“ấ”)。 Entity SQL 将看上去相同但来自不同代码页的字母视为不同的字符。 有关详细信息,请参阅输入字符集

Transact-SQL 功能在 Entity SQL 中不可用

以下 Transact-SQL 功能在 Entity SQL 中不可用。

DML
Entity SQL 当前未提供对 DML 语句(insert、update、delete)的支持。

DDL
Entity SQL 的当前版本未提供对 DDL 的支持。

命令式编程
Entity SQL 不支持命令式编程,这一点与 Transact-SQL 不同。 请改而使用编程语言。

分组函数
Entity SQL 尚未提供对分组函数(例如,CUBE、ROLLUP 和 GROUPING_SET)的支持。

分析函数
Entity SQL 尚未提供对分析函数的支持。

内置函数、运算符
Entity SQL 支持 Transact-SQL 的内置函数和运算符的子集。 这些运算符和函数可能受到主要存储提供程序的支持。 Entity SQL 使用在提供程序清单中声明的特定于存储的函数。 此外,使用实体框架可以声明内置的和用户定义的现有存储函数,以供 Entity SQL 使用。

提示
Entity SQL 不提供查询提示机制。

查询结果批处理
Entity SQL 不支持查询结果批处理。 例如,下面是有效的 Transact-SQL(在批处理中发送):

SELECT * FROM products;
SELECT * FROM categories;

但是,不支持等效的 Entity SQL:

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

Entity SQL 仅支持在每个命令中使用一个由结果生成的查询语句。

请参阅