👮‍♂️

【MySQL・PostgreSQL】データベースの「カラムコメントの変更方法」について

に公開

仕様変更やドキュメント整備などで、「カラムのコメントだけを変更したい」という場面があるかと思います。
ただし、使っているRDBMSによってやり方が異なるので注意が必要です。
本記事では、主要なRDBMSでのカラムコメント変更方法をまとめます。

🏗 Dockerを使った実行環境

今回の記事では、MySQL / PostgreSQL の2種類のRDBMSに対してテーブル定義とコメントを扱う方法を比較・検証するため、
各DBを Docker 上で起動して操作しています。自分でもやってみたい方は参考にしてください。

✅ 前提条件

以下のツールがインストールされていることを前提とします。

  • Docker
  • Docker Compose

📁 ディレクトリ構成


db-env/
    ├── docker-compose.yml
    ├── mysql/
    │   └── init.sql
    │   └── my.cnf
    ├── postgres/
    │   └── init.sql
    ├── docker-compose.sh
    ├── docker-compose.yml

🧱 docker-compose.yml の内容

MySQL・PostgreSQLの2つのDBコンテナを同時に起動します。


version: '3.9'
services:
  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: rootpass
      MYSQL_DATABASE: testdb
    ports:
      - "3306:3306"
    volumes:
      - ./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql

  postgres:
    image: postgres:16
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: testdb
    ports:
      - "5432:5432"
    volumes:
      - ./postgres/init.sql:/docker-entrypoint-initdb.d/init.sql

🚀 起動コマンド

以下のコマンドで全てのDBが起動し、初期化スクリプトが実行されます

docker-compose down -v
docker-compose up --build -d

起動後、以下のクレデンシャルで各DBに接続できます

DB ユーザー名 パスワード ホスト ポート 備考
MySQL root rootpass localhost 3306 testdb が初期DB
PostgreSQL postgres postgres localhost 5432 testdb が初期DB

📦 各初期化SQL(init.sql)の内容

各DBごとに users テーブルを作成し、カラムコメントとテーブルコメントを含めた構成になっています。

💥 MySQLの落とし穴:コメントだけ変更できない

MySQLでは、「コメントだけ変更する専用の構文」は存在しません。

-- NG: コメントだけ変更しようとしてこれを書くと…
ALTER TABLE users MODIFY COLUMN is_active TINYINT(1) COMMENT 'NG';

テーブル定義によってはデフォルト値やNOT NULL制約が失われる可能性があるので非常に危険です。

NG例

MySQLに以下のようなusersテーブルがあったとします。

MySQLのuserテーブル
mysql> SHOW CREATE TABLE users\G
*************************** 1. row ***************************
       Table: users
Create Table: CREATE TABLE `users` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ユーザーID(自動採番)',
  `username` varchar(50) NOT NULL COMMENT 'ユーザー名(ユニーク)',
  `email` varchar(255) NOT NULL COMMENT 'メールアドレス(ユニーク)',
  `password_hash` varchar(255) NOT NULL COMMENT 'ハッシュ化されたパスワード',
  `date_of_birth` date DEFAULT NULL COMMENT '生年月日',
  `gender` enum('male','female','other','prefer_not_to_say') DEFAULT 'prefer_not_to_say' COMMENT '性別',
  `is_active` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'アカウント有効状態(1: 有効, 0: 無効)',
  `last_login_at` datetime DEFAULT NULL COMMENT '最終ログイン日時',
  `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '作成日時',
  `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新日時',
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`),
  UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='ユーザー情報を格納するテーブル'
1 row in set (0.00 sec)

mysql> 

is_activeはデフォルトが1で設定されており、NOT NULL制約のカラムになっています。
このカラムのコメント変更を先程のALTER文で実行すると....

- `is_active` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'アカウント有効状態(1: 有効, 0: 無効)',
+ `is_active` tinyint(1) DEFAULT NULL COMMENT 'NG',

is_activeのコメントは変更されたがデフォルト値やNOT NULL制約が失われます。
これは、MODIFY COLUMNで明示的に制約を書かないと、上書きされてしまう仕様によるものです。

✅ MySQLで安全にカラムコメントを変更するには?

OK例:ALTER TABLE MODIFY COLUMN を使うときは、元の制約・デフォルト値も指定する

MODIFY COLUMNでは制約・デフォルト値・コメントすべて書く必要がある。

-- OK: コメントだけでなくは、元の制約・デフォルト値も指定
ALTER TABLE users MODIFY COLUMN is_active TINYINT(1) NOT NULL DEFAULT '1' COMMENT 'OK';

usersテーブルでOKのALTER文で実行すると....

- `is_active` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'アカウント有効状態(1: 有効, 0: 無効)',
+ `is_active` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'OK',

デフォルト値とNOT NULL制約は元のままコメントは更新されることが確認できました。

🧘 PostgreSQLはシンプル

PostgreSQLは非常にシンプルです。

PostgreSQLのuserテーブル
                                                                                  Table "public.users"
    Column     |            Type             | Collation | Nullable |                Default                 | Storage  | Compression | Stats target |           Description
---------------+-----------------------------+-----------+----------+----------------------------------------+----------+-------------+--------------+----------------------------------
 id            | bigint                      |           | not null | nextval('users_id_seq'::regclass)      | plain    |             |              | ユーザーID(自動採番)
 username      | character varying(50)       |           | not null |                                        | extended |             |              | ユーザー名(ユニーク)
 email         | character varying(255)      |           | not null |                                        | extended |             |              | メールアドレス(ユニーク)
 password_hash | character varying(255)      |           | not null |                                        | extended |             |              | ハッシュ化されたパスワード
 date_of_birth | date                        |           |          |                                        | plain    |             |              | 生年月日
 gender        | character varying(32)       |           |          | 'prefer_not_to_say'::character varying | extended |             |              | 性別
 is_active     | boolean                     |           | not null | true                                   | plain    |             |              | アカウント有効状態(TRUE: 有効)
 last_login_at | timestamp without time zone |           |          |                                        | plain    |             |              | 最終ログイン日時
 created_at    | timestamp without time zone |           | not null | CURRENT_TIMESTAMP                      | plain    |             |              | 作成日時
 updated_at    | timestamp without time zone |           | not null | CURRENT_TIMESTAMP                      | plain    |             |              | 更新日時
Indexes:
    "users_pkey" PRIMARY KEY, btree (id)
    "users_email_key" UNIQUE CONSTRAINT, btree (email)
    "users_username_key" UNIQUE CONSTRAINT, btree (username)
Check constraints:
    "users_gender_check" CHECK (gender::text = ANY (ARRAY['male'::character varying, 'female'::character varying, 'other'::character varying, 'prefer_not_to_say'::character varying]::text[]))
Access method: heap

COMMENT ON COLUMN は専用の構文で、コメントだけを安全に変更できます。

-- コメントだけ変更する場合(型や制約には影響なし)
COMMENT ON COLUMN users.is_active IS 'OK';
-  is_active     | boolean                     |           | not null | true                                   | plain    |             |              | アカウント有効状態(TRUE: 有効)
+  is_active     | boolean                     |           | not null | true                                   | plain    |             |              | OK

まとめ

DB カラム名変更の影響 コメントが消えるか? 対策
MySQL カラム定義丸ごと再指定必須 はい、書かないと消える CHANGE COLUMNでコメント含む全定義を書き直す
PostgreSQL 名前のみ変更 いいえ なし

🔚 おわりに

RDBMSによって、「コメントの変更」という一見シンプルな操作にも落とし穴があります。
特にMySQLは「変更時は上書き扱い」という特徴があるため、事前にSHOW CREATE TABLEなどで確認し、正確に再定義することが重要です。
「コメントだけ変えたつもりなのに、他の定義が壊れた」…そんな事故を防ぐためにも、この記事が参考になれば嬉しいです。

Discussion