本文へスキップ
totonoe.tech

プログラミング言語を整える

中級

MySQL を整える。

= Web サービスで広く使われる MySQL の書き方の癖を、同じお題で見比べて学ぶ

MySQL が初めての方は、先に そもそも MySQL とは・どんな場面で使うか をどうぞ。

MySQLとは

Web サービスの裏側で広く使われてきたリレーショナルデータベースで、PHP と組み合わせた LAMP 構成や WordPress でおなじみです。

誕生 1995年
作った人・組織 スウェーデンの MySQL AB(Michael Widenius、David Axmark ら)。Sun Microsystems による買収を経て、現在は Oracle が開発しています
種類 リレーショナルデータベース(RDB)
ライセンス GPL v2 と商用ライセンスのデュアルライセンス
得意なこと 読み書きの多い Web アプリケーションのデータを、手軽に導入して扱えることです。
手元で動かすには mysql -u root -p

日本での使われ方

  • Web サービスのデータベースとして広く使われています。
  • Linux・Apache・MySQL・PHP を組み合わせた LAMP 構成は、レンタルサーバーでもよく提供されている定番の組み合わせです。
  • WordPress は MySQL(または互換の MariaDB)を前提に作られているため、ブログや企業サイトの裏側で MySQL が動いていることが多くあります。
  • MySQL の元の開発者が始めた派生版(フォーク)の MariaDB もあり、Linux のディストリビューションによっては MySQL の代わりに MariaDB が入っています。

使えるクラウドサービス

  • Amazon RDS for MySQL:AWS が提供するマネージドの MySQL で、バックアップやパッチ適用を任せられます。
  • Amazon Aurora(MySQL 互換):AWS が独自に作ったストレージの上で動く、MySQL と互換のあるデータベースです。
  • Google Cloud SQL for MySQL:Google Cloud が提供するマネージドの MySQL です。
  • Azure Database for MySQL:Microsoft Azure が提供するマネージドの MySQL です。
  • PlanetScale:MySQL の水平分割の仕組み Vitess を土台にしたデータベースのサービスです。

研修・学習での位置づけ

MySQL は、SQL の入門で PostgreSQL と並んでよく使われるデータベースです。インストールが手軽で、PHP や WordPress と一緒に Web アプリケーションの作り方を学ぶ研修でも題材になります。ほかの DB と比べると、文字の大小を区別しない比較や || の扱いなど独自の振る舞いがあるため、その違いを知っておくと移行のときに迷いません。

関わる資格

  • Oracle Certified Professional, MySQL 8.0 Database Administrator
  • Oracle Certified Professional, MySQL 8.0 Database Developer

そもそも MySQL とは

Web サイトの裏側で長く使われてきた、定番のリレーショナルデータベース。

MySQL(マイエスキューエル)は、SQL で操作するサーバー型のリレーショナルデータベース(RDB)です。オープンソースとして公開されていて、Web サイトやアプリの保存先として広く使われてきました。Linux・Apache・MySQL・PHP を組み合わせた「LAMP」という構成の名前でも知られています。

PostgreSQL とは同じ SQL を使う仲間で、細かい書き方や機能が違います。MySQL から分かれて作られた互換のデータベースに MariaDB があります。WordPress のようなブログ・サイト作成ソフトも、MySQL か MariaDB に記事を保存しています。SQLite のように組み込むのではなく、サーバーとして動かし、多くの人が同時に使います。

どこで・どんな場面で使うか

  • WordPress などのサイト作成ソフト

    記事・ページ・ユーザー情報の保存先として使われています。

  • EC サイトや Web サービス

    商品・会員・注文のデータを保存する土台になります。

  • 業務システム

    社内の管理システムや、PHP・Java などで作られた既存システムの保存先に使われています。

  • クラウドのマネージドサービス

    主要なクラウドが、運用を任せられる MySQL 版を用意しています。

  • 求人での位置づけ

    PHP や Web 系の開発案件、保守案件の募集でよく名前が出ます。

向いている場面・向いていない場面

  • 向いている場面:読み取りが多い Web サービス、既存の PHP・LAMP 構成、情報が多い定番の道具を選びたいとき。
  • 向いていない場面:手元の大きな CSV を集計するだけの用途(DuckDB など)や、高速なキャッシュ用途(Redis など)。
  • 調べやすい。長く使われているので、解説記事や実例が多く、困ったときに調べやすいのも利点です。

このページには練習場がありません(MySQL はブラウザの中で動かせないため)。下のお題の SQL を読み、近い文は SQL の練習場や PostgreSQL のページで試せます。

6つのお題をMySQLで書く

PostgreSQL・MySQL・DuckDB・MongoDB・Redis の5ページで、同じ商品と注文のデータに同じ6つのお題を並べています。SQL の方言の違いや、SQL を使わないデータベースでの考え方の違いがそのまま比べられます。

このページでは SQL を実行できません(MySQL はブラウザの中では動きません)。表示している結果とエラーのメッセージは、MySQL 8.0.46 のサーバーで実際に流して確かめたものです。結果の表は、見比べやすいように全ページで psql に寄せた同じ形にそろえています(NULL は NULL と表示)。mysql コマンドの枠線つきの表示とは見た目が違います。

準備(全お題共通)表を作ってデータを入れるコード。お題2〜6・クイズ・エラーの例は、これを流した後に続けて流した結果です。
CREATE TABLE products (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(50) NOT NULL,
  category VARCHAR(20) NOT NULL,
  price INT NOT NULL
);
CREATE TABLE orders (
  id INT AUTO_INCREMENT PRIMARY KEY,
  product_id INT NOT NULL,
  qty INT NOT NULL,
  ordered_on DATE NOT NULL
);
INSERT INTO products (id, name, category, price) VALUES
  (1, 'りんご', '果物', 150),
  (2, 'みかん', '果物', 80),
  (3, '牛乳', '飲み物', 200),
  (4, 'お茶', '飲み物', 120),
  (5, '食パン', 'パン', 250);
INSERT INTO orders (id, product_id, qty, ordered_on) VALUES
  (1, 1, 3, '2026-10-01'),
  (2, 3, 1, '2026-10-01'),
  (3, 2, 5, '2026-10-02'),
  (4, 1, 2, '2026-10-03'),
  (5, 4, 4, '2026-10-03');

SQL(MySQL)

CREATE TABLE products (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(50) NOT NULL,
  category VARCHAR(20) NOT NULL,
  price INT NOT NULL
);
CREATE TABLE orders (
  id INT AUTO_INCREMENT PRIMARY KEY,
  product_id INT NOT NULL,
  qty INT NOT NULL,
  ordered_on DATE NOT NULL
);
INSERT INTO products (id, name, category, price) VALUES
  (1, 'りんご', '果物', 150),
  (2, 'みかん', '果物', 80),
  (3, '牛乳', '飲み物', 200),
  (4, 'お茶', '飲み物', 120),
  (5, '食パン', 'パン', 250);
INSERT INTO orders (id, product_id, qty, ordered_on) VALUES
  (1, 1, 3, '2026-10-01'),
  (2, 3, 1, '2026-10-01'),
  (3, 2, 5, '2026-10-02'),
  (4, 1, 2, '2026-10-03'),
  (5, 4, 4, '2026-10-03');
SELECT * FROM products ORDER BY id;

結果

 id | name   | category | price
----+--------+----------+-------
 1  | りんご | 果物     | 150
 2  | みかん | 果物     | 80
 3  | 牛乳   | 飲み物   | 200
 4  | お茶   | 飲み物   | 120
 5  | 食パン | パン     | 250
(5 行)

AUTO_INCREMENT を付けた列は、値を省くと自動で連番が入ります。ここでは結果を毎回同じにするため id を明示しています。日本語を正しく保存するには、データベースや表の文字コードを utf8mb4 にします(MySQL 8.0 の既定値です)。

同じお題をほかのデータベースで: PostgreSQL・DuckDB・MongoDB・Redis

出力当てクイズ

準備のデータを入れた後に流したときの、最後の SQL の結果を選んでください。選ぶと正解と理由が出ます(答えはどこにも送られず、記録もしません)。

問1

SELECT 7 / 2;

画面に出るのは?

問2

SELECT 'a' = 'A';

画面に出るのは?

問3

SELECT CONCAT('abc', NULL);

画面に出るのは?

問4

SELECT 'abc' || 'def';

画面に出るのは?

よくあるエラーと直し方

書き始めの人が出会いやすいエラーです。メッセージは英語のまま出るので、どの言葉を手がかりにすればよいかもあわせて載せています。

SQL の書き間違い

エラーになるコード

SELECT * FORM products;

画面に出るメッセージ(抜粋)

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FORM products' at line 1

何が起きているか:FROM を FORM と書き間違えたため、文の形として読めませんでした。

直し方:near の後ろに示された箇所の少し前を見直します。キーワードの綴りや、カンマ・括弧の過不足がよくある原因です。

表が見つからない

エラーになるコード

SELECT * FROM product;

画面に出るメッセージ(抜粋)

ERROR 1146 (42S02): Table 'shop.product' doesn't exist

何が起きているか:表の名前が products ではなく product になっていました。メッセージには「データベース名.表名」の形で表示されます(ここではデータベース名を shop としています)。

直し方:SHOW TABLES; で表の名前を確かめます。Linux の MySQL では、表名の大文字と小文字が区別される設定が既定です。

主キーの重複

エラーになるコード

INSERT INTO products (id, name, category, price) VALUES (1, 'ぶどう', '果物', 400);

画面に出るメッセージ(抜粋)

ERROR 1062 (23000): Duplicate entry '1' for key 'products.PRIMARY'

何が起きているか:id が 1 の行はすでにあるため、主キーの重複になりました。

直し方:id を省いて AUTO_INCREMENT に任せるか、上書きしたいときは INSERT … ON DUPLICATE KEY UPDATE を使います。

GROUP BY に無い列を選んだ

エラーになるコード

SELECT category, name, COUNT(*) FROM products GROUP BY category;

画面に出るメッセージ(抜粋)

ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'shop.products.name' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

何が起きているか:カテゴリごとにまとめた1行に、name のどれを出すかが決まらないためです。MySQL 8.0 は既定で ONLY_FULL_GROUP_BY が有効です。

直し方:name を GROUP BY に加えるか、MIN(name) や GROUP_CONCAT(name) のように集計関数で包みます。

ほかのデータベースの解説

  • PostgreSQL 1986年にカリフォルニア大学バークレー校で始まった研究プロジェクト POSTGRES が元で・リレーショナルデータベース
  • DuckDB 2019年・組み込み型の分析用
  • MongoDB 2009年・ドキュメント指向データベース
  • Redis 2009年・インメモリのキーバリューストア

5つのデータベースと SQLite を並べた比較は データベースを整える にあります。 書いたコードはどこにも送られません(このページに入力欄はクイズの選択だけで、選んだ答えも記録しません)。

このツールについて

Web サービスの裏側で広く使われてきたリレーショナルデータベースで、PHP と組み合わせた LAMP 構成や WordPress でおなじみです。

MySQL の概要と、同じ6つのお題・出力当てクイズ・よくあるエラー(1064 など)。結果は MySQL 8.0 で確かめたもの。

主な機能

  • 概要(誕生・作った人・種類・ライセンス)と日本での使われ方・クラウドサービス・研修と資格
  • 同じ商品と注文のデータで6つのお題(PostgreSQL・DuckDB・MongoDB・Redis の同じお題へ移れる)
  • 出力当てクイズ4問(正解と理由)
  • よくあるエラー4件(実際のメッセージ・原因・直し方)
  • 結果は MySQL 8.0.46 のサーバーで照合済み・送信ゼロ

よくある質問

Q. このページで MySQL の SQL を実行できますか?

A. できません。MySQL はブラウザの中で動かせないため、解説だけのページにしています。表示している結果とエラーのメッセージは、MySQL 8.0.46 のサーバーで実際に流して確かめたものです。

Q. 'a' = 'A' が 1(真)になるのはなぜですか?

A. MySQL 8.0 の既定の照合順序(utf8mb4_0900_ai_ci)が、大文字と小文字を区別しない比較をするためです。区別したいときは、列や比較に utf8mb4_bin などの照合順序を指定します。

Q. ON DUPLICATE KEY UPDATE の VALUES(price) は使えますか?

A. MySQL 8.0.20 から非推奨になっています。8.0.19 以降は INSERT … AS new … ON DUPLICATE KEY UPDATE price = new.price のように、行に別名を付けて書く形が使えます。

入力値はURLの「#」以降に入るためサーバーには送信されません。リンクを開くと同じ状態を復元します。

続けて整える

データの時点:各ページに記載の版(各プロジェクトの公式リリース)

データの更新予定の一覧

運営サイト

私たちが運営するサイト