PostgreSQL 入門

PostgreSQL におけるテーブル構造の変更

テーブル定義の変更(Altering tables)は、データベース管理において非常に重要なプロセスです。ビジネス要件の変化に伴い、テーブルをゼロから作り直すことなく、既存のデータベース構造を調整しなければならない場面が多々あります。

これには、新しいカラムの追加、既存カラムの属性変更、そして不要になったカラムの削除などが含まれます。

1. テーブルへのカラム追加

新しい情報を保存する必要が生じた際、既存のテーブルにカラムを追加するのが最も一般的な操作です。カラム追加の基本構文は以下の通りです。

ALTER TABLE table_name
ADD COLUMN column_name data_type constraint;
  • ALTER TABLE: テーブルを変更することを宣言するコマンドキーワードです。
  • table_name: 変更対象のテーブル名です。
  • ADD COLUMN: 「新しいカラムを追加する」という操作を指定します。
  • column_name: 新しいカラムの名前です。
  • data_type: 新しいカラムのデータ型(例:INTEGER, VARCHAR, DATE など)です。
  • constraint: (オプション)NOT NULLUNIQUE などの制約(Constraint)を直接指定できます。

1.1 基本的な追加例

例えば employees(従業員)テーブルがあり、従業員のメールアドレスを保存するカラムを追加したいとします。

ALTER TABLE employees
ADD COLUMN email VARCHAR(100);

このステートメントは、employees テーブルに email という名前のカラムを追加します。データ型は最大長100の文字列です。

1.2 デフォルト値を持つカラムの追加

既存のデータ行に対しても初期値を設定したい場合は、デフォルト値(DEFAULT)を使用します。

ALTER TABLE employees
ADD COLUMN hire_date DATE DEFAULT CURRENT_DATE;

これにより、hire_date(入社日)という DATE 型のカラムが追加されます。DEFAULT CURRENT_DATE を指定することで、既存のレコードや、今後日付を指定せずに挿入されるレコードに対して、自動的に当日の日付が入力されます。

1.3 制約付きのカラム追加

カラムを追加すると同時に、データのバリデーションルール(制約)を設定することも可能です。

ALTER TABLE employees
ADD COLUMN salary DECIMAL(10, 2) CHECK (salary >= 0);

ここでは salary(給与)カラムを追加しています。DECIMAL(10, 2) は通貨データの保存に適しています。CHECK (salary >= 0) というチェック制約により、給与が負の値になることを強制的に防ぎます。

2. テーブル内のカラム変更

カラムの変更では、既存カラムのデータ型、デフォルト値、または制約条件を修正できます。一般的な構文構造は以下の通りです。

ALTER TABLE table_name
ALTER COLUMN column_name [操作命令];

主な操作命令には以下があります:

  • TYPE data_type: データ型を変更します。
  • SET DEFAULT default_value: 新しいデフォルト値を設定します。
  • DROP DEFAULT: 既存のデフォルト値を削除します。
  • SET NOT NULL / DROP NOT NULL: NOT NULL 制約を追加または削除します。

2.1 データ型の変更

当初 employees テーブルの phone_number を整数型(INTEGER)として定義していたものの、国際番号(例:"+81")を保存するために文字列型(VARCHAR)に変更する必要が出たとします。

ALTER TABLE employees
ALTER COLUMN phone_number TYPE VARCHAR(20);

重要なヒント: データ型を変更する際、PostgreSQLは既存のデータを新しい型に変換しようとします。もし論理的に変換不可能なデータ(例:アルファベット "ABC" が含まれるカラムを INTEGER に強制変更しようとする場合)がある場合、ALTER TABLE コマンドはエラーとなり失敗します。

2.2 デフォルト値の設定と削除

既存の email カラムにデフォルト値を設定します。

ALTER TABLE employees
ALTER COLUMN email SET DEFAULT '[email protected]';

このデフォルト値が不要になった場合は、削除できます。

ALTER TABLE employees
ALTER COLUMN email DROP DEFAULT;

2.3 NOT NULL 制約の追加と削除

email カラムを今後必須入力(空を許可しない)にする場合:

ALTER TABLE employees
ALTER COLUMN email SET NOT NULL;

この非空制約を解除する場合:

ALTER TABLE employees
ALTER COLUMN email DROP NOT NULL;

3. テーブルからのカラム削除

カラムを削除すると、テーブルから完全に除去されます。この操作はデータが永久に失われるため、極めて慎重に行う必要があります。

構文は以下の通りです。

ALTER TABLE table_name
DROP COLUMN column_name;

3.1 基本的な削除例

employees テーブルの phone_number カラムが不要になった場合:

ALTER TABLE employees
DROP COLUMN phone_number;

核心的な注意点:

  • カラムを削除すると、そのカラムに保存されていたすべてのデータが永久に破棄されます。
  • ビュー(Views)、関数(Functions)、ストアドプロシージャなど、削除しようとしているカラムに依存するオブジェクトがある場合、PostgreSQLは通常エラーを出して削除をブロックします。その場合は、先に依存しているオブジェクトを修正または削除する必要があります。
  • 本番環境(Production environment)で DROP COLUMN を実行する前に、データベースのバックアップを取ることは極めて優れた習慣です。

3.2 IF EXISTS を使用した安全な削除

存在しないカラムを削除しようとしてスクリプトがエラーで中断されるのを防ぐために、IF EXISTS 句を使用できます。

ALTER TABLE employees
DROP COLUMN IF EXISTS phone_number;

phone_number が存在すれば削除され、存在しなければエラーを投げずにコマンドが正常終了します。

4. 実際のビジネスシナリオでの演習

実際の業務において、テーブル構造がどのように進化していくかを見てみましょう。

4.1 シナリオ1:ECプラットフォーム

カラム追加: サービスが海外展開されることに伴い、注文の決済通貨を記録する必要があります。

ALTER TABLE orders ADD COLUMN currency VARCHAR(3);

カラム変更: 当初 order_status(注文ステータス)を自由記述の TEXT 型にしていましたが、フォーマットを厳格にするため文字数制限のある型に変更します。

ALTER TABLE orders ALTER COLUMN order_status TYPE VARCHAR(20);

カラム削除: 外部の専門的な物流システムを導入したため、元の注文テーブルにあった簡易的な shipping_address(配送先住所)カラムが不要になり、クリーンアップします。

ALTER TABLE orders DROP COLUMN shipping_address;

4.2 シナリオ2:ソーシャルメディアアプリ

カラム追加: ユーザーのアクティブ状況を分析するため、users テーブルに「最終ログイン時間」を追加します。

ALTER TABLE users ADD COLUMN last_login TIMESTAMP;

カラム変更: セキュリティとコンプライアンスの観点から、ユーザー名の最大許容長を延長することに決定しました。

ALTER TABLE users ALTER COLUMN username TYPE VARCHAR(100);

カラム削除: より粒度の細かい新しいプライバシー設定パネルをリリースしたため、旧版の簡素な profile_visibility(プロフィール公開設定)フィールドを廃止します。

ALTER TABLE users DROP COLUMN profile_visibility;