Lesson 10

SELECT以外の文

Lesson 10 Chapter 1
本レッスンについて

本レッスンでは、SELECT 文以外の文のうち特に重要な文について学んでいきます。
SQL で使用できる「文(コマンド)」は、以下に説明するように、おおよそ 10 数種類程度となります。

SQL で使用できる文について

ここで SQL で使用できる文(コマンド)の全体像を俯瞰しておきましょう。
SQL で使用できる文には、大きな分類として「DDL(データ定義言語)」と「DML(データ操作言語)」の 2 種類があります。

DDL(データ定義言語:Data Definition Language)とは、テーブルの作成(CREATE)・削除(DROP)やアクセス権限の設定など、データベースのデータ構造を定義する言語となります。

DML(データ操作言語:Data Manipulation Language)とは、既存のテーブルへのデータの追加(INSERT)・変更(UPDATE)・削除(DELETE)・取得(SELECT)など、データベースのデータを操作する言語となります。

SQL で使用できる主な文は下表のとおりです。

分類 コマンド 説明
DDL(データ定義言語) CREATE テーブル・ビューなどを作成する
ALTER テーブル・ビューなどを変更する
DROP テーブル・ビューなどを削除する
TRUNCATE テーブルを再作成する
GRANT アクセス権限を与える
REVOKE アクセス権限を取り消す
DML(データ操作言語) SELECT テーブルからレコードを取得する
INSERT テーブルにレコードを追加する
UPDATE テーブルのレコードを変更する
DELETE テーブルのレコードを削除する

本レッスンでは、上記の文のうち、プログラム上で多く使用される DML(データ操作言語)を中心として、INSERT 文、UPDATE 文、DELETE 文、TRUNCATE 文について取り上げていきます。

テーブルの準備

本レッスンで使用するテーブルを準備します。
今回も、テーブルを 2 つ作成します。練習も兼ねて、手順どおりに作成を進めてください。

データベースの選択

まず、test データベースを選択します。

PowerShell
mysql> use test;

不要なテーブルを削除する

次に、Lesson 6 で作成した members テーブルを削除します。
以下の SQL を実行してください(IF EXISTS を付けているので、既にテーブルが存在しなければ空振りとなります)。

PowerShell
mysql> DROP TABLE IF EXISTS members;

テーブルが削除できているか確認してみましょう。
以下の SHOW TABLES コマンドで、テーブルの一覧を表示します。

PowerShell
mysql> SHOW TABLES;
+----------------+
| Tables_in_test |
+----------------+
| cards          |
| employees      |
| lists          |
| operators      |
| prefectures    |
| projects       |
| sample         |
| users          |
+----------------+
8 rows in set (0.00 sec)

members テーブルが削除できたことが確認できました。

members テーブルの作成

それでは、次のように本レッスン用の members テーブルを作成しましょう。
なお、このテーブルには、初期データは入れません。

PowerShell
mysql> CREATE TABLE members (
  id int PRIMARY KEY AUTO_INCREMENT,
  name varchar(20),
  age tinyint,
  prefecture varchar(20),
  attendance boolean DEFAULT true
);

作成したテーブルの内容は SHOW CREATE TABLE 文で確認できます。
SHOW CREATE TABLE members\G とコマンドを打って、確認してみましょう。

PowerShell
mysql> SHOW CREATE TABLE members\G
*************************** 1. row ***************************
        Table: members
Create Table: CREATE TABLE `members` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  `age` tinyint(4) DEFAULT NULL,
  `prefecture` varchar(20) DEFAULT NULL,
  `attendance` tinyint(1) DEFAULT '1',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
1 row in set (0.00 sec)

AUTO_INCREMENT 属性と DEFAULT 制約

テーブルの作成において、AUTO_INCREMENT と DEFAULT という語句が出てきていますので、簡単に補足します。

① AUTO_INCREMENT 属性

AUTO_INCREMENT 属性を使用すると、自動的に連番が生成されます。必ず一意の値(ユニーク値)となり他と重複しません。
指定方法は、次のとおりです。

[カラム名] [データ型] AUTO_INCREMENT

② DEFAULT 制約

DEFAULT 制約を使用すると、値の指定が無い場合は、デフォルト値を格納します。
指定方法は、次のとおりです。

[カラム名] [データ型] DEFAULT [デフォルト値]

new_members テーブルの作成

続いて、new_members テーブルを作成します。
次のように、CREATE TABLE 文、INSERT 文のコマンドを実行してください。

PowerShell
mysql> CREATE TABLE new_members (
  id int PRIMARY KEY,
  name varchar(20),
  age tinyint,
  gender varchar(8),
  prefecture varchar(20)
);

mysql> INSERT INTO new_members VALUES
  (1, 'watanabe', 25, 'male', 'tokyo'),
  (2, 'yamamoto', 41, 'female', 'tokyo'),
  (3, 'kato', 68, 'female', 'fukuoka');

  mysql> SELECT * FROM new_members;
  +----+----------+------+--------+------------+
  | id | name     | age  | gender | prefecture |
  +----+----------+------+--------+------------+
  |  1 | watanabe |   25 | male   | tokyo      |
  |  2 | yamamoto |   41 | female | tokyo      |
  |  3 | kato     |   68 | female | fukuoka    |
  +----+----------+------+--------+------------+
  3 rows in set (0.00 sec)

以上のように、ID(id)、名前(name)、年齢(age)、性別(gender)、都道府県ID(prefecture_id)をカラムに持った表ができていれば OK です。

Lesson 10 Chapter 2
INSERT文

INSERT 文は、テーブルに新しいレコードを追加するときに使用します。
これまでのレッスンでも、折々に触れてきましたので、おおよその機能はイメージできていることと思います。
この Chapter では、これまでの復習を行いながら、もう少し踏み込んだ内容を学んでいきます。

レコードを 1 件追加する

① 全てのカラムを指定してデータを登録する

INSERT 文の基本構文は次のとおりです。

INSERT INTO [テーブル名] (カラム名1, カラム名2, ...) VALUES (値1, 値2, ...);

早速、members テーブルに新しいデータを追加してみましょう。
まず、次のように、基本に忠実に INSERT INTO 文を実行してください。

PowerShell
mysql> INSERT INTO members (id, name, age, prefecture, attendance) VALUES
  (1, 'tanaka', 28, 'tokyo', true);

データが挿入できたか、SELECT 文で確認してみましょう。

PowerShell
mysql> SELECT * FROM members;
+----+--------+------+------------+------------+
| id | name   | age  | prefecture | attendance |
+----+--------+------+------------+------------+
|  1 | tanaka |   28 | tokyo      |          1 |
+----+--------+------+------------+------------+
1 row in set (0.00 sec)

以上のように表示されれば OK です。

② カラム名の指定を省略する

CERATE TABLE 文で定義された順に全てのカラムの値を指定する場合は、以下のようにカラム名の指定を省略することができます。

INSERT INTO [テーブル名] VALUES (値1, 値2, ...);

それでは、カラム名の指定を省略して、members テーブルにデータを追加してみましょう。
次のように、INSERT INTO 文を実行してください。

PowerShell
mysql> INSERT INTO members VALUES (2, 'yamada', 19, 'osaka', true);

データが挿入できたか、SELECT 文で確認してみましょう。

PowerShell
mysql> SELECT * FROM members;
+----+--------+------+------------+------------+
| id | name   | age  | prefecture | attendance |
+----+--------+------+------------+------------+
|  1 | tanaka |   28 | tokyo      |          1 |
|  2 | yamada |   19 | osaka      |          1 |
+----+--------+------+------------+------------+
2 rows in set (0.00 sec)

間違いがなければ、以上のように追加されます。

③ データの一部を指定する

AUTO_INCREMENT 属性や DEFAULT 制約があるカラムは、INSERT INTO 文に指定しなくとも、自動的にデータが登録されます。
では、name, age, prefecture の値のみを指定して INSERT INTO 文を実行してみましょう。

PowerShell
mysql> INSERT INTO members (name, age, prefecture) VALUES ('suzuki', 33, 'tokyo');

SELECT 文で確認してみましょう。

PowerShell
mysql> SELECT * FROM members;
+----+--------+------+------------+------------+
| id | name   | age  | prefecture | attendance |
+----+--------+------+------------+------------+
|  1 | tanaka |   28 | tokyo      |          1 |
|  2 | yamada |   19 | osaka      |          1 |
|  3 | suzuki |   33 | tokyo      |          1 |
+----+--------+------+------------+------------+
3 rows in set (0.00 sec)

AUTO_INCREMENT により id に 3 が自動で採番され、attendance にはデフォルト値の 1(true)が登録されています。

複数のレコードを同時に追加する(バルクインサート)

INSERT INTO 文で複数のレコードを同時に追加することができます。
次のように VALUE 以下にカンマ区切りで複数のデータを追加します。

INSERT INTO [テーブル名] (カラム名1, カラム名2, ...)
  VALUES (値1, 値2, ...), (値1, 値2, ...), (値1, 値2, ...);

この方法は、一般的に「バルクインサート」と呼ばれていて、SQL 文の実行にかかる処理のオーバーヘッドが 1 回分で済むことから高速となります。

それでは次のようにバルクインサートを使用して INSERT INTO 文を実行してみましょう。

PowerShell
mysql> INSERT INTO members (name, age, prefecture) VALUES
  ('saito', 48, 'nagoya'),
  ('honda', 31, 'osaka'),
  ('nakamura', 23, 'tokyo');

SELECT 文で確認してみましょう。

PowerShell
mysql> SELECT * FROM members;
+----+----------+------+------------+------------+
| id | name     | age  | prefecture | attendance |
+----+----------+------+------------+------------+
|  1 | tanaka   |   28 | tokyo      |          1 |
|  2 | yamada   |   19 | osaka      |          1 |
|  3 | suzuki   |   33 | tokyo      |          1 |
|  4 | saito    |   48 | nagoya     |          1 |
|  5 | honda    |   31 | osaka      |          1 |
|  6 | nakamura |   23 | tokyo      |          1 |
+----+----------+------+------------+------------+
6 rows in set (0.00 sec)

正しく 3 つのデータが追加されました。

他のテーブルからデータを追加する(INSERT ... SELECT 文)

INSERT ... SELECT 構文を使用することで、他のテーブルからデータを取得して追加をすることができます。
構文は次のとおりです。

INSERT INTO [テーブル名] (カラム名1, カラム名2, ...)
  SELECT カラムA, カラムB, ... FROM [他のテーブル名] WHERE [抽出条件];

具体例を見た方が分かりやすいです。SQL 文は次のようになります。

PowerShell
mysql> INSERT INTO members (name, age, prefecture)
  SELECT name, age, prefecture FROM new_members;

上記 SQL の SELECT 以下は、今まで学んできた SELECT 文と同じ構造です。
必要に応じて WHERE 句など、自由に使うことができます。

上記の INSERT ... SELECT 文を実行したら、テーブルの中身を確認してみましょう。

PowerShell
mysql> SELECT * FROM members;
+----+----------+------+------------+------------+
| id | name     | age  | prefecture | attendance |
+----+----------+------+------------+------------+
|  1 | tanaka   |   28 | tokyo      |          1 |
|  2 | yamada   |   19 | osaka      |          1 |
|  3 | suzuki   |   33 | tokyo      |          1 |
|  4 | saito    |   48 | nagoya     |          1 |
|  5 | honda    |   31 | osaka      |          1 |
|  6 | nakamura |   23 | tokyo      |          1 |
|  7 | watanabe |   25 | tokyo      |          1 |
|  8 | yamamoto |   41 | tokyo      |          1 |
|  9 | kato     |   68 | fukuoka    |          1 |
+----+----------+------+------------+------------+
9 rows in set (0.00 sec)

new_members テーブルのデータが正しく追加されたことが確認できます。

Lesson 10 Chapter 3
UPDATE文

この Chapter では、前の Chapter で INSERT した以下の members テーブルをそのまま使用します。

+----+----------+------+------------+------------+
| id | name     | age  | prefecture | attendance |
+----+----------+------+------------+------------+
|  1 | tanaka   |   28 | tokyo      |          1 |
|  2 | yamada   |   19 | osaka      |          1 |
|  3 | suzuki   |   33 | tokyo      |          1 |
|  4 | saito    |   48 | nagoya     |          1 |
|  5 | honda    |   31 | osaka      |          1 |
|  6 | nakamura |   23 | tokyo      |          1 |
|  7 | watanabe |   25 | tokyo      |          1 |
|  8 | yamamoto |   41 | tokyo      |          1 |
|  9 | kato     |   68 | fukuoka    |          1 |
+----+----------+------+------------+------------+

基本的構文

UPDATE文は、テーブルに登録されているレコードを更新するときに使用します。
UPDATE 文の基本構文は次のとおりです。

UPDATE [テーブル名] SET [カラム名1] = [値1], [カラム名2] = [値2], ... WHERE [抽出条件];

1 つのカラムを更新する

members テーブルの id = 1 のレコードにつき、prefecture を tokyo から osaka に更新してみましょう。
SQL 文は次のように記述します。

PowerShell
UPDATE members SET prefecture = 'osaka' WHERE id = 1;

SQL を実行して、データが更新できたか、SELECT 文で確認してみましょう。

PowerShell
mysql> SELECT * FROM members;
+----+----------+------+------------+------------+
| id | name     | age  | prefecture | attendance |
+----+----------+------+------------+------------+
|  1 | tanaka   |   28 | osaka      |          1 |
|  2 | yamada   |   19 | osaka      |          1 |
|  3 | suzuki   |   33 | tokyo      |          1 |
|  4 | saito    |   48 | nagoya     |          1 |
|  5 | honda    |   31 | osaka      |          1 |
|  6 | nakamura |   23 | tokyo      |          1 |
|  7 | watanabe |   25 | tokyo      |          1 |
|  8 | yamamoto |   41 | tokyo      |          1 |
|  9 | kato     |   68 | fukuoka    |          1 |
+----+----------+------+------------+------------+
9 rows in set (0.00 sec)

id = 1 のレコードにつき、prefecture が osaka と変更されていることが確認できました。

複数のカラムを更新する

次に、複数のカラムを更新してみましょう。
members テーブルの id = 2 のレコードにつき、age を 20 に、prefecture を osaka から tokyo に更新するようにします。

複数のカラム更新の指定は、SET 句以下にカンマで区切って記述します。
次のように SQL 文を記述して実行してみましょう。

PowerShell
mysql> UPDATE members SET age = 20, prefecture = 'tokyo' WHERE id = 2;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1  Changed: 1  Warnings: 0

SELECT 文で確認してみましょう。

PowerShell
mysql> SELECT * FROM members;
+----+----------+------+------------+------------+
| id | name     | age  | prefecture | attendance |
+----+----------+------+------------+------------+
|  1 | tanaka   |   28 | osaka      |          1 |
|  2 | yamada   |   20 | tokyo      |          1 |
|  3 | suzuki   |   33 | tokyo      |          1 |
|  4 | saito    |   48 | nagoya     |          1 |
|  5 | honda    |   31 | osaka      |          1 |
|  6 | nakamura |   23 | tokyo      |          1 |
|  7 | watanabe |   25 | tokyo      |          1 |
|  8 | yamamoto |   41 | tokyo      |          1 |
|  9 | kato     |   68 | fukuoka    |          1 |
+----+----------+------+------------+------------+
9 rows in set (0.00 sec)

age と prefecture の 2 つのカラムが変更されていることが確認できました。

複数のレコードを更新する

UPDATE 文は、指定された条件に合うレコードを全て更新します。
members テーブルの prefecture = 'tokyo' のレコード全てにつき、attendance を 0 (false) に更新するようにします。 次のように SQL 文を記述して実行してみましょう。

PowerShell
mysql> UPDATE members SET attendance = false WHERE prefecture = 'tokyo';
Query OK, 5 rows affected (0.02 sec)
Rows matched: 5  Changed: 5  Warnings: 0

更新結果を SELECT 文で確認してみましょう。

PowerShell
mysql> SELECT * FROM members;
+----+----------+------+------------+------------+
| id | name     | age  | prefecture | attendance |
+----+----------+------+------------+------------+
|  1 | tanaka   |   28 | osaka      |          1 |
|  2 | yamada   |   20 | tokyo      |          0 |
|  3 | suzuki   |   33 | tokyo      |          0 |
|  4 | saito    |   48 | nagoya     |          1 |
|  5 | honda    |   31 | osaka      |          1 |
|  6 | nakamura |   23 | tokyo      |          0 |
|  7 | watanabe |   25 | tokyo      |          0 |
|  8 | yamamoto |   41 | tokyo      |          0 |
|  9 | kato     |   68 | fukuoka    |          1 |
+----+----------+------+------------+------------+
9 rows in set (0.00 sec)

prefecture = 'tokyo' のレコードについて、attendance が 0 (false) に変更されていることが確認できました。

Lesson 10 Chapter 4
DELETE文

この Chapter では、前の Chapter で使用した以下の members テーブルをそのまま使用します。

+----+----------+------+------------+------------+
| id | name     | age  | prefecture | attendance |
+----+----------+------+------------+------------+
|  1 | tanaka   |   28 | osaka      |          1 |
|  2 | yamada   |   20 | tokyo      |          0 |
|  3 | suzuki   |   33 | tokyo      |          0 |
|  4 | saito    |   48 | nagoya     |          1 |
|  5 | honda    |   31 | osaka      |          1 |
|  6 | nakamura |   23 | tokyo      |          0 |
|  7 | watanabe |   25 | tokyo      |          0 |
|  8 | yamamoto |   41 | tokyo      |          0 |
|  9 | kato     |   68 | fukuoka    |          1 |
+----+----------+------+------------+------------+

基本的構文

DELETE文は、テーブルに登録されているレコードを削除するときに使用します。
DELETE 文の基本構文は次のとおりです。

DELETE FROM [テーブル名] WHERE [抽出条件];

条件指定したデータを削除する

members テーブルの id = 3 のレコードを削除してみましょう。
SQL 文は次のように記述します。

PowerShell
DELETE FROM members WHERE id = 3;

SQL を実行して、データが削除できたか、SELECT 文で確認してみましょう。

PowerShell
mysql> SELECT * FROM members;
+----+----------+------+------------+------------+
| id | name     | age  | prefecture | attendance |
+----+----------+------+------------+------------+
|  1 | tanaka   |   28 | osaka      |          1 |
|  2 | yamada   |   20 | tokyo      |          0 |
|  4 | saito    |   48 | nagoya     |          1 |
|  5 | honda    |   31 | osaka      |          1 |
|  6 | nakamura |   23 | tokyo      |          0 |
|  7 | watanabe |   25 | tokyo      |          0 |
|  8 | yamamoto |   41 | tokyo      |          0 |
|  9 | kato     |   68 | fukuoka    |          1 |
+----+----------+------+------------+------------+
8 rows in set (0.00 sec)

id = 3 のレコードにつき、レコードが削除されていることが確認できました。

全てのデータを削除する

続いて members テーブルの全てのレコードを削除してみましょう。
この場合、抽出条件の WHERE 句は使用せず DELETE FROM [テーブル名] という形式で SQL 文を記述します。
それでは、次のように SQL 文を実行しましょう。

PowerShell
mysql> DELETE FROM members;
Query OK, 8 rows affected (0.00 sec)

以下のように、SELECT 文で実行結果を確認してみましょう。

PowerShell
mysql> SELECT * FROM members;
Empty set (0.00 sec)

テーブルの取得結果として Empty set と返却されました。
これは、テーブルのレコードが 0 件という状態を表します。
したがって、DELETE 文が正常に実行され、全てのレコードが削除されたということになります。

DELETE 文を実行した際の AUTO_INCREMENT の挙動について

ここで、1 つ確認をしておきます。
DELETE 文で全てのレコードを削除した後に、新しいレコードを追加した場合、AUTO_INCREMENT による id の採番はどのようになるかということです。
次のように INSERT 文を使用して、SQL を実行してみてください。

PowerShell
mysql> INSERT INTO members (name, age, prefecture) VALUES
  ('tanaka', 28, 'tokyo'),
  ('yamada', 19, 'osaka'),
  ('suzuki', 33, 'tokyo');

データ追加後のテーブルを確認してみると、次のようになっています。

PowerShell
mysql> SELECT * FROM members;
+----+--------+------+------------+------------+
| id | name   | age  | prefecture | attendance |
+----+--------+------+------------+------------+
| 10 | tanaka |   28 | tokyo      |          1 |
| 11 | yamada |   19 | osaka      |          1 |
| 12 | suzuki |   33 | tokyo      |          1 |
+----+--------+------+------------+------------+
3 rows in set (0.00 sec)

削除前の最終レコードの id = 9 の続きとして、新しいレコードの id は 10 から採番されることが確認できました。
これは、DELETE 文には、削除したレコードの記録を保持する仕組みがあるためです。この仕組みから、削除処理の取消し(ロールバック)などの実装をすることが可能となっています。
この結果については、次に紹介する TRUNCATE 文において、また言及します。

Lesson 10 Chapter 5
TRUNCATE文

ここでは、前の Chapter で使用したテーブルをそのまま使用して説明をしていきます。

+----+--------+------+------------+------------+
| id | name   | age  | prefecture | attendance |
+----+--------+------+------------+------------+
| 10 | tanaka |   28 | tokyo      |          1 |
| 11 | yamada |   19 | osaka      |          1 |
| 12 | suzuki |   33 | tokyo      |          1 |
+----+--------+------+------------+------------+

基本的構文

TRUNCATE 文は、テーブルに登録されているレコードを全て削除するときに使用します。
基本構文は次のとおりです。

TRUNCATE [テーブル名];

レコードを全削除するという点では、前の Chapter で学んだ DELETE FROM [テーブル名] 構文と同じ機能ということができます。

TRUNCATE 文と DELETE 文の違い

では、TRUNCATE 文と DELETE 文の違いはどこにあるのでしょうか。
大きな違いは、DELETE 文では「テーブルを保持したまま削除している」のに対して、TRUNCATE 文では「テーブルを削除して再作成している」という点にあります。

DELETE 文と TRUNCATE 文の比較

項目 DELETE 文 TRUNCATE 文
処理内容 テーブルを保持したままレコードを削除する テーブルを削除して再作成する
削除対象 削除するレコードを選択できる 全件削除のみ
削除記録 削除したレコードの記録を保持するためロールバックの実装が可能 削除記録は残らない
AUTO_INCREMENT AUTO_INCREMENT は削除されない AUTO_INCREMENT は削除されるので 1 番から採番される
処理速度 一定程度の時間がかかる 高速
分類 DML(データ操作言語) DDL(データ定義言語)

TRUNCATE 文は、テーブルを削除して再作成するため、高速でデータを削除することができますが、削除記録などが残らないため、状況に応じて DELETE 文と使い分けるようにしましょう。

データ削除の実行

それでは TRUNCATE 文を使用して members テーブルのレコードを削除してみましょう。
次のように SQL 文を実行してください。

PowerShell
mysql> TRUNCATE members;
Query OK, 0 rows affected (0.05 sec)

SELECT 文で実行結果を確認してみましょう。

PowerShell
mysql> SELECT * FROM members;
Empty set (0.00 sec)

テーブルの取得結果として Empty set と返却されました。
TRUNCATE 文で、全てのレコードが削除されたことが確認できました。

TRUNCATE 文を実行した際の AUTO_INCREMENT の挙動について

TRUNCATE 文で、AUTO_INCREMENT がどのように採番されるか確認してみましょう。
次のように INSERT 文を使用して、SQL を実行してみてください。

PowerShell
mysql> INSERT INTO members (name, age, prefecture) VALUES
  ('tanaka', 28, 'tokyo'),
  ('yamada', 19, 'osaka'),
  ('suzuki', 33, 'tokyo');

データ追加後のテーブルを確認してみると、次のようになりました。

PowerShell
mysql> SELECT * FROM members;
+----+--------+------+------------+------------+
| id | name   | age  | prefecture | attendance |
+----+--------+------+------------+------------+
|  1 | tanaka |   28 | tokyo      |          1 |
|  2 | yamada |   19 | osaka      |          1 |
|  3 | suzuki |   33 | tokyo      |          1 |
+----+--------+------+------------+------------+
3 rows in set (0.00 sec)

id が 1 から採番されていますね。
こういったところも DELETE 文と挙動が変わってきます。
TRUNCATE 文の性質を把握した上で、必要に応じて適切に使用できるようにしましょう。

本レッスンは、以上です。