实体 SQL 与 Transact-SQL 有何不同

本文介绍实体 SQL 和 Transact-SQL 之间的差异。

继承和关系支持

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

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

集合支持

实体 SQL 将集合视为一流的实体。 例如:

  • from 子句中,集合表达式是有效的。

  • inexists 子查询已通用化以允许任何集合。

    子查询是一种集合。 e1 in e2exists(e) 是用于执行这些操作的实体 SQL 构造。

  • 集合操作,例如 unionintersectexcept,现在对集合进行操作。

  • 联接对集合执行运算。

对表达式的支持

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 中,给定作用域(例如 selectfrom)中的表达式不能引用之前在同一作用域中定义的表达式。 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 Tselect T1.* from T1, T2... 的查询可以分别在实体 SQL 中表示为 select value t from T as tselect 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 仅支持每个命令一个生成结果的查询语句。

另请参阅