カテゴリ: PostgreSQL 更新日: 2026/02/21

PostgreSQLスキーマ作成・削除完全ガイド!初心者でもわかるデータベース設計の基礎

PostgreSQLのスキーマを作成・削除する方法
PostgreSQLのスキーマを作成・削除する方法

先生と生徒の会話形式で理解しよう

生徒

「PostgreSQLでスキーマって言葉を聞いたんですけど、これって何ですか?」

先生

「スキーマは、データベースの中をさらに区切るための仕組みです。大きな本棚の中に、ジャンル別の仕切りを作るようなものですね。」

生徒

「データベースだけじゃダメなんですか?なぜスキーマが必要なんでしょう?」

先生

「データベースが会社の建物だとすれば、スキーマは各部署のようなものです。営業部、経理部、人事部と分けることで、データを整理しやすくなります。」

PostgreSQLのスキーマとは何か?

<i class= PostgreSQLのスキーマとは何か?" onerror="this.onerror=null; this.src='/img/view/java-exception-introduce.jpg';">
PostgreSQLのスキーマとは何か?

スキーマとは、データベース内でテーブルやビュー、関数などのオブジェクトをグループ化して管理するための名前空間のことです。名前空間という言葉は難しく聞こえますが、要するに「名前が重複しないように区切られた領域」という意味です。

例えば、会社のシステムを考えてみましょう。営業部門にも経理部門にも「売上」というテーブルが必要かもしれません。スキーマを使わないと、同じデータベース内に同じ名前のテーブルを二つ作ることはできません。しかし、「営業スキーマ」と「経理スキーマ」を作れば、それぞれに「売上」テーブルを持つことができます。

PostgreSQLでは、データベースを作成すると、デフォルトで「public」という名前のスキーマが自動的に作成されます。何も指定しない場合、テーブルなどはこのpublicスキーマに作成されます。つまり、今までスキーマを意識していなくても、実は自動的にpublicスキーマを使っていたのです。

スキーマを使うメリットと活用場面

<i class= スキーマを使うメリットと活用場面" onerror="this.onerror=null; this.src='/img/view/java-exception-introduce.jpg';">
スキーマを使うメリットと活用場面

スキーマを使うことで、データベース管理に様々なメリットが生まれます。実際の運用でどのように活用されるのか見ていきましょう。

データの論理的な整理

大規模なシステムでは、数百個ものテーブルが存在することがあります。これらすべてを一つのスキーマにまとめると、管理が非常に困難になります。スキーマで分類することで、どこに何があるか分かりやすくなります。

例えば、ショッピングサイトのデータベースなら、「商品管理用スキーマ」「顧客管理用スキーマ」「注文管理用スキーマ」のように分けることができます。

セキュリティとアクセス制御

スキーマ単位で権限を設定できるため、セキュリティ管理が簡単になります。営業部のユーザーには営業スキーマへのアクセスだけを許可し、給与情報を含む人事スキーマへのアクセスは人事部だけに制限する、といった制御が可能です。

複数チームでの開発

大きなプロジェクトでは、複数のチームが同時に開発を進めることがあります。各チームに専用のスキーマを割り当てることで、お互いのテーブル名が衝突する心配がなくなります。開発スキーマとテストスキーマを分けて、本番に影響を与えずに開発を進めることもできます。

基本的なスキーマ作成方法

<i class= 基本的なスキーマ作成方法" onerror="this.onerror=null; this.src='/img/view/java-exception-introduce.jpg';">
基本的なスキーマ作成方法

それでは、実際にスキーマを作成してみましょう。スキーマの作成はCREATE SCHEMAコマンドを使います。構文は非常にシンプルです。

基本的なスキーマ作成の例

CREATE SCHEMA sales;

このコマンドで、「sales」という名前のスキーマが作成されます。CREATE SCHEMAの後ろに、作成したいスキーマの名前を指定するだけです。

スキーマ作成の確認方法

スキーマが正しく作成されたか確認するには、psqlコマンドラインツールで「\dn」というコマンドを使います。これはデータベース内の全スキーマを一覧表示するコマンドです。

スキーマ一覧の表示例

  List of schemas
  Name   |  Owner   
---------+----------
 public  | postgres
 sales   | postgres

このように、デフォルトのpublicスキーマと、今作成したsalesスキーマが表示されます。Ownerの欄には、そのスキーマを作成したユーザー名が表示されます。

所有者を指定したスキーマ作成

スキーマを作成する際に、特定のユーザーを所有者として指定することもできます。所有者は、そのスキーマ内のオブジェクトを自由に操作できます。

所有者を指定したスキーマ作成例

CREATE SCHEMA accounting AUTHORIZATION accounting_user;

このコマンドは、「accounting」という名前のスキーマを作成し、その所有者を「accounting_user」に設定します。AUTHORIZATIONキーワードの後に、所有者にしたいユーザー名を指定します。

スキーマ内にテーブルを作成する方法

<i class= スキーマ内にテーブルを作成する方法" onerror="this.onerror=null; this.src='/img/view/java-exception-introduce.jpg';">
スキーマ内にテーブルを作成する方法

スキーマを作成したら、その中にテーブルを作ってみましょう。スキーマを指定してテーブルを作成するには、テーブル名の前にスキーマ名を付けます。

スキーマを指定したテーブル作成例

CREATE TABLE sales.customers (
    customer_id SERIAL PRIMARY KEY,
    name VARCHAR(100),
    email VARCHAR(100),
    registration_date DATE
);

この例では、salesスキーマの中に「customers」テーブルを作成しています。「sales.customers」のように、スキーマ名とテーブル名をドット(.)で繋いで指定します。これを「完全修飾名」といいます。

スキーマ内のテーブルにデータを挿入

作成したテーブルにデータを挿入する際も、同じように完全修飾名を使います。

スキーマ指定でのデータ挿入例

INSERT INTO sales.customers (name, email, registration_date)
VALUES 
    ('山田太郎', 'yamada@example.com', '2025-01-15'),
    ('佐藤花子', 'sato@example.com', '2025-01-16'),
    ('鈴木一郎', 'suzuki@example.com', '2025-01-17');
データ挿入後のテーブル内容

customer_id | name       | email                | registration_date
------------+------------+----------------------+------------------
1           | 山田太郎   | yamada@example.com   | 2025-01-15
2           | 佐藤花子   | sato@example.com     | 2025-01-16
3           | 鈴木一郎   | suzuki@example.com   | 2025-01-17

スキーマ内のデータを検索

データを検索する際も、完全修飾名を使ってスキーマを指定します。

スキーマ指定での検索例

SELECT * FROM sales.customers WHERE registration_date >= '2025-01-16';
検索結果

customer_id | name       | email                | registration_date
------------+------------+----------------------+------------------
2           | 佐藤花子   | sato@example.com     | 2025-01-16
3           | 鈴木一郎   | suzuki@example.com   | 2025-01-17

検索パスの設定と活用

<i class= 検索パスの設定と活用" onerror="this.onerror=null; this.src='/img/view/java-exception-introduce.jpg';">
検索パスの設定と活用

毎回「スキーマ名.テーブル名」と入力するのは面倒です。そこで、検索パス(search_path)という機能を使って、デフォルトで使用するスキーマを設定できます。

現在の検索パスを確認

現在設定されている検索パスは、次のコマンドで確認できます。

検索パス確認コマンド

SHOW search_path;
検索パス表示例

   search_path   
-----------------
 "$user", public

デフォルトでは、ユーザー名と同じスキーマ、そしてpublicスキーマの順で検索されます。

検索パスの変更方法

検索パスを変更することで、スキーマ名を省略してテーブルにアクセスできるようになります。

検索パス変更の例

SET search_path TO sales, public;

このコマンドを実行すると、まずsalesスキーマを検索し、見つからなければpublicスキーマを検索するようになります。これで「sales.customers」を単に「customers」と書くだけでアクセスできます。

セッション単位とユーザー単位の設定

SET search_pathで変更した設定は、現在のセッション(接続)でのみ有効です。接続を切ると元に戻ります。ユーザー単位で永続的に設定したい場合は、ALTER USERコマンドを使います。

ユーザーのデフォルト検索パス設定例

ALTER USER sales_user SET search_path TO sales, public;

これで、sales_userでログインするたびに、自動的にsalesスキーマが優先的に検索されるようになります。

スキーマの削除方法

<i class= スキーマの削除方法" onerror="this.onerror=null; this.src='/img/view/java-exception-introduce.jpg';">
スキーマの削除方法

不要になったスキーマを削除するには、DROP SCHEMAコマンドを使います。ただし、削除には注意が必要です。

空のスキーマを削除

スキーマ内にテーブルなどのオブジェクトが何も存在しない場合は、単純にDROP SCHEMAコマンドで削除できます。

空のスキーマ削除例

DROP SCHEMA sales;

このコマンドで、salesスキーマが削除されます。ただし、スキーマ内にテーブルやビューなどが残っている場合は、エラーになります。

オブジェクトごと削除

スキーマ内のテーブルなども含めて、すべてまとめて削除したい場合は、CASCADEオプションを使います。これは非常に強力なコマンドなので、実行前に十分確認してください。

警告:CASCADE使用時は要注意
スキーマとその中身をすべて削除する例

DROP SCHEMA sales CASCADE;

CASCADEを付けると、スキーマ内のすべてのテーブル、ビュー、関数などが削除されます。データも完全に消えてしまうので、本番環境では特に慎重に実行してください。削除する前に、必ずバックアップを取ることをお勧めします。

安全な削除方法

IF EXISTSオプションを付けると、スキーマが存在しない場合でもエラーにならず、警告だけが表示されます。スクリプトで自動化する際に便利です。

存在確認付き削除の例

DROP SCHEMA IF EXISTS temp_schema CASCADE;

このコマンドは、temp_schemaが存在すれば削除し、存在しなければ何もしません。エラーで処理が止まることがないため、安全です。

スキーマの名前変更とその他の操作

<i class= スキーマの名前変更とその他の操作" onerror="this.onerror=null; this.src='/img/view/java-exception-introduce.jpg';">
スキーマの名前変更とその他の操作

作成したスキーマの設定を後から変更することもできます。

スキーマ名の変更

スキーマの名前を変更するには、ALTER SCHEMAコマンドを使います。

スキーマ名変更の例

ALTER SCHEMA sales RENAME TO sales_department;

このコマンドで、salesスキーマの名前がsales_departmentに変更されます。スキーマ内のテーブルはそのまま残り、アクセスする際は新しいスキーマ名を使います。

スキーマの所有者変更

スキーマの所有者を別のユーザーに変更することもできます。

所有者変更の例

ALTER SCHEMA accounting OWNER TO new_accounting_manager;

このコマンドで、accountingスキーマの所有者がnew_accounting_managerに変更されます。所有者には、そのスキーマ内のオブジェクトを管理する権限があります。

スキーマとアクセス権限の管理

<i class= スキーマとアクセス権限の管理" onerror="this.onerror=null; this.src='/img/view/java-exception-introduce.jpg';">
スキーマとアクセス権限の管理

スキーマには、ユーザーごとに異なるアクセス権限を設定できます。これにより、セキュアなデータベース運用が可能になります。

スキーマの使用権限を付与

他のユーザーにスキーマを使用させるには、USAGE権限を付与します。

スキーマ使用権限の付与例

GRANT USAGE ON SCHEMA sales TO sales_user;

USAGE権限を持つユーザーは、そのスキーマ内のオブジェクトにアクセスできるようになります。ただし、テーブルへのアクセス権限は別途必要です。

スキーマ内のオブジェクト作成権限

スキーマ内に新しいテーブルなどを作成する権限は、CREATE権限で管理します。

オブジェクト作成権限の付与例

GRANT CREATE ON SCHEMA sales TO developer_user;

この権限を持つユーザーは、salesスキーマ内に自由にテーブルやビューを作成できます。

権限の取り消し

付与した権限を取り消すには、REVOKEコマンドを使います。

権限取り消しの例

REVOKE CREATE ON SCHEMA sales FROM developer_user;

このコマンドで、developer_userからsalesスキーマ内でのオブジェクト作成権限が取り消されます。

実践的なスキーマ設計例

<i class= 実践的なスキーマ設計例" onerror="this.onerror=null; this.src='/img/view/java-exception-introduce.jpg';">
実践的なスキーマ設計例

実際のプロジェクトでは、どのようにスキーマを設計すればよいのか、具体例を見ていきましょう。

部門別スキーマ構成

大企業のシステムでは、部門ごとにスキーマを分けると管理しやすくなります。

部門別スキーマ設計例
  • sales:営業部門(顧客情報、商談履歴、売上データ)
  • accounting:経理部門(会計データ、請求書、支払情報)
  • hr:人事部門(社員情報、給与、勤怠データ)
  • inventory:在庫管理部門(商品在庫、入出庫履歴)

環境別スキーマ構成

開発環境、テスト環境、本番環境でスキーマを分ける方法もあります。

環境別スキーマ設計例
  • dev:開発用スキーマ(自由に実験できる)
  • test:テスト用スキーマ(品質確認用)
  • prod:本番用スキーマ(実際の運用データ)

この構成では、同じデータベース内で異なる環境を管理できるため、データベースサーバーの数を減らせます。ただし、本番データと開発データが混在するリスクもあるため、権限管理は厳重に行う必要があります。

よくあるトラブルと解決方法

<i class= よくあるトラブルと解決方法" onerror="this.onerror=null; this.src='/img/view/java-exception-introduce.jpg';">
よくあるトラブルと解決方法
スキーマを作成したのにテーブルが作れない

スキーマは作成できても、その中にテーブルを作る権限がない場合があります。CREATE権限が必要です。スキーマの所有者であれば自動的に権限がありますが、他のユーザーの場合はGRANT CREATE ON SCHEMAで権限を付与してもらう必要があります。

スキーマを削除しようとするとエラーが出る

スキーマ内にテーブルなどのオブジェクトが残っている場合、通常のDROP SCHEMAでは削除できません。すべて削除したい場合はCASCADEオプションを付けてください。ただし、データも完全に消えるので注意が必要です。

テーブルにアクセスできない

スキーマへのUSAGE権限とテーブルへのSELECT権限の両方が必要です。どちらか一方だけではアクセスできません。また、検索パスにそのスキーマが含まれていない場合は、完全修飾名(スキーマ名.テーブル名)で指定する必要があります。

publicスキーマは削除できますか?

技術的には削除できますが、推奨されません。publicスキーマは多くのアプリケーションがデフォルトで使用することを前提にしているため、削除すると

カテゴリの一覧へ
新着記事
New1
MySQL
MySQLのWHERE句でNOT条件を指定する方法を徹底解説!初心者向けSQL条件検索ガイド
New2
PostgreSQL
PostgreSQLのLIMIT・OFFSETとパフォーマンス問題を完全解説|初心者でもわかる安全な使い方
New3
MySQL
MySQLのUPDATE文でデータを更新する基本を徹底解説|SQL初心者でもわかるデータベース更新入門
New4
PostgreSQL
PostgreSQLのOFFSET完全入門|並び替えと組み合わせてデータをスキップする方法を初心者向けに解説
人気記事
No.1
Java&Spring記事人気No1
PostgreSQL
PostgreSQLのDISTINCT完全ガイド|SQLで重複データを除外する方法を初心者向けに解説
No.2
Java&Spring記事人気No2
PostgreSQL
PostgreSQLの主キー・外部キーを完全解説!初心者でもわかる設定方法と考え方
No.3
Java&Spring記事人気No3
PostgreSQL
PostgreSQLとは?初心者向けに特徴をわかりやすく解説
No.4
Java&Spring記事人気No4
PostgreSQL
PostgreSQLのLEFT JOIN完全入門!不足データを補いながらテーブル結合する仕組みをやさしく解説
No.5
Java&Spring記事人気No5
PostgreSQL
PostgreSQLのUPDATE文の使い方(部分更新・条件更新)
No.6
Java&Spring記事人気No6
PostgreSQL
PostgreSQLスキーマ設計のベストプラクティス完全ガイド|初心者でもわかるデータベース整理術
No.7
Java&Spring記事人気No7
PostgreSQL
PostgreSQLスキーマ作成・削除完全ガイド!初心者でもわかるデータベース設計の基礎
No.8
Java&Spring記事人気No8
PostgreSQL
PostgreSQLの権限管理を完全解説|スキーマ単位で理解するデータベースセキュリティの基礎