Skip to main content

CASCADE を禁止する: SQL レビュールール解説

Tianzhou · 2026年5月5日

1 つの誤解された CASCADE コマンドが、数秒で本番データを消し飛ばすことがあります。このキーワードは無害に見えますが、データベーススキーマ全体にまたがる削除を引き起こせます。

Bytebase の SQL レビュー には、CASCADE 障害を防ぐためのルールが含まれます。

  1. ON DELETE 句に CASCADE オプションを使うことを禁止する: ON DELETECASCADE オプションは、依存オブジェクトの大量削除や変更を引き起こし、想定外の結果につながる。

  2. テーブル削除時に CASCADE を使うことを禁止する: テーブル削除時の CASCADE オプションは、依存オブジェクトの大量削除や変更を引き起こし、想定外の結果につながる。

CASCADE とは

SQL における CASCADE は 2 つの文脈で現れます。

外部キー制約での CASCADE

CREATE TABLE posts (
    user_id INT,
    FOREIGN KEY (user_id) REFERENCES users(id)
        ON DELETE CASCADE  -- ユーザーを削除すると、その投稿もすべて削除される
);

TRUNCATE 操作での CASCADE

TRUNCATE TABLE users CASCADE;  -- users と、それを参照するテーブルすべてを truncate する

補足: TRUNCATE ... CASCADE は PostgreSQL 固有です。外部キーで依存しているテーブルを自動的に truncate するこの挙動は、MySQL、SQL Server などの他データベースには存在しません。Oracle にも TRUNCATE ... CASCADE はありますが、目的は別 (マテリアライズドビュー) です。

これはとくに危険です — 多くの開発者がその挙動を誤解しています。

よくある誤解

あるチームがデータベースを移行していて、新テーブルからテストデータをクリーンアップしたい、という場面を想像してください。開発者は次を実行します。

TRUNCATE TABLE new_feature_table CASCADE;

意図: 新テーブルからテストデータを削除する。

仮定: CASCADE は他テーブルの関連テストデータだけを消すはず。

実際に起きたこと: TRUNCATE ... CASCADEnew_feature_table へ外部キーを持つすべてのテーブルの全データを削除しました — 数年分の本番データを含めて。

ここでの決定的な誤解は: TRUNCATE TABLE A CASCADE は B テーブルの「関連行」を消すのではないということです。それは A を参照する外部キーを持つテーブルそのものを truncate します。相互参照が複雑なスキーマでは、1 つの CASCADE がデータベース全体を吹き飛ばし得ます。

データベースを守る方法

1. 明示的な DELETE 文を使う

-- ❌ 危険: CASCADE が想定外のテーブルに波及する
TRUNCATE TABLE users CASCADE;

-- ✅ 安全: 何を消すかを完全に制御できる
DELETE FROM user_sessions WHERE user_id IN (SELECT id FROM users WHERE ...);
DELETE FROM users WHERE ...;

2. 自動 SQL レビューを導入する

Bytebase を使って、実行前にすべての SQL を自動スキャンし、本番での危険な CASCADE 操作をブロックする。

3. 危険な権限を取り上げる

REVOKE TRUNCATE ON ALL TABLES IN SCHEMA public FROM app_user;

4. マイグレーションを徹底的にテストする

本番ライクなデータで、ステージングでフルマイグレーションを実行し、影響範囲を確認し、ロールバック手順をテストする。

5. より安全な外部キーオプションを使う

ON DELETE CASCADE の代わりに ON DELETE RESTRICTON DELETE SET NULL を検討する。

まとめ

CASCADE キーワードはデータベース全体にまたがる自動削除を引き起こせます。最も重要な点: TRUNCATE TABLE A CASCADE は A を参照する外部キーを持つすべてのテーブルを truncate します — 関連行だけではありません。

データベースを守る:

  • 明示的な DELETE 文でデータ削除を完全に制御する
  • Bytebase の SQL レビュールールで本番の CASCADE をブロックする
  • アプリケーションユーザーから TRUNCATE 権限を取り上げる
  • スキーマ変更は必ずステージングでテストする
ブログに戻る

データベース開発のスタンダードを体験する