2012年8月28日火曜日

6.2 テーブルの操作


ここでは、テーブルや列、レコードの追加や削除、更新といった作
業について取り上げます。

6.2.1 列の追加

テーブルを作成後に、列を新たに追加することができます。
ALTER TABLE テーブル名ADD 新規列名データ型[FIRST];

この書式を使うと、テーブルの右端に列を追加することができます。次の例
では、branchテーブルにtel欄を追加しています。

mysql> ALTER TABLE branch ADD tel VARCHAR(16);
mysql> DESC branch;
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| id | smallint(6) | NO | PRI | | |
| branchname | varchar(20) | YES | | NULL | |
| tel | varchar(16) | YES | | NULL | |
+------------+-------------+------+-----+---------+-------+

なお、次のように「FIRST」を指定すると、テーブルの右端ではなく左端に
列が追加されます。


mysql> ALTER TABLE branch ADD tel VARCHAR(16) FIRST;

6.2.2 列の削除

列を削除するには、以下の書式を使います。
ALTER TABLE テーブル名DROP 列名;

次の例では、branchテーブルからtel列を削除します。削除の確認メッセージなどは表示されませんので注意して操作してください。
mysql> ALTER TABLE branch DROP tel;

6.2.3 レコードの更新

既存のレコードを更新するには、SQLコマンドのUPDATEを使います。
UPDATE テーブル名SET 列名= 値[WHERE 条件]

次の例では、name列の値が「Sato」であるレコードのage列の値を「24」
に変更します。

mysql> UPDATE staff SET age='24' WHERE name =
'Sato';
mysql> SELECT * FROM staff WHERE name =
'Sato';
+----+------+------+------+
| id | name | age | bid |
+----+------+------+------+
| 1 | Sato | 24 | 1 |
+----+------+------+------+

なお、WHERE句を指定しないと、すべてのレコードの列に同じ値が格納さ
れてしまいますので注意してください。

mysql> UPDATE staff SET age = '20';
mysql> SELECT * FROM staff;
+----+-----------+------+------+
| id | name | age | bid |
+----+-----------+------+------+
| 1 | Sato | 20 | 1 |
| 2 | Suzuki | 20 | 2 |
| 3 | Takahashi | 20 | 5 |
| 4 | Tanaka | 20 | 3 |
| 5 | Watanabe | 20 | 2 |
+----+-----------+------+------+









2012年8月23日木曜日

6.1 テーブルの結合(2)

6.1.3 外部結合


内部結合では、結合に使う列のデータが両方のテーブルにあるレコードのみ
出力されますが、外部結合では、どちらかのテーブルにしかデータがないレ
コードも出力されます。外部結合には、左外部結合と右外部結合があります。

SELECT 列名1 FROM テーブル名1 LEFT|RIGHT [OUTER]
JOIN テーブル名2 ON テーブル名1.列名1 = テーブル名2.列名2;

先ほどのテーブルとは少し異なるデータを使います。staffテーブルには、
bidが5のメンバーがいるとします。一方、branchテーブルには、idは4まで
しかありません。

mysql> SELECT * FROM staff;
+----+-----------+------+------+
| id | name | age | bid |
+----+-----------+------+------+
| 1 | Sato | 23 | 1 |
| 2 | Suzuki | 24 | 2 |
| 3 | Takahashi | 28 | 5 |
| 4 | Tanaka | 26 | 3 |
| 5 | Watanabe | 30 | 2 |
+----+-----------+------+------+
mysql> SELECT * FROM branch;
+----+------------+
| id | branchname |
+----+------------+
| 1 | Tokyo |
| 2 | Yokohama |
| 3 | Osaka |
| 4 | Nagoya |
+----+------------+

まず、左外部結合から見ていきましょう。左外部結合では、最初に(左側で)
指定した方のテーブルにあるレコードすべてを出力します。右側のテーブル
のレコードは、場合によってはNULLとなります。次の例では、左側のテー
ブルにあるbid = 5に対応するデータが右側のテーブルにないので、その部
分はNULLとなっています。

mysql> SELECT * FROM staff LEFT JOIN branch ON staff.bid =
branch.id;
+----+-----------+------+------+------+------------+
| id | name | age | bid | id | branchname |
+----+-----------+------+------+------+------------+
| 1 | Sato | 23 | 1 | 1 | Tokyo |
| 2 | Suzuki | 24 | 2 | 2 | Yokohama |
| 3 | Takahashi | 28 | 5 | NULL | NULL |
| 4 | Tanaka | 26 | 3 | 3 | Osaka |
| 5 | Watanabe | 30 | 2 | 2 | Yokohama |

右外部結合はその逆です。後に(右側で)指定した方のテーブルにあるレコ
ードをすべて出力します。

mysql> SELECT * FROM staff RIGHT JOIN branch ON staff.bid =
branch.id;
+------+----------+------+------+----+------------+
| id | name | age | bid | id | branchname |
+------+----------+------+------+----+------------+
| 1 | Sato | 23 | 1 | 1 | Tokyo |
| 2 | Suzuki | 24 | 2 | 2 | Yokohama |
| 5 | Watanabe | 30 | 2 | 2 | Yokohama |
| 4 | Tanaka | 26 | 3 | 3 | Osaka |
| NULL | NULL | NULL | NULL | 4 | Nagoya |
+------+----------+------+------+----+------------+

6.1.4 副問い合わせ


ある条件で検索したデータを使ってさらに検索を行いたい場合があります。
そのような、SELECT文の中で使われるSELECT文を副問い合わせ(サブクエリー)といいます。
SELECT 列名FROM テーブル名WHERE 列名IN (SELECT ~);
次の例では、age列が最大のレコードのname列を表示しています。

mysql> SELECT name FROM staff WHERE age IN
(SELECT MAX(age) FROM staff);
+----------+
| name |
+----------+
| Watanabe |
+----------+
処理を分析してみましょう。

mysql> SELECT MAX(age) FROM staff;
+----------+
| MAX(age) |
+----------+
| 30 |
+----------+
mysql> SELECT * FROM staff WHERE age = 30;
+----+----------+------+------+
| id | name | age | bid |
+----+----------+------+------+
| 5 | Watanabe | 30 | 2 |
+----+----------+------+------+

6.1.5 自己結合

同一のテーブルに別名を付けて結合することを自己結合といいます。

SELECT 列名FROM テーブル名AS 別名1 JOIN テーブル名AS 別名2;
自己結合の例を見てみましょう。

mysql> SELECT * FROM staff AS a JOIN staff AS b;
+----+-----------+------+------+----+-----------+------+------+
| id | name | age | bid | id | name | age | bid |
+----+-----------+------+------+----+-----------+------+------+
| 1 | Sato | 23 | 1 | 1 | Sato | 23 | 1 |
| 2 | Suzuki | 24 | 2 | 1 | Sato | 23 | 1 |
| 3 | Takahashi | 28 | 5 | 1 | Sato | 23 | 1 |
| 4 | Tanaka | 26 | 3 | 1 | Sato | 23 | 1 |
| 5 | Watanabe | 30 | 2 | 1 | Sato | 23 | 1 |
| 1 | Sato | 23 | 1 | 2 | Suzuki | 24 | 2 |
| 2 | Suzuki | 24 | 2 | 2 | Suzuki | 24 | 2 |
| 3 | Takahashi | 28 | 5 | 2 | Suzuki | 24 | 2 |
| 4 | Tanaka | 26 | 3 | 2 | Suzuki | 24 | 2 |
| 5 | Watanabe | 30 | 2 | 2 | Suzuki | 24 | 2 |
| 1 | Sato | 23 | 1 | 3 | Takahashi | 28 | 5 |
| 2 | Suzuki | 24 | 2 | 3 | Takahashi | 28 | 5 |
| 3 | Takahashi | 28 | 5 | 3 | Takahashi | 28 | 5 |
| 4 | Tanaka | 26 | 3 | 3 | Takahashi | 28 | 5 |
| 5 | Watanabe | 30 | 2 | 3 | Takahashi | 28 | 5 |
| 1 | Sato | 23 | 1 | 4 | Tanaka | 26 | 3 |
| 2 | Suzuki | 24 | 2 | 4 | Tanaka | 26 | 3 |
| 3 | Takahashi | 28 | 5 | 4 | Tanaka | 26 | 3 |
| 4 | Tanaka | 26 | 3 | 4 | Tanaka | 26 | 3 |
| 5 | Watanabe | 30 | 2 | 4 | Tanaka | 26 | 3 |
| 1 | Sato | 23 | 1 | 5 | Watanabe | 30 | 2 |
| 2 | Suzuki | 24 | 2 | 5 | Watanabe | 30 | 2 |
| 3 | Takahashi | 28 | 5 | 5 | Watanabe | 30 | 2 |
| 4 | Tanaka | 26 | 3 | 5 | Watanabe | 30 | 2 |
| 5 | Watanabe | 30 | 2 | 5 | Watanabe | 30 | 2 |
+----+-----------+------+------+----+-----------+------+------+












2012年8月22日水曜日

6.1 テーブルの結合


複数のテーブルを結合して、1つの表として扱うことができます。
結合にはいくつかの種類があります。

6.1.1 UNIONによる結合


UNIONを使うと、複数のSELECT文を繋いで、複数テーブルのレコードを
表示することができます。

SELECT 列名1 FROM テーブル名1 UNION SELECT 列名2 FROM テーブル名2;
たとえば、次のような2つのテーブルがあるとします。

mysql> SELECT * FROM staff;
+----+-----------+------+------+
| id | name | age | bid |
+----+-----------+------+------+
| 1 | Sato | 23 | 1 |
| 2 | Suzuki | 24 | 2 |
| 3 | Takahashi | 28 | 1 |
| 4 | Tanaka | 26 | 3 |
| 5 | Watanabe | 30 | 2 |
+----+-----------+------+------+
mysql> SELECT * FROM staff2;
+----+----------+------+------+
| id | name | age | bid |
+----+----------+------+------+
| 1 | Ito | 27 | 2 |
| 2 | Yamamoto | 31 | 1 |
| 3 | Nakamura | 24 | 4 |
+----+----------+------+------+
2つのテーブルのレコードを全部まとめて出力できます。

mysql> SELECT * FROM staff UNION SELECT * FROM staff2;
+----+-----------+------+------+
| id | name | age | bid |
+----+-----------+------+------+
| 1 | Sato | 23 | 1 |
| 2 | Suzuki | 24 | 2 |
| 3 | Takahashi | 28 | 1 |
| 4 | Tanaka | 26 | 3 |
| 5 | Watanabe | 30 | 2 |
| 1 | Ito | 27 | 2 |
| 2 | Yamamoto | 31 | 1 |
| 3 | Nakamura | 24 | 4 |
+----+-----------+------+------+

なお、それぞれのテーブルでキャラクタセットが異なると、UNIONを使う
ことができませんので注意してください。

6.1.2 内部結合


UNIONによる結合は、2つのテーブルを縦に結合しましたが、横に結合す
るには内部結合や外部結合を使います。まず、以下のような2つのテーブル
(staffとbranch)があるとします。

mysql> SELECT * FROM staff;
+----+-----------+------+------+
| id | name | age | bid |
+----+-----------+------+------+
| 1 | Sato | 23 | 1 |
| 2 | Suzuki | 24 | 2 |
| 3 | Takahashi | 28 | 1 |
| 4 | Tanaka | 26 | 3 |
| 5 | Watanabe | 30 | 2 |
+----+-----------+------+------+
mysql> SELECT * FROM branch;
+----+------------+
| id | branchname |
+----+------------+
| 1 | Tokyo |
| 2 | Yokohama |
| 3 | Osaka |
| 4 | Nagoya |
+----+------------+

staffテーブルのbid列とbranchテーブルのid列を関連づけて表示することを
内部結合と呼んでいます。

SELECT 列名1 FROM テーブル名1 [INNER] JOIN テーブル名2
ON テーブル名1.列名1 = テーブル名2.列名2;

次の例を見てください。「staff.bid = branch.id」により、それぞれの列が
関連づけられています。

mysql> SELECT * FROM staff JOIN branch ON staff.bid = branch.id;
+----+-----------+------+------+----+------------+
| id | name | age | bid | id | branchname |
+----+-----------+------+------+----+------------+
| 1 | Sato | 23 | 1 | 1 | Tokyo |
| 2 | Suzuki | 24 | 2 | 2 | Yokohama |
| 3 | Takahashi | 28 | 1 | 1 | Tokyo |
| 4 | Tanaka | 26 | 3 | 3 | Osaka |
| 5 | Watanabe | 30 | 2 | 2 | Yokohama |
+----+-----------+------+------+----+------------+
mysql> SELECT name,age,branchname FROM staff JOIN branch ON
staff.bid = branch.id;
+-----------+------+------------+
| name | age | branchname |
+-----------+------+------------+
| Sato | 23 | Tokyo |
| Takahashi | 28 | Tokyo |
| Suzuki | 24 | Yokohama |
| Watanabe | 30 | Yokohama |
| Tanaka | 26 | Osaka |
+-----------+------+------------+

なお、branchテーブルにある4つめのレコード(Nagoya)は、staffテーブ
ルにはないので表示されません。

2012年8月20日月曜日

5.2 データの検索(3)


5.2.5 出力レコード数の制限

表示するレコード数は、LIMITで指定できます。
SELECT 列名FROM テーブル名LIMIT 出力レコード数;
次の例では、出力レコード数を3に指定しています。

mysql> SELECT * FROM staff LIMIT 3;
+----+-----------+------+------+
| id | name | age | bid |
+----+-----------+------+------+
| 1 | Sato | 23 | 1 |
| 2 | Suzuki | 24 | 2 |
| 3 | Takahashi | 28 | 1 |
+----+-----------+------+------+

 5.2.6 ソート


ORDER BY句を使うと、任意の項目でソートして出力することができます。
デフォルトは昇順です。
SELECT 列名FROM テーブル名ORDER BY 順序指定;
次の例では、age列を昇順にソートして出力します。

mysql> SELECT * FROM staff ORDER BY age;
+----+-----------+------+------+
| id | name | age | bid |
+----+-----------+------+------+
| 1 | Sato | 23 | 1 |
| 2 | Suzuki | 24 | 2 |
| 4 | Tanaka | 26 | 3 |
| 3 | Takahashi | 28 | 1 |
| 5 | Watanabe | 30 | 2 |
+----+-----------+------+------+
DESCを指定すると、昇順ではなく降順でソートされます。

mysql> SELECT * FROM staff ORDER BY age DESC;
+----+-----------+------+------+
| id | name | age | bid |
+----+-----------+------+------+
| 5 | Watanabe | 30 | 2 |
| 3 | Takahashi | 28 | 1 |
| 4 | Tanaka | 26 | 3 |
| 2 | Suzuki | 24 | 2 |
| 1 | Sato | 23 | 1 |
+----+-----------+------+------+


5.2.7 ファイルへの出力

SELECT文の実行結果をファイルに出力することもできます。
SELECT 列名FROM テーブル名INTO OUTFILE 出力ファイル名;
次の例では、ファイルtest.txtに検索結果が出力されます。

mysql> SELECT * FROM staff INTO OUTFILE 'test.txt';

デフォルトでは、データベースファイルのあるディレクトリ(/var/lib/mysql以下など)に出力されます。

# cat /var/lib/mysql/testdb/test.txt
1 Sato 23 1
2 Suzuki 24 2
3 Takahashi 28 5
4 Tanaka 26 3
5 Watanabe 30 2

2012年8月17日金曜日

5.2 データの検索(2)

5.2.3 グループ化


列のデータが同じレコードをまとめることをグループ化といいます。グループ化はGROUP BY句を使います。
SELECT 列名FROM テーブル名GROUP BY グループ化する列名;
次の例では、bid列が同じレコードをグループ化して表示しています。

mysql> SELECT * FROM staff;
+----+-----------+------+------+
| id | name | age | bid |
+----+-----------+------+------+
| 1 | Sato | 23 | 1 |
| 2 | Suzuki | 24 | 2 |
| 3 | Takahashi | 28 | 1 |
| 4 | Tanaka | 26 | 3 |
| 5 | Watanabe | 30 | 2 |
+----+-----------+------+------+
mysql> SELECT * FROM staff GROUP BY bid;
+----+--------+------+------+
| id | name | age | bid |
+----+--------+------+------+
| 1 | Sato | 23 | 1 |
| 2 | Suzuki | 24 | 2 |
| 4 | Tanaka | 26 | 3 |
+----+--------+------+------+

この例では、bid列が共通しているレコードの中から1レコードだけが抽出
されています。グループ化は、次に述べる集合関数を使って、合計や平均
を計算する場合に使います。

5.2.4 集合関数


集合関数を使うと、抽出した結果を集計したり、検索条件にマッチしたレコ
ードの中から平均値や最大値を計算したりすることができます。集合関数に
は、表のようなものがあります。




主な集合関数

AVG(列名) 平均値を計算する
COUNT(列名) レコード数をカウントする
COUNT(DISTINCT 列名) 重複なしでレコード数をカウントする
MAX(列名) 最大値を調べる
MIN(列名) 最小値を調べる
SUM(列名) 合計を計算する

例を見てみましょう。次のようなテーブルを例に取ります。

mysql> SELECT * FROM members;
+-----------+----------+------+
| name | address | age |
+-----------+----------+------+
| Sato | Tokyo | 23 |
| Suzuki | Tokyo | 24 |
| Takahashi | Kanagawa | 28 |
| Tanaka | Kanagawa | 26 |
| Watanabe | Tokyo | 30 |
+-----------+----------+------+

addressごとにage列の合計を表示するには、SUM()関数を使います。

mysql> SELECT address,SUM(age) FROM members
GROUP BY address;
+----------+----------+
| address | SUM(age) |
+----------+----------+
| Kanagawa | 54 |
| Tokyo | 77 |
+----------+----------+

今度は、AVG()関数を使って平均を計算してみます。

mysql> SELECT address,AVG(age) FROM members
GROUP BY address;
+----------+----------+
| address | AVG(age) |
+----------+----------+
| Kanagawa | 27.0000 |
| Tokyo | 25.6667 |
+----------+----------+

COUNT()関数を使うとレコード数をカウントできます。

mysql> SELECT address,COUNT(name) FROM members
GROUP BY address;
+----------+-------------+
| address | COUNT(name) |
+----------+-------------+
| Kanagawa | 2 |
| Tokyo | 3 |
+----------+-------------+





2012年8月16日木曜日

5.2 データの検索

データの検索もSQL文で行います。

5.2.1 SELECT文の基本


データベース内のレコードを検索するには、SQLコマンドのSELECTを使い
ます。基本的な書式は次のとおりです。
SELECT 列名FROM テーブル名;
次の例では、staffテーブルのname列とage列を出力します。

mysql> SELECT name,age FROM staff;
+-----------+------+
| name | age |
+-----------+------+
| Sato | 23 |
| Suzuki | 24 |
| Takahashi | 28 |
| Tanaka | 26 |
| Watanabe | 30 |
+-----------+------+
列名に「*」を指定すると、すべての列が出力されます。

mysql> SELECT * FROM staff;
+----+-----------+------+------+
| id | name | age | bid |
+----+-----------+------+------+
| 1 | Sato | 23 | 1 |
| 2 | Suzuki | 24 | 2 |
| 3 | Takahashi | 28 | 1 |
| 4 | Tanaka | 26 | 3 |
| 5 | Watanabe | 30 | 2 |
+----+-----------+------+------+
列名を表示するときに、ASを使って別名を付けることもできます。

mysql> SELECT name as '名前' ,age as '年齢' FROM staff;
+-----------+--------+
| 名前| 年齢|
+-----------+--------+
| Sato | 23 |
| Suzuki | 24 |
| Takahashi | 28 |
| Tanaka | 26 |
| Watanabe | 30 |
+-----------+--------+


5.2.2 検索条件の指定

検索条件を指定するには、SELECTに続けてWHERE句を使います。
SELECT 列名FROM テーブル名WHERE 検索条件;
次の例では、age列が25未満のレコードを出力します。

mysql> SELECT * FROM staff WHERE age <= 25;
+----+--------+------+------+
| id | name | age | bid |
+----+--------+------+------+
| 1 | Sato | 23 | 1 |
| 2 | Suzuki | 24 | 2 |
+----+--------+------+------+
条件には、以下の表のような記号を利用することができます。


条件に指定できる記号
=   等しい
!=  等しくない
IN  いずれかが含まれる
ある文字列を含むレコードを検索したい場合は、LIKEで条件を指定します。
SELECT 列名FROM テーブル名WHERE 列名LIKE 条件;
次の例では、name列が「T」で始まるレコードを出力します。

mysql> SELECT * FROM staff WHERE name LIKE 'T%';
+----+-----------+------+------+
| id | name | age | bid |
+----+-----------+------+------+
| 3 | Takahashi | 28 | 1 |
| 4 | Tanaka | 26 | 3 |
+----+-----------+------+------+


「%」は任意の文字列を表すワイルドカード文字です。「_」は任意の1文字
を表します。SQLでは「*」や「?」ではありませんので注意してください。
なお、「~以外」で検索したいときは、LIKEの代わりに「NOT LIKE」を使います。

mysql> SELECT * FROM staff WHERE name NOT LIKE 'T%';
+----+----------+------+------+
| id | name | age | bid |
+----+----------+------+------+
| 1 | Sato | 23 | 1 |
| 2 | Suzuki | 24 | 2 |
| 5 | Watanabe | 30 | 2 |
+----+----------+------+------+







2012年8月15日水曜日

5.1 テーブルの作成と更新(2)


5.1.2 主キー

主キーを設定するには、CREATE TABLEコマンドを実行する際、データ型
の直後に「PRIMARY KEY」と指定します。次の例では、id列を主キーと
して設定しています。

mysql> CREATE TABLE staff (id SMALLINT PRIMARY
KEY, name VARCHAR(20), age TINYINT, bid SMALLINT);
どの列に主キーが設定されているかは、以下のようにして確認できます。

mysql> DESC staff;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | smallint(6) | NO | PRI | | |
| name | varchar(20) | YES | | NULL | |
| age | tinyint(4) | YES | | NULL | |
| bid | smallint(6) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+

key欄に「PRI」とあるフィールドが主キーです。

5.1.3 NOT NULL


レコードを識別するためのキーとして使いたい列にデータが入っていなけ
れば、困ったことになります。データの入力を必須とする列を指定するには、
NOT NULLを指定します。次の例では、id列への入力を必須としています。


mysql> CREATE TABLE staff (id SMALLINT NOT
NULL, name VARCHAR(20), age TINYINT, bid
SMALLINT);
DESCコマンドを使ってテーブルの情報を調べてみます。

mysql> DESC staff;+-------+-------------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+-------+-------------+------+-----+---------+-------+| id | smallint(6) | NO | | | || name | varchar(20) | YES | | NULL | || age | tinyint(4) | YES | | NULL | || bid | smallint(6) | YES | | NULL | |+-------+-------------+------+-----+---------+-------+



id列のNull欄が「NO」になっているのが確認できます。「YES」となってい
る列は、値が格納されていなくてもかまわない、ということです。

5.1.4 レコードの追加


テーブルにレコードを追加するには、SQLコマンドのINSERTを使います。

INSERT INTO テーブル名[(列名1[, 列名2, ...])] VALUES
(値1[, 値2, ...]);
次の例では、staffテーブルにレコードを追加しています。

mysql> INSERT INTO staff VALUES ('1', 'Sato', '23', '1');
以下のように、複数のレコードをまとめて追加することもできます。

mysql> INSERT INTO staff VALUES ('2', 'Suzuki', '24', '2'), ('3', 'Takahashi', '28', '1');



もちろん、見やすいように、複数行に分けてもかまいません。

mysql> INSERT INTO staff VALUES
> ('2', 'Suzuki', '24', '2'),
> ('3', 'Takahashi', '28', '1');
次のようにすると、指定した列にのみ値を追加することができます。



mysql> INSERT INTO staff (id, name) VALUES
('9', 'Kobayashi');
mysql> SELECT * FROM staff;
+----+-----------+------+------+
| id | name | age | bid |
+----+-----------+------+------+
| 1 | Sato | 23 | 1 |
| 2 | Suzuki | 24 | 2 |
| 3 | Takahashi | 28 | 5 |
| 4 | Tanaka | 26 | 3 |
| 5 | Watanabe | 30 | 2 |
| 9 | Kobayashi | NULL | NULL |
+----+-----------+------+------+

値を指定しなかった列はNULLとなります。