本文介绍实体 SQL 和 Transact-SQL 之间的差异。
继承和关系支持
实体 SQL 直接使用概念实体架构,并支持概念模型功能,例如继承和关系。
使用继承时,从超类型实例集合中选择子类型的实例通常很有用。 Entity SQL 中的 type 运算符(类似于 oftype
C# 序列)提供此功能。
集合支持
实体 SQL 将集合视为一流的实体。 例如:
在
from
子句中,集合表达式是有效的。in
和exists
子查询已通用化以允许任何集合。子查询是一种集合。
e1 in e2
和exists(e)
是用于执行这些操作的实体 SQL 构造。集合操作,例如
union
、intersect
和except
,现在对集合进行操作。联接对集合执行运算。
对表达式的支持
Transact-SQL 具有子查询(表)和表达式(行和列)。
为了支持集合和嵌套集合,Entity SQL 使所有内容都成为表达式。 实体 SQL 比 Transact-SQL 更可组合, 每个表达式都可以在任何位置使用。 查询表达式始终会导致投影类型的集合,并且可在允许集合表达式的任何位置使用。 有关实体 SQL 中不支持的 Transact-SQL 表达式的信息,请参阅 不支持的表达式。
以下是所有有效的实体 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
运算符左侧使用的子查询被视为标量子查询,而位于其右侧的子查询应为多集子查询。
实体 SQL 消除了这些差异。 表达式具有不依赖于其使用的上下文的统一解释。 实体 SQL 将所有子查询视为多集子查询。 如果希望从子查询中取得标量值,Entity SQL 提供了一个用于在集合(在此例中是子查询)上进行操作的 anyelement
运算符,以从集合中提取一个单值。
避免对子查询执行隐式强制转换
子查询的统一处理的相关副作用是将子查询隐式转换为标量值。 具体而言,在 Transact-SQL 中,多组行(具有单个字段)隐式转换为标量值,其数据类型为该字段的标量值。
实体 SQL 不支持此隐式强制。 Entity SQL 提供 ANYELEMENT
运算符从集合中提取单一值,以及一个 select value
子句,以避免在查询表达式期间创建行包装。
Select Value:避免隐式行包装
在 Transact-SQL 子查询中的 select 子句会隐式地为子句中的项创建一个行包装器。 这意味着我们不能创建标量或对象的集合。 Transact-SQL 允许在具有一个字段的 rowtype
与相同数据类型的单一实例值之间进行隐式强制转换。
Entity SQL 提供子句select value
以便跳过隐式行构造。 在 select value
子句中只能指定一个项。 在使用这样的子句时,不会对 select
子句中的项构造行包装器,并且可生成所需形状的集合,例如:select value a
。
实体 SQL 还提供用于构造任意行的行构造函数。
select
接受投影中的一个或多个元素,并生成含有字段的数据记录,如下所示:
select a, b, c
左相关与别名化
在 Transact-SQL 中,给定作用域(例如 select
或 from
)中的表达式不能引用之前在同一作用域中定义的表达式。 SQL 的一些方言(包括 Transact-SQL)确实在 from
子句中支持这些形式的某些有限形式。
实体 SQL 概括了 from
子句中的左相关性,并统一处理它们。 子句中的 from
表达式可以引用同一子句中的早期定义(左侧定义),而无需其他语法。
实体 SQL 还会对包含 group by
子句的查询施加额外的限制。 此类查询的 select
子句和 having
子句中的表达式只能通过其别名引用 group by
关键字。 以下构造在 Transact-SQL 中有效,但不在实体 SQL 中:
SELECT t.x + t.y FROM T AS t group BY t.x + t.y
若要在实体 SQL 中执行此操作,请按照以下步骤进行:
SELECT k FROM T AS t GROUP BY (t.x + t.y) AS k
引用表(集合)的列(属性)
实体 SQL 中的所有列引用都必须使用表别名进行限定。 以下构造(假设 a
是表 T
的有效列)在 Transact-SQL 中有效,但在实体 SQL 中无效。
SELECT a FROM T
Entity SQL 形式为
SELECT t.a AS A FROM T AS t
表别名在 from
子句中是可选的。 表的名称用作隐式别名。 实体 SQL 还允许以下形式:
SELECT Tab.a FROM Tab
通过对象导航
Transact-SQL 使用“.”表示法来引用表(行)的列。 实体 SQL 扩展此表示法(从编程语言借用)以支持通过对象的属性进行导航。
例如,如果 p
为 Person 类型的表达式,则下面是用于引用此人地址市的实体 SQL 语法。
p.Address.City
不支持 *
Transact-SQL 支持使用非限定性 * 语法作为整个行的别名,并且支持使用限定性 * 语法 (t.*) 作为该表字段的快捷方式。 此外,Transact-SQL 允许使用一种特殊的 count(*) 聚合,其中包括 Null。
实体 SQL 不支持 * 构造。 Transact-SQL 形式为 select * from T
和 select T1.* from T1, T2...
的查询可以分别在实体 SQL 中表示为 select value t from T as t
和 select value t1 from T1 as t1, T2 as t2...
。 此外,这些构造处理继承(值替代性),而 select *
变体仅限于声明类型的顶级属性。
实体 SQL 不支持 count(*)
聚合。 请改用 count(0)
。
对 Group By 的更改
Entity SQL 支持 group by
键别名。
select
子句和having
子句中的表达式必须通过这些别名引用group by
键。 例如,此实体 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
基于集合的聚合
实体 SQL 支持两种类型的聚合。
基于集合的聚合对集合进行作并生成聚合结果。 这些内容可以出现在查询中的任何位置,并且不需要一个 group by
子句。 例如:
SELECT t.a AS a, count({1,2,3}) AS b FROM T AS t
实体 SQL 还支持 SQL 样式聚合。 例如:
SELECT a, sum(t.b) FROM T AS t GROUP BY t.a AS a
ORDER BY 子句用法
Transact-SQL 允许仅在最顶层 ORDER BY
块中指定 SELECT .. FROM .. WHERE
子句。 在 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”不等于“ấ”)。 实体 SQL 将显示相同但来自不同代码页的字母版本视为不同的字符。 有关详细信息,请参阅 输入字符集。
在实体 SQL 中,功能 Transact-SQL 不可用。
实体 SQL 中不提供以下 Transact-SQL 功能。
DML
实体 SQL 当前不支持 DML 语句(插入、更新、删除)。
DDL
实体 SQL 不支持当前版本中的 DDL。
命令性编程
实体 SQL 不支持命令性编程,与 Transact-SQL 不同。 请改用编程语言。
分组函数
实体 SQL 尚不支持分组函数(例如 CUBE、ROLLUP 和 GROUPING_SET)。
分析函数
实体 SQL 尚不支持分析函数。
内置函数、运算符
实体 SQL 支持 Transact-SQL 的内置函数和运算符的子集。 这些运算符和函数可能受到主要存储提供程序的支持。 实体 SQL 使用在提供程序清单中声明的与存储相关的函数。 此外,Entity Framework 还允许声明用于实体 SQL 的内置和用户定义的现有存储函数。
提示
实体 SQL 不提供查询提示的机制。
批处理查询结果
实体 SQL 不支持批处理查询结果。 例如,下面是有效的 Transact-SQL(以批处理的形式发送):
SELECT * FROM products;
SELECT * FROM categories;
但是,实体 SQL 的等效版本不被支持:
SELECT value p FROM Products AS p;
SELECT value c FROM Categories AS c;
实体 SQL 仅支持每个命令一个生成结果的查询语句。