Claude Media
Claude Codeでカラム定義書を作る — PostgreSQLのCOMMENT ONで意味をDBに残す

Claude Codeでカラム定義書を作る — PostgreSQLのCOMMENT ONで意味をDBに残す

DDLとアプリのコードから、Claude CodeにPostgreSQLのCOMMENT ON文を下書きさせる手順です。推測と確証を分けて出力させ、人がレビューして流し込みます。

カラム定義書をExcelで別管理すると、スキーマが変わるたびに古くなります。PostgreSQLの COMMENT ON COLUMN でデータベース自体に意味を書き込んでおけば、定義書はコメントから生成でき、psql からもその場で読めます。

その下書きを作る作業はClaude Codeに向いています。DDLとアプリのコードを突き合わせて「このカラムは何か」を文章にする仕事だからです。ただし、コードから読み取れる意味と、名前から推測しただけの意味は別物です。この記事では、2つを分けて出力させ、人が確証のある分だけを流し込む手順を組みます。

COMMENT ONで押さえる仕様

先にPostgreSQLの側の約束事を確認します。Claude Codeに任せる範囲は、この仕様から決まるためです。

仕様

COMMENT ONの動作

  • 1オブジェクトに1つだけ

    同じオブジェクトに再度 COMMENT を実行すると、既存のコメントは置き換わります。NULL か空文字列 '' を指定すると、コメントが消えます。

  • 書けるのは所有者

    多くのオブジェクトでは、コメントを設定できるのは所有者だけです。スーパーユーザーならどのオブジェクトにも設定できます。

  • ロックを取る

    対象オブジェクトに SHARE UPDATE EXCLUSIVE ロックを取ります。

  • 見る側に制限がない

    コメントの閲覧にはセキュリティ機構がありません。そのデータベースに接続できるユーザーなら、全オブジェクトのコメントが見えます。

カラムに付けるときの書式は次のとおりです。relation_name に指定できるのはテーブル、ビュー、複合型、外部テーブルです。

COMMENT ON COLUMN my_table.my_column IS 'Employee ID number';

読み出しには、psql の \d 系コマンドが使えます。SQLから取り出したいときは、同じ仕組みの組み込み関数 col_description があります。

SELECT a.attname,
       col_description(a.attrelid, a.attnum) AS comment
FROM pg_attribute a
WHERE a.attrelid = 'public.orders'::regclass
  AND a.attnum > 0
  AND NOT a.attisdropped
ORDER BY a.attnum;

この問い合わせの結果が、そのままカラム定義書の「説明」列になります。定義書を別のファイルで持つ必要はなく、Markdownの表やスプレッドシートはこの結果から書き出せます。

この仕様から、人が判断する点が3つ出ます。

  • 既存のコメントは置き換わるので、人が書いた説明を上書きしない
  • 誰でも読めるので、秘密にすべき情報を書かない
  • 所有者でないと実行できないので、流し込みは所有者のロールで人が行う

推測と確証を分ける考え方

LLMにカラムの説明を書かせると、どれも同じ丁寧さの文章で返ってきます。読み手には、コードで裏づけが取れた説明と、名前から連想しただけの説明が見分けられません。定義書として書き込まれた時点で、後者も事実として扱われます。

そこで出力を、根拠の強さで次の3区分に分けさせます。

区分根拠扱い
確証根拠列挙定数・バリデーション・CHECK制約・外部キーなど、コードやDDLに意味が明記されている扱い差分を確認して適用
推測根拠カラム名・型・使われ方から読み取った意味。コードに定義が見当たらない扱い担当者に確認してから適用
不明根拠手がかりがない。参照するコードがない扱いコメントを出さず、質問として返す

例えば、orders.status が smallint で、アプリ側に次の定義があるとします。

export const OrderStatus = {
  Received: 0,
  Shipped: 1,
  Completed: 2,
  Canceled: 3,
} as const;

このとき、status の意味は列挙定数から確証が取れます。一方、total_cents は名前と型から「最小通貨単位の合計金額」と推測できますが、税込かどうかはコードを読まない限り分かりません。この差を出力に残すのが目的です。

手順1: Skillに作業手順を固定する

毎回プロンプトで依頼を書き直すより、手順をSkillにしておくほうが出力の形が安定します。個人用なら ~/.claude/skills/<skill名>/SKILL.md、チームで使うならリポジトリの .claude/skills/<skill名>/SKILL.md に置きます。リポジトリに入れてコミットすれば、同じ手順を全員が使えます。

---
name: column-comments
description: PostgreSQLのDDLとアプリのコードを読み、カラムのCOMMENT ON文を根拠付きで下書きする。カラム定義書やデータ辞書を作るときに使う。
disable-model-invocation: true
allowed-tools: Read Grep
---
 
対象テーブルは呼び出し時の会話で指定される。
 
1. DDLを読み、対象テーブルの全カラムを列挙する。
2. 各カラム名でアプリのコードを検索し、列挙定数・
   バリデーション・外部キー・CHECK制約を探す。
3. 次の3区分に分けて、SQLファイルの下書きを書く。
   - 確証: コードかDDLに意味が明記されているもの
   - 推測: 名前や型からの推測。コメント先頭に[要確認]を付ける
   - 不明: COMMENT文は出さず、末尾に質問として並べる
4. すべての COMMENT ON 文の直前に、根拠のファイルと行を
   `-- 根拠:` で書く。
5. 既存コメントを上書きしないよう、DDLに COMMENT 文が
   既にあれば出力から除き、その旨を報告する。
6. 個人情報・認証情報・社内の機密を、コメント文に書かない。
7. データベースには接続しない。SQLを実行しない。

ポイントは3つあります。

disable-model-invocation: true は、Claudeが自分の判断でSkillを呼ばないようにする設定です。副作用のある作業やタイミングを自分で決めたい作業向けに使われる設定で、このSkillも人が /column-comments と打って起動します。

allowed-tools: Read Grep は、そのターンのあいだ、列挙したツールを承認なしで使えるようにします。リストに無いツールを禁止するものではないため、ファイルの書き出しなどは通常の権限設定に従い、確認が出ます。出力ファイルを作る前に一度確認が入るので、下書きの段階で人が目を通す機会になります。

手順7は、あくまでこのSkillの運用ルールです。SKILL.mdに書いたからといってツールが制限されるわけではありません。確実にSQLを実行させたくないなら、権限設定のdenyルールでデータベース接続コマンドを拒否します。

手順2: 下書きを出力させる

Skillを呼び、テーブルを指定します。

/column-comments orders テーブルを対象にしてください。
DDLは db/schema.sql、アプリのコードは src/ にあります。
出力は db/drafts/orders_comments.sql に書いてください。

出力の形は、例えば次のようになります(Skillの指示に沿った例示です。内容は対象のコードによって変わります)。

-- 区分: 確証
-- 根拠: src/domain/order.ts の OrderStatus
COMMENT ON COLUMN public.orders.status IS
  '注文状態。0=受付、1=出荷済み、2=完了、3=キャンセル';
 
-- 区分: 推測
-- 根拠: カラム名と型(integer)のみ。税込か税抜かはコードに記述なし
COMMENT ON COLUMN public.orders.total_cents IS
  '[要確認] 注文合計金額(最小通貨単位)。税込か税抜かは未確認';
 
-- 質問(区分: 不明)
-- ship_flag (char(1)): 'Y' 以外にどの値が入るか、参照するコードが見つからない

「推測」の行に [要確認] を付けておくと、あとから col_description で抜き出せます。適用後に確認が残っているカラムを一覧にする、といった使い方ができます。

手順3: 人がレビューして適用する

下書きは次の順で確認します。

  1. 「推測」の行を担当者に回し、確認が取れたものは [要確認] を外して「確証」にする
  2. 「不明」の質問に答えを入れ、COMMENT文を足す
  3. 文面に機密情報・個人情報が入っていないかを読む
  4. 既存のコメントを置き換えて良いかを、現在のコメントと見比べて確認する

手順4は、適用前に現在値を取り出せば比べられます。上で示した col_description の問い合わせを、適用前と後に実行して差分を見ます。

適用は、所有者のロールで psql から行います。トランザクションに包んでおけば、内容に不満があればロールバックできます。

psql "$DATABASE_URL" --single-transaction \
  -v ON_ERROR_STOP=1 -f db/drafts/orders_comments.sql

--single-transaction は、-f で渡したファイルの前後に BEGIN と COMMIT を送ります。ただしエラー時に ROLLBACK へ切り替わるのは、変数 ON_ERROR_STOP を設定している場合です。上のコマンドは両方を指定しているので、途中で失敗したら、そのファイルのコメントは1行も反映されません。ON_ERROR_STOP を付け忘れると、失敗した文だけが飛ばされたまま残りが確定する可能性があります。

流し込んだあとに、col_description で意図どおりの文字列になっているかを確かめます。コメントを消したくなった場合は、対象のオブジェクトに IS NULL を指定します。

COMMENT ON COLUMN public.orders.ship_flag IS NULL;

テーブルやビューにも付けて、定義書として書き出す

カラムだけでなく、テーブル・ビュー・スキーマにも同じ構文でコメントを付けられます。カラム定義書の見出しに当たる「このテーブルは何を表すか」は、テーブルのコメントに置くと一緒に管理できます。

COMMENT ON TABLE my_schema.my_table IS 'Employee Information';
COMMENT ON VIEW my_view IS 'View of departmental costs';
COMMENT ON SCHEMA my_schema IS 'Departmental data';

Skillの手順に「テーブルの用途を1行で、根拠付きで書く」を加えるだけで、Claude Codeは COMMENT ON TABLE も同じ形式で下書きします。ビューは、元になるテーブルのカラムとは別オブジェクトです。ビューのカラムにも COMMENT ON COLUMN が必要になる点に注意してください。

コメントが入ったら、定義書はクエリで書き出せます。型と必須かどうかも同じ結果に並べると、そのままMarkdownの表やスプレッドシートに貼れます。

SELECT a.attnum                          AS no,
       a.attname                         AS column_name,
       format_type(a.atttypid, a.atttypmod) AS data_type,
       a.attnotnull                      AS not_null,
       col_description(a.attrelid, a.attnum) AS description
FROM pg_attribute a
WHERE a.attrelid = 'public.orders'::regclass
  AND a.attnum > 0
  AND NOT a.attisdropped
ORDER BY a.attnum;

説明の列が空のカラムは、コメントが未整備の一覧になります。ここをClaude Codeへの次の依頼材料にすれば、「不明」として返ってきた質問と合わせて、整備が進んだ割合を追えます。

推測させてはいけない情報

「確証」に入れる条件を厳しくしておくほど、定義書への信頼は保てます。次のような情報は、名前や型から推測できても確証にはなりません。

  • 数値の単位(円か銭か、秒かミリ秒か)
  • フラグ値の全種類(コードに現れない値が、過去のデータに残っていることがあります)
  • 税込・税抜、UTC・日本時間のような、解釈が分かれる前提
  • 論理削除や履歴管理など、アプリの運用ルールに依存する意味

これらは、コードに明記されているか、データを実際に見て確かめられたときだけ「確証」に格上げします。データを見る作業は、Claude Codeではなく担当者が読み取り専用のロールで行うのが安全です。

実運用の落とし穴

落とし穴

再実行すると人が直したコメントが消える

コメントは1オブジェクトに1つで、再実行すれば置き換わります。Claude Codeに下書きを何度も作らせ、そのまま流し込むと、手で直した説明が元に戻ります。適用前に現在のコメントを出力し、置き換えてよいものだけを残してください。

もうひとつの落とし穴は、権限です。流し込む対象のオブジェクトの所有者でないと、COMMENT ON は失敗します。アプリ用のロールが所有者でない環境では、マイグレーション用のロールで実行します。

コメントを書くカラムが多いときは、1テーブルずつ依頼するほうが安全です。出力が長くなるほど、確証と推測の区分が混ざる確率が上がります。レビューする側の負担もそのぶん増えます。

運用に乗せるには

コメントの整備は一度やって終わりではなく、新しいカラムを足すたびに必要になります。マイグレーションのレビュー時に「COMMENT ONが付いているか」を見るルールにすると、定義書の更新漏れが減ります。

Claude Codeに新しいマイグレーションを書かせるときも、同じ観点を渡せます。プロジェクトの CLAUDE.md に次のような1行を足しておく方法があります。

- 新しいカラムを追加するマイグレーションには、
  COMMENT ON COLUMN を同じファイルに含める。
  意味が不明なカラムは、コメントを推測で書かず質問する。

データベースに直接つないで作業させたい場合は、接続方法ごとの手順が別にあります。Cloud SQL for PostgreSQLプラグインやPrisma Postgres MCPでは、Claude Codeがスキーマを読み、SQLを実行するところまで進められます。ただし、そこまで権限を渡すと、コメントの上書きもClaude Code自身が実行できてしまいます。下書きの段階では、DDLファイルとコードだけを読ませる構成のほうが、適用前に人の目を通しやすくなります。

Skillの書き方そのものは、Claude Code Skillsのfrontmatter全フィールドとSKILL.mdの書き方にまとめています。データカタログ側で意味を管理する選択肢もあり、その場合はDataHubプラグインが手がかりになります。

まとめ

COMMENT ON COLUMN は、カラムの意味をデータベースの中に残す標準的な手段です。Claude Codeは下書きを作る役、人は確証のある分だけを適用する役、と分けると、定義書がコードと食い違う事態を避けられます。

この方法の核は、出力を「確証」「推測」「不明」に分けさせることです。コメントは誰にでも読めて、再実行すれば置き換わる性質があります。だからこそ、適用前のレビューを1段挟むと安全です。まずは更新頻度の高いテーブル1つで試し、レビューにかかる時間を見てから範囲を広げると進めやすくなります。

参照した一次ソース

この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。

  1. postgresql.org/docs/current/sql-comment.html
  2. code.claude.com/docs/en/skills
この記事を共有:XはてブLinkedIn