今野 英明
2015年7月6日
SELECT * FROM population ; name | popul | house --------+--------+-------- 函館市 | 294264 | 128411 七飯町 | 28424 | 10363 北斗市 | 48056 | 17779 鹿部町 | 4919 | 1646 森町 | 19149 | 7363このテーブルでは,列 name (自治体名) が文字列であるのに対し,列 popul (人口) と列 house (世帯数) は整数です。 文字列や整数のような値の種類をデータ型といいます。 なお,計算機科学では,「値」という言葉は数値以外のもの(文字など)に対しても使われます。
この資料では,SQL に用意されているデータ型の詳細には触れませんが, データ型には文字のための型と数値のための型があることは覚えておいてください。
これまでに使ってきた方法です。 このルールに反すると,次のようなエラーが起きます。
SELECT * FROM population WHERE name = 函館市; ERROR: 列"函館市"は存在しません 行 1: select * from population where name = 函館市; ^(函館市を ' で囲まなかったので列名とみなされた)
SELECT * FROM population WHERE popul > 200000 ; name | popul | house --------+--------+-------- 函館市 | 294264 | 128411
psql には,テーブルの情報を表示する,psql 固有のコマンド
\d
テーブル名
があります。
これを使うとテーブル population における各列のデータ型がわかります。
\d
は SQL 文ではないので,末尾に ; を付けないことに注意してください。db_a=> \d population テーブル "public.population" カラム | 型 | 修飾語 --------+-------------------+-------- name | character varying | popul | integer | house | integer |ここでカラム (column) は列名を,型 (type) はデータ型を意味します。 これより,テーブル population では, 列 name は character varying (可変長文字列) 型であり, 列 popul と列 house は integer (整数) 型であることがわかります。 したがって,テーブル population では, 列 name のデータを SQL で指定する場合には ' (単一引用符) で囲む必要があり, 列 popul と house ではその必要はありません。
SELECT * FROM area_code; name | code --------+------- 函館市 | 01202 七飯町 | 01337 北斗市 | 01236 鹿部町 | 01343 森町 | 01345一見,列 name は文字の型に,列 code は数値の型に見えますが, 実は違います。
db_a=> \d area_code テーブル "public.area_code" カラム | 型 | 修飾語 --------+-------------------+-------- name | character varying | code | character(5) |列 name は character varying (可変長文字列) 型で, 列 code は character(5) (5文字からなる固定長文字列) 型です。 つまり,数字のみが格納された列であっても,その列が数値の型とは限りません。
SQL 文における単一引用符の必要性は,列のデータ型によって決まりますので, テーブル area_code における列 code の値を指定する場合には, ' (単一引用符) で囲む必要があります。
SELECT * FROM area_code WHERE code = '01202'; name | code --------+------- 函館市 | 01202 (1 row) SELECT * FROM area_code WHERE code = 01202; ERROR: 演算子が存在しません: character = integer 行 1: select * from area_code where code = 01202; ^ HINT: 指定名称、指定引数型に合う演算子がありません。明示的な型キャストが必要かもしれません
なお,列 code (地域コード) が整数型にされていない理由としては, 次の点が挙げられます。
列 name (地域名): 可変長文字型 (varchar),
列 code (地域コード): 固定長文字型 (char(5))
SELECT * FROM area_code ; name | code --------+------- 函館市 | 01202 七飯町 | 01337 北斗市 | 01236 鹿部町 | 01343 森町 | 01345 (5 rows)
列 code (地域コード): 固定長文字型 (char(5)),
列 num (地域の病院数): 整数型 (int)
SELECT * FROM n_hospital ; code | num -------+----- 01202 | 284 01337 | 19 01236 | 27 01343 | 3 01345 | 14 (5 rows)
FROM テーブル1,テーブル2,...これにより, FROM に続いて指定したテーブル(テーブル1,テーブル2,...) に含まれる行の, すべての組み合わせが得られます。 これを交差結合(直積1)と呼ぶことがあります。
SELECT * FROM area_code, n_hospital; name | code | code | num --------+-------+-------+----- 函館市 | 01202 | 01202 | 284 函館市 | 01202 | 01337 | 19 函館市 | 01202 | 01236 | 27 函館市 | 01202 | 01343 | 3 函館市 | 01202 | 01345 | 14 七飯町 | 01337 | 01202 | 284 七飯町 | 01337 | 01337 | 19 七飯町 | 01337 | 01236 | 27 七飯町 | 01337 | 01343 | 3 七飯町 | 01337 | 01345 | 14 北斗市 | 01236 | 01202 | 284 北斗市 | 01236 | 01337 | 19 北斗市 | 01236 | 01236 | 27 北斗市 | 01236 | 01343 | 3 北斗市 | 01236 | 01345 | 14 鹿部町 | 01343 | 01202 | 284 鹿部町 | 01343 | 01337 | 19 鹿部町 | 01343 | 01236 | 27 鹿部町 | 01343 | 01343 | 3 鹿部町 | 01343 | 01345 | 14 森町 | 01345 | 01202 | 284 森町 | 01345 | 01337 | 19 森町 | 01345 | 01236 | 27 森町 | 01345 | 01343 | 3 森町 | 01345 | 01345 | 14 (25 rows)
複数のテーブルから列を指定する場合,
テーブル名.列名の形で,テーブルと列を . (ドット) で区切って記述します。
SELECT * FROM area_code, n_hospital WHERE area_code.code = n_hospital.code; name | code | code | num --------+-------+-------+----- 函館市 | 01202 | 01202 | 284 七飯町 | 01337 | 01337 | 19 北斗市 | 01236 | 01236 | 27 鹿部町 | 01343 | 01343 | 3 森町 | 01345 | 01345 | 14 (5 rows)このように,一方の列の値と, もう一方の列の値が等しい行をつなぎ合わせる操作を等結合といいます。
SELECT * FROM area_code JOIN n_hospital ON area_code.code = n_hospital.code;
SELECT * FROM area_code NATURAL JOIN n_hospital;で得られます。
SELECT area_code.code, area_code.name, n_hospital.num FROM area_code, n_hospital WHERE area_code.code = n_hospital.code; code | name | num -------+--------+----- 01202 | 函館市 | 284 01337 | 七飯町 | 19 01236 | 北斗市 | 27 01343 | 鹿部町 | 3 01345 | 森町 | 14 (5 rows)
さらに検索条件を加えることにより,取り出す行を限定できます。
SELECT area_code.code, area_code.name, n_hospital.num FROM area_code, n_hospital WHERE area_code.code = n_hospital.code AND area_code.code = '01202'; code | name | num -------+--------+----- 01202 | 函館市 | 284 (1 row)
さらに表示する列と行を限定してみます。
SELECT area_code.name, n_hospital.num FROM area_code, n_hospital WHERE area_code.code = n_hospital.code AND (area_code.code = '01202' OR area_code.code = '01337'); name | num --------+----- 函館市 | 284 七飯町 | 19 (2 rows)この SQL 文においては,次の点に注意してください。
SELECT area_code.name AS area_name, n_hospital.num AS hospital_num FROM area_code, n_hospital WHERE area_code.code = n_hospital.code AND area_code.code = '01202'; area_name | hospital_num -----------+-------------- 函館市 | 284 (1 row)
相関名は FROM に続くテーブル名の後で AS に続き定義します3。 定義した相関名は,SELECT に続く列名や WHERE 検索条件で使用できます。
次の例ではテーブル area_code に相関名 a を, テーブル n_hospital には相 関名 h を与えています。
SELECT a.name, h.num FROM area_code AS a, n_hospital AS h WHERE a.code = h.code AND a.code = '01202'; name | num --------+----- 函館市 | 284 (1 row)
name | popul --------+-------- 函館市 | 294264 (1 row)
name | code | name | popul | house --------+-------+--------+--------+-------- 函館市 | 01202 | 函館市 | 294264 | 128411 七飯町 | 01337 | 七飯町 | 28424 | 10363 北斗市 | 01236 | 北斗市 | 48056 | 17779 鹿部町 | 01343 | 鹿部町 | 4919 | 1646 森町 | 01345 | 森町 | 19149 | 7363 (5 rows)
name | location --------------+---------- 谷地頭温泉 | 函館市 湯の川温泉街 | 函館市 東大沼温泉郷 | 七飯町 川汲温泉郷 | 函館市 戸井温泉 | 函館市 せせらぎ温泉 | 北斗市 鹿部温泉郷 | 鹿部町 濁川温泉郷 | 森町 仁山温泉 | 七飯町 (9 rows)
name | code | name | popul | house | code | num --------+-------+--------+--------+--------+-------+----- 函館市 | 01202 | 函館市 | 294264 | 128411 | 01202 | 284 七飯町 | 01337 | 七飯町 | 28424 | 10363 | 01337 | 19 北斗市 | 01236 | 北斗市 | 48056 | 17779 | 01236 | 27 鹿部町 | 01343 | 鹿部町 | 4919 | 1646 | 01343 | 3 森町 | 01345 | 森町 | 19149 | 7363 | 01345 | 14 (5 rows)
name | code | popul | house | hospital --------+-------+--------+--------+---------- 函館市 | 01202 | 294264 | 128411 | 284 七飯町 | 01337 | 28424 | 10363 | 19 北斗市 | 01236 | 48056 | 17779 | 27 鹿部町 | 01343 | 4919 | 1646 | 3 森町 | 01345 | 19149 | 7363 | 14 (5 rows)