0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【PostgreSQL】備忘録 PostgreSQLのテーブル制約についてとSQLiteとの比較

0
Posted at

はじめに

基本情報技術者試験の学習をしていた為、
更新が遅れました。

本記事では、PostgreSQLのテーブル制約の種類と使い方を
SQLiteとの比較を交えながら備忘録としてまとめます。


1. 制約の種類一覧

制約 キーワード SQLiteとの違い
主キー制約 PRIMARY KEY ほぼ同じ
NOT NULL制約 NOT NULL 同じ
UNIQUE制約 UNIQUE 同じ
CHECK制約 CHECK ほぼ同じ
DEFAULT制約 DEFAULT ほぼ同じ
外部キー制約 FOREIGN KEY デフォルトで有効(SQLiteは無効)
除外制約 EXCLUDE PostgreSQL独自(SQLiteにはない)

2. PRIMARY KEY(主キー制約)

-- 列レベル
CREATE TABLE users (
    id   SERIAL PRIMARY KEY, -- 自動採番はSERIALを使う
    name TEXT
);

-- テーブルレベル(複合主キー)
CREATE TABLE order_parts (
    order_id INTEGER,
    part_id  INTEGER,
    PRIMARY KEY (order_id, part_id)
);

SQLiteとの違い

項目 SQLite PostgreSQL
自動採番 INTEGER PRIMARY KEY SERIAL PRIMARY KEY
大きな自動採番 INTEGER PRIMARY KEY BIGSERIAL PRIMARY KEY
UUID主キー 非推奨 UUID DEFAULT gen_random_uuid()

PostgreSQLではSERIALの代わりにGENERATED ALWAYS AS IDENTITYも使えます。

id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY

より標準SQLに近い書き方です。


3. NOT NULL制約

CREATE TABLE users (
    id   SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    age  INTEGER          -- NULLを許可
);

SQLiteと同じ書き方で使えます。


4. UNIQUE制約

CREATE TABLE users (
    id    SERIAL PRIMARY KEY,
    email TEXT UNIQUE,
    name  TEXT
);

-- 複合UNIQUE
CREATE TABLE schedules (
    user_id INTEGER,
    date    DATE,
    UNIQUE (user_id, date)
);

SQLiteとの違い

PostgreSQLのUNIQUE制約には部分インデックスを使った
条件付きUNIQUEが設定できます。

-- activeがTRUEの行だけUNIQUEにする(PostgreSQL独自)
CREATE UNIQUE INDEX unique_active_email
ON users (email)
WHERE active = TRUE;

5. CHECK制約

CREATE TABLE products (
    id    SERIAL PRIMARY KEY,
    name  TEXT    NOT NULL,
    price NUMERIC CHECK (price >= 0),
    rank  TEXT    CHECK (rank IN ('A', 'B', 'C'))
);

SQLiteとほぼ同じ書き方で使えます。

PostgreSQL独自の書き方

-- 制約に名前を付けられる(エラーメッセージが分かりやすくなる)
CREATE TABLE products (
    id    SERIAL PRIMARY KEY,
    price NUMERIC CONSTRAINT price_non_negative CHECK (price >= 0)
);

エラー時にprice_non_negativeという名前が表示されるため
原因を特定しやすくなります。


6. DEFAULT制約

CREATE TABLE logs (
    id         SERIAL PRIMARY KEY,
    message    TEXT    NOT NULL,
    level      TEXT    DEFAULT 'INFO',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 現在日時
    is_read    BOOLEAN   DEFAULT FALSE
);

SQLiteとの違い

項目 SQLite PostgreSQL
現在日時 datetime('now', 'localtime') CURRENT_TIMESTAMP
真偽値デフォルト DEFAULT 0 DEFAULT FALSE
UUID自動生成 なし DEFAULT gen_random_uuid()

7. FOREIGN KEY(外部キー制約)

-- 親テーブル
CREATE TABLE parts (
    id   SERIAL PRIMARY KEY,
    name TEXT NOT NULL
);

-- 子テーブル
CREATE TABLE orders (
    id      SERIAL PRIMARY KEY,
    part_id INTEGER NOT NULL,
    qty     INTEGER NOT NULL CHECK (qty > 0),
    FOREIGN KEY (part_id) REFERENCES parts(id)
        ON DELETE CASCADE
        ON UPDATE CASCADE
);

SQLiteとの最大の違い

項目 SQLite PostgreSQL
デフォルトの有効・無効 無効(毎回PRAGMAが必要) 有効(設定不要)
有効化方法 PRAGMA foreign_keys = ON 不要

PostgreSQLでは外部キー制約がデフォルトで有効です。
SQLiteのように毎回PRAGMAを実行する必要がありません。


8. EXCLUDE制約(PostgreSQL独自)

SQLiteにはないPostgreSQL独自の制約です。
特定の条件で重複する行を禁止できます。

-- 同じ部屋の予約が重複しないようにする
CREATE TABLE reservations (
    room_id  INTEGER,
    period   TSRANGE, -- 時間範囲型
    EXCLUDE USING GIST (room_id WITH =, period WITH &&)
);

範囲型と組み合わせて予約システムの重複チェックなどに使われます。
通常のCHECK制約では難しい「範囲の重複禁止」を実現できます。


9. 制約の組み合わせ例

CREATE TABLE employees (
    id         SERIAL          PRIMARY KEY,
    emp_code   TEXT            NOT NULL UNIQUE,
    name       TEXT            NOT NULL,
    department TEXT            NOT NULL DEFAULT '未配属',
    salary     NUMERIC(10, 2)  NOT NULL CHECK (salary >= 0),
    is_active  BOOLEAN         NOT NULL DEFAULT TRUE,
    created_at TIMESTAMPTZ     DEFAULT CURRENT_TIMESTAMP
);

10. SQLiteとPostgreSQLの制約比較まとめ

制約 SQLite PostgreSQL
自動採番 INTEGER PRIMARY KEY SERIAL / BIGSERIAL
外部キーの有効化 PRAGMAが必要 不要(デフォルト有効)
BOOLEAN型 INTEGER(0/1) BOOLEAN(TRUE/FALSE)
日時のデフォルト datetime('now','localtime') CURRENT_TIMESTAMP
制約への命名 非推奨 CONSTRAINT 名前 CHECK(...)
除外制約 なし EXCLUDE USING GIST
部分インデックス 対応 対応(より高機能)

まとめ

ポイント 内容
外部キーはデフォルト有効 SQLiteと異なりPRAGMA不要
自動採番はSERIAL SQLiteのINTEGER PRIMARY KEYと同等
制約に名前を付けられる エラー追跡がしやすくなる
EXCLUDE制約はPostgreSQL独自 範囲の重複禁止に有効
型が厳密 BOOLEANやTIMESTAMPが専用型として使える

さいごに

SQLiteでの実務経験があれば
PostgreSQLの制約は比較的スムーズに理解できる気がします。
ただ、SQLiteはサーバーレスのDBMSなので
SQLiteにはない機能も多いです。

今回、まとめた内容以外にも
オリジナルの機能もあるので学習をすすめます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?