現代のほとんどのリレーショナル言語においては、 SQL はタプルリレーショナル論理に基づいています。 その結果、タプルリレーショナル論理(もしくは同様にリレーショナル代 数)を使用することによって表現できるあらゆる問い合わせは、また SQLを使用して表現することもできます。しかし、リ レーショナル題意数やリレーショナル論理の範囲を越えた能力もあります。 以下に示すのは、リレーショナル代数やリレーショナル論理の一部でない SQLによって提供されるいくつかの追加機能のリスト です。
データの挿入、削除、修正のためのコマンド
計算能力:SQLでは、比較と同様に算術演算を含む ことが可能です。例えば、
A < B + 3.注: + やその他の算術演算子は、リレーショナル代数でも、リレーショナル 論理にもありません。
割り当てと表示コマンド:問い合わせによって作られるリレーションを 表示したり、計算されたリレーションをリレーション名に割り当てること も可能です。
集約関数:average, sum, maxといった 操作でリレーションの列に対して一つの数値を得ることができます。
SQLで最もよく使われるコマンドはSELECT文です。これ はデータを検索するために使われます。文法は以下の通りです。
SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ] * | expression [ AS output_name ] [, ...] [ INTO [ TEMPORARY | TEMP ] [ TABLE ] new_table ] [ FROM from_item [, ...] ] [ WHERE condition ] [ GROUP BY expression [, ...] ] [ HAVING condition [, ...] ] [ { UNION | INTERSECT | EXCEPT [ ALL ] } select ] [ ORDER BY expression [ ASC | DESC | USING operator ] [, ...] ] [ FOR UPDATE [ OF class_name [, ...] ] ] [ LIMIT { count | ALL } [ { OFFSET | , } start ]]
ここで様々な例でSELECT文の複雑な構文を説明します。例で使われている テーブルはSUPPLIER と PART データベースで 定義されています。
SELECT文を使った簡単な例は以下の通りです。
Example 1-4. 条件による簡単な問い合わせ
テーブル PART から、属性 PRICE が 10 を越えるすべてのタプルを 検索するには、以下のような問い合わせを作ります。
SELECT * FROM PART WHERE PRICE > 10;結果が以下のように得られます。
PNO | PNAME | PRICE -----+---------+-------- 3 | Bolt | 15 4 | Cam | 25
SELECT文で "&*&" を使用することで、テーブルのすべての 属性をとりだします。もしテーブル PART から属性 PNAME と PRICE だけを取り出したければ、以下の文を使用します。
SELECT PNAME, PRICE FROM PART WHERE PRICE > 10;この場合の結果は以下のようになります。
PNAME | PRICE --------+-------- Bolt | 15 Cam | 25SQLの SELECT がリレーショナル代数における 「選択」ではなく「射影」に一致することに注意してください。(詳 細は リレーショナル代数 をご覧ください)
WHERE句における条件は OR, AND, NOT といったキーワードを使用し て論理的につなげることができます。
SELECT PNAME, PRICE FROM PART WHERE PNAME = 'Bolt' AND (PRICE = 0 OR PRICE <= 15);このような結果が得られます。
PNAME | PRICE --------+-------- Bolt | 15
算術演算を、ターゲット・リスト(訳注:SELECT文で指定する、取り出 す属性のリストのこと)や WHERE句で使用できます。例えば、 PART テーブル の 2倍の値段がどれくらいなのか知りたければ、以下のよ うな問い合わせを発行することができます。
SELECT PNAME, PRICE * 2 AS DOUBLE FROM PART WHERE PRICE * 2 < 50;結果は以下のように得られます。
PNAME | DOUBLE --------+--------- Screw | 20 Nut | 16 Bolt | 30キーワード AS の後にある DOUBLE は2番目の列の新しいタイトルで あるという点に注意してください。このテクニックはターゲットリス トのあらゆる要素に使われ、結果の列を新しいタイトルにすることが できます。この新しいタイトルはしばしば別名といわれます。別名は 問い合わせの残りの部分では使用できません。
以下の例は、結合 がSQL でどのように表現されるかについてです。
SUPPLIER,PART,SELLS という共通の属性をもつ3つのテーブルを結合す るために、以下の文を考えてみます。
SELECT S.SNAME, P.PNAME FROM SUPPLIER S, PART P, SELLS SE WHERE S.SNO = SE.SNO AND P.PNO = SE.PNO;結果として以下のようなテーブルが得られます。
SNAME | PNAME -------+------- Smith | Screw Smith | Nut Jones | Cam Adams | Screw Adams | Bolt Blake | Nut Blake | Bolt Blake | Cam
共通の名前がつけられた属性(SNOとPNO)がリレーション中にあるので、 FROM句ですべてのリレーションに対して別名をつけています。 ここで属性名の前に別名と続くドットをつけることにより、同じ名前を もつ属性を区別することができます。結合は内部結合に出てくるのと同じ 方法で計算されています。まず、直積は SUPPLIER × PART × SELLS を導き出します。次にこれらのタプルから WHERE句で指定される条件を満たす ものだけが選択されます。(すなわち、共通の名前がつけられた属性名 は等しくなければいけない)最後に、 S.NAME と P.PNAME 以外のすべて の列を射影します。
結合を行うもう一つの方法は次のように SQL の JOIN 文を使用することです。
select sname, pname from supplier JOIN sells USING (sno) JOIN part USING (pno);結果は前と同じです。
sname | pname -------+------- Smith | Screw Adams | Screw Smith | Nut Blake | Nut Adams | Bolt Blake | Bolt Jones | Cam Blake | Cam (8 rows)
JOIN 文を使用してできた結合テーブルは、WHERE句も ,GROUP BY や HAVING 句よりも前におかれた FROM 句内の発生するテーブルリファ レンスならび項目です。 FROM 句内で、 WHERE 句・GROUP BY 句、HAVING 句が始まる前には、 テーブルリファレンス並びを置くことができますが、JOIN 文によっ てできる結合テーブルはこのリファレンスならびの中の一項目とし て使うことができます。コンマで区切られるならば、他のテーブル 参照やテーブル名や他の JOIN を FROM 句ni 含んでもかまいません。 結合されたテーブルは論理上 FROM 句でリストされる他のどのテー ブルと同じです。
SQL の JOIN には2つの主要な型があります。交差結合(修飾なし結 合) と修飾結合です。修飾結合は、 ON,USING,NATURAL といった結合条件とそれが適用 される方法(内部結合または外部結合)によって更に分類されます。
結合型
{ T1 } CROSS JOIN { T2 }
交差結合は、N行のテーブルT1とM行のテーブルT2に ついて、互いの行のあらゆる組合わせを行った結果 のテーブル(N*M行)を返します。T1の各行R1につい て、T2の各行R2をR1に結合し、結果のテーブルの行 JRとします。ここで JRにはR1,R2全ての属性が含ま れています。CROSS JOIN は INNER JOIN ON TRUE と同等です。
{ T1 } [ NATURAL ] [ INNER | { LEFT | RIGHT | FULL } [ OUTER ] ] JOIN { T2 } { ON search condition | USING ( join column list ) }
修飾結合は、NATURAL,ON,USING のうちの1つ(しかもたった1つだけ)を指定す ることによってその結合条件を指定しなければいけません。ON句は、 search conditionが必要です。これは WHERE 句 と同じようなものです。USING句は、列名のコンマで区切られたリストが必要 です。ここで結合されるテーブルは共通の列名をもっていなければならずこれ らの列が等しいという条件で結合します。NTRURAL は、2つのテーブルに共通 の列名すべてをリストした USING 句の短縮形です。USING と NATURAL による 副作用は、結合された列のうちの片方のコピーだけが結果テーブルに現れるこ とです。(すでにでた JOIN のリレーショナル代数の定義と比較してください。)
[ INNER ] JOIN
T1の各行R1について、T2の各行のうちR1との結合条件を満たしたものが結合後 のテーブルの行に含まれます。
Tip: INNER と OUTER という単語はすべての結合にオプションで指定することがで きます。INNER はデフォルトです。LEFT,RIGHT,FULL を指定すると、自動的に OUTER も指定したことになります。
LEFT [ OUTER ] JOIN
まず、INNER JOIN が実行されます。それから、T2のどの行をもってきても結 合条件が満たされないようなT1の行について、T2の列に相当する部分には NULL をセットして結合結果を追加します。
Tip: 結合後のテーブルには、T1のすべての行に対応する行が無条件に含まれます。
RIGHT [ OUTER ] JOIN
まず、INNER JOIN を実行します。それから、T1のどの行をもってきても結合 条件が満たされないような T2 の行について、T1 の列に相当する部分には NULL をセットして結合結果に追加します。
Tip: 結合後のテーブルには、T2のすべての行に対応する行が無条件に含まれます。
FULL [ OUTER ] JOIN
まず、INNER JOIN が実行されます。それから、T2 のどの行をもってきても結 合条件が満たされないような T1 の行について、T2 の列に相当する部分には NULL をセットして結合結果に追加します。さらに同様に、T1のどの行をもっ てきても結合条件が満たされないような T2 の行について、T1 の列に相当す る部分には NULL をセットして結合結果に追加します。
Tip: 結合後のテープルには、T1 のすべての行に対応する行が無条件に含まれます し、T2 のすべての行に対応する行も無条件に含まれます。
結合はどんな型のものでも連結したりネストする(すなわちT1かT2の一方もしくは両方が、結合でできたテー ブルになっている) ことができます。結合は通常左から右へ処理されますが、 JOIN 句を括弧でくくって結合順を指定することもできます。
SQLは引数として式をとる集約関数(たとえば AVG, COUNT, SUM, MIN, MAX)を提供しています。式は WHERE 句で合致したそ れぞれの行に対して評価されます。そして、集約演算子は入力値の集合 に対して集約演算が計算されます。通常集約は SELECT 文に対して単一 行の結果を返します。しかし、問い合わせにおいてグループわけを行っ た場合には、それぞれのグループの行に対して別々に演算を行います。 そして、集約の結果はグループ毎に返されます。(次節を参照してくだ さい)
Example 1-5. 集約
PART テーブルのすべての部品の平均値を知りたい場合には以下の ような問い合わせを行います。
SELECT AVG(PRICE) AS AVG_PRICE FROM PART;
結果は
AVG_PRICE ----------- 14.5
PARTテーブルで定義されたパーツの数を知りたい場合には以下のよう にします。
SELECT COUNT(PNO) FROM PART;以下のような結果になります。
COUNT ------- 4
SQLではテーブルのタプルをグループに分割させる ことができます。それから、上で記述された集約の演算子は、各グルー プに適用させることができます。すなわちその列のすべての値に対して ではなく、各グループ毎に集約演算しが別々に適用されます。
グループへのタプルの分割は GROUP BYというキー ワードの後にグループを定義する属性のリストを続けることで行います。 GROUP BY A1, ⃛, Akとすれば、ある2つの行が同じグ ループに振り分けられるのは、属性A1, ⃛, Ak すべてが等しくなっている時かつ その時に限ることになります。
Example 1-6. 集約
どのくらいの部品がそれぞれの供給者で売られているか知りたい場 合には、このような問い合わせが考えられます。
SELECT S.SNO, S.SNAME, COUNT(SE.PNO) FROM SUPPLIER S, SELLS SE WHERE S.SNO = SE.SNO GROUP BY S.SNO, S.SNAME;そして以下が得られます。
SNO | SNAME | COUNT -----+-------+------- 1 | Smith | 2 2 | Jones | 1 3 | Adams | 2 4 | Blake | 3
ここで起こったことを見てみましょう。まず、SUPPLIER と SELLS テー ブルの結合が行われます。
S.SNO | S.SNAME | SE.PNO -------+---------+-------- 1 | Smith | 1 1 | Smith | 2 2 | Jones | 4 3 | Adams | 1 3 | Adams | 3 4 | Blake | 2 4 | Blake | 3 4 | Blake | 4
次に、S.NO と S.SNAME の両方の属性が等しい全てのタプルを同じグ ループに分割します。
S.SNO | S.SNAME | SE.PNO -------+---------+-------- 1 | Smith | 1 | 2 -------------------------- 2 | Jones | 4 -------------------------- 3 | Adams | 1 | 3 -------------------------- 4 | Blake | 2 | 3 | 4
この例では、4つのグループを得ることができました。そして、集約 演算子 COUNT を各グループに適用し、上で示した問い合わせの最終 結果を得ます。
GROUP BY と集約演算子を使っている問い合わせが意味をなすためには、 ターゲットリストの中に直接記述できる属性は GROUP BY で指定した属 性のみであることに注意してください。その他の属性は、集約関数の引 数の内部から間接的に使用できるだけです。そうでないと他の属性と関 係づけられる一意の値が存在しないことになります。
また、例えば AVG(MAX(sno))のように、集約の集約は意味をなさないこ とにも注意しましょう。SELECT はグループ化と集約については1パスの 処理しかしないからです。この種のことがやりたければ、FROM 句で副 問い合わせや一時テーブルを使って、内側の(最初の)集約の処理を1段 階行えばよいでしょう。
HAVING 句は WHERE 句のような働きをします。つまり HAVING 句で指定 された条件を満たすグループのみが抽出されて SELECT の対象になりま す。本質的に、グループ化と集約演算が行われる前に、WHERE句は不必 要な入力行を省くのに対して、HAVINGは GOURP 化された後のグループ のそれぞれの行に対して不必要なグループを省きます。よって、WEHRE は集約関数の結果を使うことができません。一方で、HAVING には集約 関数を含むことができないなどの条件はありません!条件に集約を含ま ないのであれば WHERE を使って書いた方がいいでしょう。その方が、 結局は捨ててしまうグループに対する集約計算をしなくてすみます。
Example 1-7. Having
複数の部品を売っている供給者のみを調べたい場合には、この 問い合わせを行います。
SELECT S.SNO, S.SNAME, COUNT(SE.PNO) FROM SUPPLIER S, SELLS SE WHERE S.SNO = SE.SNO GROUP BY S.SNO, S.SNAME HAVING COUNT(SE.PNO) > 1;結果は以下の通りです。
SNO | SNAME | COUNT -----+-------+------- 1 | Smith | 2 3 | Adams | 2 4 | Blake | 3
WHERE と HAVING 句で値が使えるような場所ならどこでも副問い合わせ (subqyery,subselect)が使用できます。この場合、先に副問い合わせが 評価され、得られた結果がその場所での値として使われます。副問い合 わせの使用はSQLに表現力を拡張します。
Example 1-8. 副問い合わせ
'Screw'という名前の部品よりも値段が高い部品をすべて検索したい 場合には、
SELECT * FROM PART WHERE PRICE > (SELECT PRICE FROM PART WHERE PNAME='Screw');
結果はこうなります。
PNO | PNAME | PRICE -----+---------+-------- 3 | Bolt | 15 4 | Cam | 25
上記の問い合わせを振り返ってみると、SELECT というキーワードが2 回現れているのが分かります。一つは問い合わせの最初にあるもので すが、以下では外側の SELECT と呼ぶことにします。もう一つは WHERE 句の中にあって入れ子の問い合わせの始まりになっているもの で、以下では内側の SELECT と呼ぶことにします。そして、内側の SELECT を参照します。外側の SELECT のあらゆるタプルに対して内 側の SELECT が評価されていなければいけません。内側の SELECT の 評価をするごとに、'Screw' という名前のタプルの値段がわかり、実 際のタプルの価格がそれより高いかが判断できます。(実際にはこの例 では、内側の問い合わせは一度の評価のみしか必要とされません。なぜなら その結果は外側の問い合わせの状態に依存せずに決まるからです。)
どの部品も売っていない供給者をすべて求める場合(例えば、データ ベースからこれらの供給者を削除する場合)には以下を使用します。
SELECT * FROM SUPPLIER S WHERE NOT EXISTS (SELECT * FROM SELLS SE WHERE SE.SNO = S.SNO);
例ではどの供給者も少なくとも一つの部品を売っているので、結果は 空です。内側の SELECT の WHERE 句中で外側の SELECT の S.SNO を 使用していることに注意してください。この場合は、外側の問い合わ せの各タプルに対して、副問い合わせが新たに評価しなおされる必要 があります。すなわち、S.SNOの値は、外側の SELECT が現在処理し ているタプルから常に取り出されるのです。
副問い合わせの別の使い方は、FROM句に副問い合わせを使うことです。 このような使い方では副問い合わせが複数の列と行を出力することがで きるので非常に有効です、一方式の中の副問い合わせは単一の結果のみ を返さなければいけません。またこのような副問い合わせにより、一時 テーブルを使うという手段にでることなく、複数段のグループ化と集約 計算を行うことができます。
Example 1-9. FROM句中の副問い合わせ
すべての供給者の中から部品の平均価格が最も高いところを知りたい 場合には MAX(AVG(PRICE)) と書くことはできませんが、以下のよう に記述することができます。
SELECT MAX(subtable.avgprice) FROM (SELECT AVG(P.PRICE) AS avgprice FROM SUPPLIER S, PART P, SELLS SE WHERE S.SNO = SE.SNO AND P.PNO = SE.PNO GROUP BY S.SNO) subtable;供給者は一カ所につき一つの行(GROUP BY を供給者に適用したので) を返します。そして、外側の問い合わせでこれらの行を集計します。
これらの操作は和、積、2つの副問い合わせによって得られたタプルの 差である集合論的差を計算します。
Example 1-10. Union, Intersect, Except
以下の問い合わせは UNION の例です。
SELECT S.SNO, S.SNAME, S.CITY FROM SUPPLIER S WHERE S.SNAME = 'Jones' UNION SELECT S.SNO, S.SNAME, S.CITY FROM SUPPLIER S WHERE S.SNAME = 'Adams';結果は以下の通りです。
SNO | SNAME | CITY -----+-------+-------- 2 | Jones | Paris 3 | Adams | Vienna
次は INTERSECT の例です。
SELECT S.SNO, S.SNAME, S.CITY FROM SUPPLIER S WHERE S.SNO > 1 INTERSECT SELECT S.SNO, S.SNAME, S.CITY FROM SUPPLIER S WHERE S.SNO < 3;以下のような結果が得られます。
SNO | SNAME | CITY -----+-------+-------- 2 | Jones | Paris問い合わせの前後半どちらからの結果にも含まれる唯一のタプルは SNO が 2のものものです。
最後は EXCEPT の例です。
SELECT S.SNO, S.SNAME, S.CITY FROM SUPPLIER S WHERE S.SNO > 1 EXCEPT SELECT S.SNO, S.SNAME, S.CITY FROM SUPPLIER S WHERE S.SNO > 3;結果は以下のように得られます。
SNO | SNAME | CITY -----+-------+-------- 2 | Jones | Paris 3 | Adams | Vienna
SQLに含まれるデータ定義に使われるコマンド群についてです。
データ定義における最も基本的なコマンドは新しいリレーション(テー ブル)を作成するものです。 CREATE TABLE コマンドの文法は以下の通 りです。
CREATE TABLE table_name (name_of_attr_1 type_of_attr_1 [, name_of_attr_2 type_of_attr_2 [, ...]]);
Example 1-11. テーブルの作成
SUPPLIER と PART データベースのテーブル 定義をSQL文で表すと以下のような記述になりま す。
CREATE TABLE SUPPLIER (SNO INTEGER, SNAME VARCHAR(20), CITY VARCHAR(20));
CREATE TABLE PART (PNO INTEGER, PNAME VARCHAR(20), PRICE DECIMAL(4 , 2));
CREATE TABLE SELLS (SNO INTEGER, PNO INTEGER);
以下はSQLでサポートされているいくつかのデータ 型のリストです。
INTEGER: 符号付き整数 (31 ビットの精度).
SMALLINT: 符号付き整数 (15 ビット精度).
DECIMAL (p[,q]): 小数点以上が p桁までで、小数 点以下が q桁まで の、符号付きのパック 10進数。 qが省略された場合には 0 とみなされます。
FLOAT: 符号付き倍精度実数
CHAR(n): 長さ nの固定長文字列
VARCHAR(n): 最大 n文字の可変長文 字列
インデックスはリレーションにアクセスする速度をあげるために使用さ れます。例えば、リレーションRの属性 Aにインデックスが張られているものとします。 この時、t(A) = aであるようなタプル全部を取り出すのに は、この条件を満たすタプルの数のほぼ比例する時間だけでできてしま い、R全体のタプル数に比例する時間はかかり ません。
SQLにおけるインデックスの作成には CREATE INDDEX コマンドが使用されます。文法は以下の通りです。
CREATE INDEX index_name ON table_name ( name_of_attribute );
Example 1-12. Create Index
リレーション SUPPLIER の SNAME 属性に I という名前のインデック スを作成する場合には、以下のような文となります。
CREATE INDEX I ON SUPPLIER (SNAME);
作成されたインデックスは自動的に更新されます。つまりリレーショ ン SUPPLIER に新しいタプル i を挿入した時にはインデックス I も 修正されます。ユーザからみた場合の唯一のインデックスがあること による違いは SELECT の速度が上昇して、更新の速度が遅くなること だということに注意してください。
ビューは仮想的なテーブルと考えられます。 すなわちデータベース中に物理的には 存在しないがユーザにとってはそれが存在するように見えるということ です。一方、基底テーブルの場合には、 テーブルのどの行に対しても物理的記憶領域がが本当にどこかに存在します。
ビューの場合、それ専用で他とは物理的に独立したような、ビューのも のと見分けられるようなデータが格納されることはありません。その代 わりに、システムはシステムカタログ(システムカタログ を参照)でビューの定義を格納し ています。(すなわちビューを実体化するために物理的に格納されてい る基底テーブルにアクセスするルールを格納しています。)ビューの実 装に関するそのほかの方法論についてはSIM98 で言及されています。
SQLではビューの定義にCREATE VIEW コマンドを使用します。文法は以下の通りです。
CREATE VIEW view_name AS select_stmtselect_stmtには Select(選択)で定義されて いる SELECT を記述します。ビューを作成する際にselect_stmtは実行されないという 点に注意してください。ビューはシステムカタログ に格納されるだけで、ビューに対する問い合わせがあると きに実行されるのです。
以下のビュー定義を考えてみましょう。(SUPPLIER と PART データベースで使われているテー ブルを再び使用します。)
CREATE VIEW London_Suppliers AS SELECT S.SNAME, P.PNAME FROM SUPPLIER S, PART P, SELLS SE WHERE S.SNO = SE.SNO AND P.PNO = SE.PNO AND S.CITY = 'London';
これで仮想リレーションである London_Suppliersをあたかも基底テーブルの 一つであるかのように使用することができます。
SELECT * FROM London_Suppliers WHERE PNAME = 'Screw';以下のようなテーブルが返されます。
SNAME | PNAME -------+------- Smith | Screw
この結果を計算するために、データベースシステムは最初に基底テーブ ル SUPPLIER , SELL, PARTに隠れたアクセスを しなければいけません。それはこれらの基底テーブルに対してビュー定 義で与えられる問い合わせを実行することによって行われます。その後、 さらなる選択(ビューに対する問い合わせで指定されている)が行われて、 結果のテーブルが得られます。
テーブルを削除する(テーブル中にあるすべてのタプルを含む)ためには DROP TABLE コマンドを使用します。
DROP TABLE table_name;
SUPPLIER テーブルを削除するには以下のような文を使用します。
DROP TABLE SUPPLIER;
DROP INDEX コマンドはインデックスの削除に使用されます。
DROP INDEX index_name;
最後に、ビューを削除するには DROP VIEW コマンドを使用します。
DROP VIEW view_name;
いったんテーブルが作成されると(Create Tableを参照)INSERT INTOコマンドを使用してタプルを挿入することができます。 構文は以下の通りです。
INSERT INTO table_name (name_of_attr_1 [, name_of_attr_2 [,...]]) VALUES (val_attr_1 [, val_attr_2 [, ...]]);
リレーション SUPPLIER(SUPPLIER と PART データベースより)に最初のタプルを挿入するには以下の文 を使用します。
INSERT INTO SUPPLIER (SNO, SNAME, CITY) VALUES (1, 'Smith', 'London');
リレーション SELLES に最初のタプルを挿入するには以下を使用します。
INSERT INTO SELLS (SNO, PNO) VALUES (1, 1);
あるリレーションで、いくつかのタプルの一つもしくは複数のの属性値 を変更する場合には、 UPDATE コマンドを使用します。構文は以下の通 りです。
UPDATE table_name SET name_of_attr_1 = value_1 [, ... [, name_of_attr_k = value_k]] WHERE condition;
PARTというリレーションで、'Screw' という部品の属性 PRICE の値を 変更するには以下のようにします。
UPDATE PART SET PRICE = 15 WHERE PNAME = 'Screw';
名前が 'Screw' のタプルの属性 PRICE の新しい値は 15 です。
特定のテーブルのタプルを削除するには DELEFE FROM コマンドを使用 します。構文は以下の通りです。
DELETE FROM table_name WHERE condition;
SUPPLIER テーブルの供給者 'Smith' を削除するには以下の文を使用し ます。
DELETE FROM SUPPLIER WHERE SNAME = 'Smith';
あらゆるSQLデータベースシステムでシ ステムカタログがデータベース中に定義されるテーブル、 ビュー、インデックス等を保持するのに使用されています。システムカ タログは通常のリレーションのように問い合わせすることができます。 例えば、ビューの定義に使用されている一つのカタログがあります。こ のカタログはビューの定義に現れる問い合わせを格納しています。ビュー に対する問い合わせが行われるときはいつでも、システムはまず、 ビュー定義の問い合わせをカタログから取り出 し、ユーザ問い合わせを実行する前にビューを実体化します。(Simkovics, 1998に詳細があります。)システムカタロ グに関する更なる情報はDate, 1994を ご覧ください。
この節では、ホスト言語(例えば C)にSQLを埋め込 む方法の概略をのべます。ホスト言語からSQLを使用 したい理由としては主に2つのものがあります。
純粋なSQLでは表現できない問い合わせ(例えば 再起問い合わせ)があります。このような問い合わせを実行するため にSQLよりも表現力豊かなホスト言語が必要なの です。
単純に上位言語でかかれたアプリケーションからデータベースにアク セスしたいのです。(たとえば、グラフィカルユーザインタフェース を使ったチケット予約システムでは、全体は C で記述し、残ってい るチケットの情報は埋め込みSQLを通してデータ ベースにアクセスして蓄えておく。)
ホスト言語で埋め込みSQLを使用しているプログラ ムはホスト言語の文と埋め込み SQL(ESQL) 文か らなります。すべてのESQL文はEXEC SQLというキーワードで始まります。 ESQL文はプリコンパイラ (通常はいろいろな)SQLコマンドを実行するライブ ラリルーチンの呼び出しを挿入する)によってホスト言語の文に置き換え られます。
Select(選択)に現れる一連 の例をみてみると、問い合わせの結果がたいていの場合タプルの集合で あると分かると思います。大部分のホスト言語は集合を操作するように 設計されておらず、SELECT文によって返されるタプルの集合から個々の タプルにアクセスするための何らかのメカニズムが必要となります。こ のメカニズムはcursorを宣言することによって 得ることができます。宣言した後は、FETCH コマンドを使えば、タプル を一つ取り出してカーソルを次のタプルに設定することができます。
埋め込みSQLに関する詳細な議論はDate and Darwen, 1997, Date, 1994, Ullman, 1988などで述 べられています。