このトピックでは、Entity SQL と Transact-SQL の相違点について説明します。
継承とリレーションシップのサポート
Entity SQL は、エンティティの概念スキーマを直接操作し、継承やリレーションシップなどの EDM 機能をサポートしています。
継承を操作するときは、スーパータイプ インスタンスのコレクションからサブタイプのインスタンスを選択すると便利である場合がよくあります。Entity SQL 内の oftype 演算子 (C# シーケンスの oftype に相当) によってこの機能が提供されます。この演算子と他の種類の演算子の詳細については、「型演算子 (Entity SQL)」を参照してください。
コレクションのサポート
Entity SQL では、コレクションをファーストクラスのエンティティとして取り扱います。以下にサンプルを示します。
コレクションの式は、from 句内で有効です。
in サブクエリと exists サブクエリは任意のコレクションを使用できるように一般化されています。
サブクエリは一種のコレクションです。
e1 in e2
およびexists(e)
は、これらの演算を実行する Entity SQL コンストラクトです。union、intersect、except などの集合演算は、現在ではコレクションに対して実行されます。
結合はコレクションに対して実行されます。
式のサポート
Transact-SQL にはサブクエリ (テーブル) と式 (行と列) があります。
コレクションおよび入れ子になったコレクションをサポートするために、Entity SQL ではすべてを式として取り扱います。SQL とは異なり、Entity SQL はコンポーザブルです。つまり、すべての式はどこでも使用できます。クエリ式は常に投射型のコレクションとなり、コレクション式が許可されている任意の場所で使用できます。Entity SQL でサポートされていない Transact-SQL 式の詳細については、「サポートされていない式 (Entity 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 句を使用してクエリ式の実行中に row ラッパーが作成されないようにします。
SELECT VALUE: 暗黙の row ラッパーの回避
Transact-SQL ではクエリの結果があいまいに処理されます。Transact-SQL サブクエリ内の SELECT 句では、句内の項目に row ラッパーを暗黙的に作成します。これは、スカラやオブジェクトのコレクションを作成できないことを意味します。Transact-SQL では、1 つのフィールドの RowType と、同じデータ型のシングルトン値との間の暗黙の強制型変換を許可しています。
Entity SQL には、暗黙の行の構築をスキップする select value 句が用意されています。select value 句には 1 つの項目のみを指定できます。このような句を使用した場合、select 句内の項目には row ラッパーは構築されず、目的の構造を持つコレクションを作成できます。たとえば、select value a
のように指定します。
Entity SQL には、任意の行を構築するための行コンストラクタも用意されています。select は、投影の 1 つ以上の要素を受け取り、フィールドを持つデータ レコードを結果として得ます。次のように指定します。
select a, b, c
左の相関関係と別名定義
Transact-SQL では、1 つのスコープ内の式 (select または from のような単一句) は同じスコープ内で先に定義された式を参照できません。一部の 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 内の列の参照は、すべてテーブルの別名を使用して修飾する必要があります。次の構造は Transact-SQL では有効ですが、Entity SQL では無効です (a
がテーブル T
の有効な列である場合)。
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 では NULL を含む特殊な count(*) 集計も使用できます。
Entity SQL では * 構造をサポートしていません。select * from T
および select T1.* from T1, T2...
の形式の Transact-SQL クエリは、Entity SQL ではそれぞれ select value t from T as t
および select value t1 from T1 as t1, T2 as t2...
として表すことができます。また、これらの構造は継承 (値の置換可能性) に対応していますが、select * Variant 型では宣言された型の最上位レベルのプロパティに限定されています。
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 は、2 種類の集計をサポートしています。
コレクションベースの集計は、コレクションに対して演算を行い、集計結果を生成します。これらはクエリ内の任意の場所で使用でき、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 では、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' と 'ấ' は等しくありません)。Entity SQL では、同じように表示される文字であってもコード ページが異なる場合は、異なる文字と見なされます。詳細については、「入力文字セット (Entity SQL)」を参照してください。
Entity SQL では使用できない Transact-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 Data Model では Entity SQL が使用する既存の組み込みストア関数とユーザー定義ストア関数を宣言できます。
- ヒント
Entity SQL ではクエリ ヒントのメカニズムは提供していません。