PREPARATION
受験対策

オススメ!OSS-DB情報

第13回 表別名と列別名

ALIAS(エイリアス)という言葉を聞いたことはありますか。日本語でいうと「別名」です。
Linuxのシェルである bash には alias の機能があり、例えば、
alias ll='ls -l'
とすると、ll は 'ls -l' の別名となり、コマンドラインから ll を入力すると内部的に、ls -l が実行されるようになることをご存知の人も多いでしょう。
データベースのSQLにも、ALIAS(別名)の機能があります。

例えば、以下のように定義された、受験者表(candidate)と受験データ表(examination)からデータを検索(SELECT)する場合を考えます。

CREATE TABLE candidate (
 cid INTEGER PRIMARY KEY,
 firstname VARCHAR(20),
 lastname VARCHAR(20)
);

CREATE TABLE examination (
 eid INTEGER PRIMARY KEY,
 cid INTEGER REFERENCES candidate(cid),
 examname VARCHAR(20),
 examdate DATE,
 score INTEGER
);

これらを結合する SELECT 文は、次のようになります。

SELECT column_list...
FROM candidate
JOIN examination ON candidate.cid = examination.cid
WHERE condition...

ここで、SELECT の column_list、ON 句、WHERE 句の condition の部分には candidate 表や examination 表の多数の列の名前が table_name.column_name の形式で書かれます。
どちらか一方の表にしか存在しない列であれば "table_name." を省略することもできますが、上の例の cid のように両方に存在する列にはテーブル名の修飾が必須です。
また、特に多数の表を結合する場合などは、わかりやすさや保守のしやすさの観点からも、すべての列についてテーブル名を付加した状態で記述することが望ましいことがあります。
しかし、それぞれの列にいちいち長い表名をつけて参照するのは煩わしく、かえって読みづらくなるかもしれません。
そんなときに使われるのが表の別名(以下、表別名と呼びます)です。
表別名は、FROM 句、および JOIN 句に指定したテーブル名の直後に、空白を入れて指定します。上の例では

SELECT column_list...
FROM candidate c
JOIN examination e ON c.cid = e.cid
WHERE condition...

のようになります。ここでは candidate の表別名を c、examination の表別名を e にしました。ON 句に指定する結合条件が短くなったのがわかるでしょう。
単に読みやすくなるだけではありません。例えば、candidate、examination と同じ構造を持つ別の表、new_candidate、new_examination を作ったとして、これらから同じ検索を実行するとき、FROM 句と JOIN 句の表名を付け替えれば、 ON や WHERE など、他の場所は一切、変更せずに同じ SQL 文を流用することができます。

同じテーブルを2回以上結合する場合には、表別名が必須になります。例えば、

CREATE TABLE emp (
 emp_id INTEGER,
 emp_name VARCHAR(50),
 manager_id INTEGER
);

で定義されたテーブルから、上司と部下の関係の一覧を表示するのに、

SELECT m.emp_id, m.emp_name, e.emp_id, e.emp_name
FROM emp m
JOIN emp e ON e.manager_id = m.emp_id;

という SELECT 文を使うことができますが、この場合、表別名を使わないと、それぞれの列が FROM で指定した emp と JOIN で指定した emp のどちらかわからなくなってしまいますので表別名が必須です。

また、SELECT 文の FROM 句には表名だけでなく、別の SELECT 文を書くこともできますが、この場合も表別名が必須となります。例えば

SELECT column_list1...
FROM (SELECT column_list2... FROM ...) alias_name
WHERE ...

といった感じで FROM 句に書いた SELECT 文の結果をビュー(VIEW)として扱う SELECT 文を書くことができるのですが、このとき、FROM 句の SELECT 文の後に表別名をつけないとエラーになります(注1)。

表別名を使うのは SELECT 文だけではありません。UPDATE 文や DELETE 文でも、他の表を参照する条件を記述したいには表別名を使うことができます。例えば、次のような使い方があります。

DELETE FROM candidate c
WHERE NOT EXISTS (SELECT * FROM examination e WHERE c.cid = e.cid);

上の DELETE 文は、examination 表に該当するデータが1件もない受験者のデータを candidate 表から削除するものです。

SQL で使う ALIAS には、表別名の他に列別名があります。例えば、psql で次の SELECT 文を実行すると、どうなるでしょうか。

SELECT cid, firstname || ' ' || lastname
FROM candidate;

表形式の結果が返されますが、そのヘッダは

cid|?column?

-----+----------

のようになり、元の SELECT 文を見ないと何を SELECT したのかわかりません。
次のように列別名を指定すれば、表示が改善されます。

SELECT cid, firstname || ' ' || lastname fullname FROM candidate;

cid|fullname

-----+----------

列別名は、単にヘッダの表示を改善するだけでなく、GROUP BY 句や ORDER BY 句の列名として指定することもできます。例えば

SELECT cid, firstname || ' ' || lastname fullname
FROM candidate
ORDER BY fullname;

ただし、WHERE 句の条件などに列別名を使うことはできないので注意してください。

SELECT cid, firstname || ' ' || lastname fullname
FROM candidate
WHERE fullname LIKE 'A%'; ← エラー!

さて、表別名と列別名の利用にあたり、注意事項がいくつかあります。
まず、別名の指定方法ですが、上の例のように、表名や列名のすぐ後に空白を置いて別名を指定する方法の他に、表名(列名)と別名の間に AS キーワードを置いて、その後の文字列が別名であることを明示する方法があります。つまり、

SELECT firstname AS name
FROM candidate AS c
JOIN ...

のような書き方もあります。
表別名に関しては、ほとんどのデータベースで AS があってもなくても動作しますが、Oracleでは AS を指定するとエラーになりますので、互換性の観点からは、なるべく AS を指定せずに SQL を書くようにした方が良いでしょう。
列別名については、少し事情が複雑なので注意が必要です。PostgreSQLのバージョン8.3までは、列別名の AS が必須でした(8.4から省略可能になりました)。
一方で、Oracleでは、ASを指定するとエラーになります。他の多くのデータベースでは AS があってもなくても動作するようです。

次に、SQL 文中の列名の指定方法ですが、table_name.column_name のように記述する際、表別名を指定したものについては、table_name として表別名を書かなければならない、ということにも注意が必要です。例えば、

(A) SELECT c.first_name FROM candidate c WHERE ...
(B) SELECT candidate.first_name FROM candidate WHERE ...
(C) SELECT candidate.first_name FROM candidate c WHERE ...

のうち、(A)と(B)は実行できますが、(C)はエラーになります。

注意事項の最後ですが、SELECT 文の表別名はどのデータベースでも利用できますが、UPDATE や DELETE に関しては、副問い合わせがあっても、表別名を使えないというデータベースもあるようです(注3)。

(注1) Oracleなど、表別名をつけなくてもエラーにならないデータベースもあります。
(注2) Oracleでは表別名の前に AS を指定するとエラーになります。
(注3) 例えば、MySQLでは DELETE 文で表別名を指定することができません。

 

解説:松田神一

LPI-Japan
Platinum Sponsors

関連資格