【Oracle】スキーマとは何か・作成から活用まで完全ガイド|他RDBMS比較・クロススキーマアクセス・SYNONYM・CURRENT_SCHEMAまで解説

【Oracle】スキーマとは何か・作成から活用まで完全ガイド|他RDBMS比較・クロススキーマアクセス・SYNONYM・CURRENT_SCHEMAまで解説 Oracle

「Oracle でスキーマを作るには?」と調べると、CREATE USER で作れると書いてあって戸惑う方は多いと思います。MySQL や PostgreSQL では CREATE SCHEMACREATE DATABASE でスキーマを作りますが、Oracle ではユーザーを作ることがそのままスキーマを作ることになります

Oracle のスキーマはほかの RDBMS と概念が異なるため、「スキーマとユーザーがなぜ同じなのか」を理解しないまま設計すると、接続用ユーザーが誤ってアプリのオブジェクトを全部所有してしまったり、スキーマ間アクセスの権限設定を間違えてセキュリティリスクが生じたりします。

この記事では、Oracle のスキーマの概念を他の RDBMS との比較で整理したうえで、スキーマの作成・クロススキーマアクセス・シノニム・CURRENT_SCHEMA の切り替え・オブジェクト確認・削除・実践的な設計パターンまで解説します。

この記事でわかること
・Oracle のスキーマとは何か(MySQL/PostgreSQL/SQL Server との概念の違い)
・Oracle でスキーマ = ユーザーになっている理由
・CREATE USER でスキーマを作る基本手順(詳細は 1921 へリンク)
・CREATE SCHEMA AUTHORIZATION の正しい用途と制限
・スキーマ間アクセス(schema.object 表記・GRANT・SYNONYM)
・CURRENT_SCHEMA でデフォルトスキーマを切り替える方法
・USER_OBJECTS / DBA_OBJECTS でスキーマのオブジェクトを確認する方法
・スキーマ(ユーザー)の削除:DROP USER CASCADE
・実践的なスキーマ設計パターン
スポンサーリンク

Oracle のスキーマと他 RDBMS の違い

「スキーマ」という言葉は RDBMS によって指す概念が大きく異なります。まず全体像を整理しましょう。

RDBMS スキーマの概念 作成コマンド 1 アカウントで複数スキーマを持てるか
Oracle スキーマ = ユーザーが所有するオブジェクトの集合。ユーザーと 1 対 1 で対応する CREATE USER(スキーマは自動生成) × 1 ユーザー = 1 スキーマ固定
MySQL スキーマ ≒ データベース。CREATE SCHEMA と CREATE DATABASE は同義 CREATE DATABASE / CREATE SCHEMA ○ 1 ユーザーが複数の DB(スキーマ)にアクセス可能
PostgreSQL スキーマはデータベース内の名前空間。1 データベースに複数のスキーマを持てる CREATE SCHEMA ○ 1 ユーザーが複数のスキーマを所有・利用可能
SQL Server スキーマはデータベース内の名前空間(PostgreSQL に近い概念) CREATE SCHEMA ○ 1 ユーザーが複数のスキーマを所有可能
Oracle の特徴:ユーザーとスキーマは 1 対 1
Oracle では CREATE USER hr IDENTIFIED BY password; を実行した瞬間に、同名の「HR スキーマ」が自動的に作られます。HR ユーザーが作成したすべてのオブジェクト(テーブル・インデックスなど)は自動的に HR スキーマに属します。
逆に言うと、スキーマだけを独立して作ることはできません。スキーマを作る = ユーザーを作る、という理解が Oracle では正確です。

スキーマ(ユーザー)の作成:CREATE USER

Oracle でスキーマを作るには CREATE USER 文を実行します。ユーザーを作ると、同名のスキーマが自動的に使用可能になります。

SQL(最小構成:ユーザー=スキーマを作成)
-- ユーザーを作成すると同名のスキーマが自動生成される
CREATE USER app_schema IDENTIFIED BY "SecurePass#2024"
    DEFAULT TABLESPACE app_data      -- オブジェクトを格納する表領域
    TEMPORARY TABLESPACE temp        -- ソート作業領域
    QUOTA UNLIMITED ON app_data;     -- 表領域の使用上限(UNLIMITED = 無制限)

-- 接続するには CREATE SESSION 権限が必要
GRANT CREATE SESSION TO app_schema;

-- アプリのオブジェクトを作る権限を付与
GRANT CREATE TABLE, CREATE INDEX, CREATE VIEW, CREATE SEQUENCE,
      CREATE PROCEDURE, CREATE TRIGGER TO app_schema;
CREATE USER の全構文(プロファイル指定・パスワードポリシー・ALTER USER・DROP USER・ロールの付与など)については【Oracle】新規ユーザー作成と権限付与の完全ガイドを参照してください。

CREATE SCHEMA AUTHORIZATION:原子的なオブジェクト作成

Oracle には CREATE SCHEMA AUTHORIZATION という構文があります。これは「新しいスキーマを作る」コマンドではなく、既存のスキーマ内に複数のオブジェクト(テーブル・ビュー)と権限付与を1 トランザクションで原子的に実行するための構文です。

SQL(CREATE SCHEMA AUTHORIZATION の構文)
-- CREATE SCHEMA AUTHORIZATION は「新スキーマ作成」ではない
-- 自分のスキーマ(HR)内にテーブル・ビューを一括で作成し、権限も付与する
-- HR ユーザーとして実行する例
CREATE SCHEMA AUTHORIZATION hr
    CREATE TABLE departments (
        dept_id   NUMBER PRIMARY KEY,
        dept_name VARCHAR2(100) NOT NULL
    )
    CREATE TABLE employees (
        emp_id   NUMBER PRIMARY KEY,
        emp_name VARCHAR2(100),
        dept_id  NUMBER REFERENCES departments(dept_id)
    )
    CREATE VIEW emp_dept_view AS
        SELECT e.emp_name, d.dept_name
        FROM   employees e JOIN departments d ON e.dept_id = d.dept_id
    GRANT SELECT ON departments TO scott;
CREATE SCHEMA AUTHORIZATION の制限事項
AUTHORIZATION の後に指定できるスキーマ名は自分自身のユーザー名のみです。他のユーザーのスキーマに作成することはできません。
② 作成できるのは TABLE・VIEW・GRANT のみです(INDEX・SEQUENCE・PROCEDURE 等は含められない)。
③ ブロック内のいずれかの文が失敗すると、ブロック全体がロールバックされます(原子性の保証)。
④ 実際の開発現場では個別の DDL を順番に実行する方が多く、この構文の使用頻度は低いです。

スキーマ間アクセス:他スキーマのオブジェクトを参照する

Oracle では スキーマ名.オブジェクト名 の形式で他スキーマのオブジェクトを参照できます。ただし、参照するには適切な権限が必要です。

スキーマ間アクセスの権限付与

SQL(スキーマ間アクセスの権限付与と参照)
-- HR スキーマの employees テーブルを SCOTT スキーマから参照する例

-- Step 1: HR ユーザーが SCOTT に SELECT 権限を付与
GRANT SELECT ON hr.employees TO scott;

-- Step 2: SCOTT ユーザーからスキーマ名付きで参照
SELECT emp_id, emp_name
FROM   hr.employees   -- スキーマ名.テーブル名 で他スキーマを参照
WHERE  dept_id = 10;

-- あるスキーマのすべてのテーブルへの SELECT を一括付与(DBA が実行)
BEGIN
    FOR t IN (SELECT table_name FROM dba_tables WHERE owner = 'HR') LOOP
        EXECUTE IMMEDIATE 'GRANT SELECT ON hr.' || t.table_name || ' TO scott';
    END LOOP;
END;
/
付与できるオブジェクト権限 対象 説明
SELECT テーブル・ビュー・シーケンス 参照のみ許可
INSERT / UPDATE / DELETE テーブル・ビュー 変更操作を許可
EXECUTE プロシージャ・関数・パッケージ 実行を許可
REFERENCES テーブル(特定列) 外部キー制約の参照先として使用する権限
ALL 対象オブジェクト全体 上記すべての権限を一括付与

WITH GRANT OPTION:権限の委譲

SQL(WITH GRANT OPTION で権限を委譲可能にする)
-- SCOTT が受け取った権限をさらに別のユーザーに付与できるようにする
GRANT SELECT ON hr.employees TO scott WITH GRANT OPTION;

-- SCOTT は受け取った権限を JONES にも付与できる
-- (SCOTT として実行)
GRANT SELECT ON hr.employees TO jones;

シノニム(SYNONYM):スキーマ名を意識せずにアクセスする

毎回 hr.employees とスキーマ名を付けて書くのは面倒です。シノニム(別名)を作成すると、スキーマ名なしでアクセスできるようになります。アプリケーションのコードをスキーマ名から独立させる効果もあります。

プライベートシノニム vs パブリックシノニム

種類 範囲 作成構文 作成権限 用途
プライベートシノニム 作成したユーザーのみ参照可能 CREATE SYNONYM CREATE SYNONYM 権限 特定ユーザーの開発作業の簡略化
パブリックシノニム すべてのユーザーが参照可能 CREATE PUBLIC SYNONYM CREATE PUBLIC SYNONYM 権限(DBA) 全ユーザーが共用するオブジェクトの共有(DUAL テーブルもパブリックシノニム)
SQL(シノニムの作成・使用・削除)
-- プライベートシノニム:SCOTT が HR.EMPLOYEES を「EMPLOYEES」として参照
CREATE SYNONYM employees FOR hr.employees;

-- シノニムを使ってスキーマ名なしでアクセス
SELECT emp_id, emp_name FROM employees;   -- hr.employees と同じ

-- パブリックシノニム(DBA が作成、すべてのユーザーが参照可能)
CREATE PUBLIC SYNONYM pub_employees FOR hr.employees;

-- シノニムの削除
DROP SYNONYM employees;
DROP PUBLIC SYNONYM pub_employees;

-- 存在するシノニムを確認
SELECT synonym_name, table_owner, table_name FROM user_synonyms ORDER BY synonym_name;
SELECT synonym_name, table_owner, table_name FROM all_synonyms WHERE owner = 'PUBLIC' AND table_owner = 'HR';
パブリックシノニムの注意点
パブリックシノニムはすべてのユーザーが参照できますが、参照するには対象オブジェクトへのアクセス権限が依然として必要です。シノニムはあくまで「名前の別名」であり、アクセス制御には使えません。
また、パブリックシノニムと同名のプライベートシノニム・テーブルが存在する場合、プライベートシノニム → テーブル → パブリックシノニムの順で優先されます。

CURRENT_SCHEMA:デフォルトスキーマを切り替える

Oracle では ALTER SESSION SET CURRENT_SCHEMA を使うと、SQL 内でスキーマ名を省略したときに参照するデフォルトスキーマを変更できます。ログイン中のユーザーは変わらないため、権限もそのままです。

SQL(CURRENT_SCHEMA の切り替えと確認)
-- 現在のスキーマを確認
SELECT SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA') FROM dual;

-- CURRENT_SCHEMA を HR スキーマに切り替える
ALTER SESSION SET CURRENT_SCHEMA = hr;

-- これ以降、スキーマ名を省略すると HR スキーマが参照される
SELECT * FROM employees;    -- hr.employees として解釈される
SELECT * FROM departments;  -- hr.departments として解釈される

-- 元のスキーマに戻す(自分のユーザー名を指定)
ALTER SESSION SET CURRENT_SCHEMA = scott;
CURRENT_SCHEMA の主な用途
① テスト・開発環境で別スキーマのオブジェクトを頻繁に参照する場合
② アプリケーションスキーマ分離パターン(後述)で、接続ユーザーがアプリスキーマのオブジェクトをスキーマ名なしで参照するログオントリガーに使う
③ Data Pump インポート時のスキーマ名変換
CURRENT_SCHEMA を変更してもログインユーザーは変わらないため、CURRENT_USER とは別物であることに注意してください。

スキーマ内のオブジェクトを確認する

USER_OBJECTS / ALL_OBJECTS / DBA_OBJECTS

ビュー名 参照範囲 主な用途
USER_OBJECTS 自分のスキーマのオブジェクトのみ 自分のスキーマの確認(DBA 権限不要)
ALL_OBJECTS 自分がアクセス権限を持つすべてのオブジェクト 他スキーマの参照可能オブジェクトを確認
DBA_OBJECTS データベース内のすべてのオブジェクト DBA がスキーマ横断で全オブジェクトを確認
SQL(スキーマ内のオブジェクト一覧を確認)
-- 自分のスキーマのオブジェクト一覧(種別・状態含む)
SELECT object_name,
       object_type,
       status,         -- VALID / INVALID
       created,
       last_ddl_time
FROM   user_objects
ORDER  BY object_type, object_name;

-- 種別ごとのオブジェクト数を集計
SELECT object_type, COUNT(*) AS cnt
FROM   user_objects
GROUP  BY object_type
ORDER  BY cnt DESC;
SQL(DBA_OBJECTS:特定スキーマのオブジェクトを DBA が確認)
-- HR スキーマのすべてのオブジェクトを確認
SELECT object_name, object_type, status, last_ddl_time
FROM   dba_objects
WHERE  owner = 'HR'
ORDER  BY object_type, object_name;

-- INVALID になっているオブジェクトを全スキーマから抽出
SELECT owner, object_name, object_type, last_ddl_time
FROM   dba_objects
WHERE  status = 'INVALID'
ORDER  BY owner, object_type;

スキーマの使用容量を確認する

SQL(DBA_SEGMENTS:スキーマごとの使用容量を確認)
-- スキーマごとの合計使用容量(MB)
SELECT owner,
       COUNT(*)                              AS segment_count,
       ROUND(SUM(bytes) / 1024 / 1024, 1)   AS total_mb
FROM   dba_segments
GROUP  BY owner
ORDER  BY total_mb DESC
FETCH  FIRST 20 ROWS ONLY;

-- 特定スキーマの種別ごとの使用容量
SELECT segment_type, ROUND(SUM(bytes) / 1024 / 1024, 1) AS mb
FROM   dba_segments
WHERE  owner = 'HR'
GROUP  BY segment_type
ORDER  BY mb DESC;

スキーマの削除:DROP USER CASCADE

スキーマ(ユーザー)を削除するには DROP USER 文を使います。スキーマ内にオブジェクトが存在する場合は CASCADE オプションが必要です。

SQL(スキーマの削除パターン)
-- パターン①: スキーマにオブジェクトがない場合
DROP USER app_schema;
-- → スキーマにテーブル等が残っているとエラー(ORA-01922: CASCADE must be specified)

-- パターン②: スキーマとその中のすべてのオブジェクトを削除(CASCADE)
DROP USER app_schema CASCADE;
-- → テーブル・インデックス・ビュー・プロシージャなどをすべて削除
-- → 他スキーマから参照している外部キー制約も自動的に削除される

-- 削除前に格納オブジェクト数を確認
SELECT COUNT(*) FROM dba_objects WHERE owner = 'APP_SCHEMA';
DROP USER CASCADE は取り消し不可の操作です
① スキーマ内のすべてのオブジェクト(テーブル・データ含む)が削除されます
② ユーザーが現在接続中の場合はエラーになります。SELECT username, sid, serial# FROM v$session WHERE username = 'APP_SCHEMA' で確認し、接続中のセッションをすべて切断してから実行してください
③ 本番環境では必ず Data Pump でスキーマのバックアップを取ってから実行してください

実践的なスキーマ設計パターン

パターン①:アプリスキーマ + 接続スキーマの分離

Oracle のよくある設計パターンとして、「オブジェクトを所有するスキーマ」と「接続するスキーマ」を分離する方法があります。アプリケーションの接続アカウントに直接オブジェクトを所有させないため、最小権限の原則を実現しやすくなります。

SQL(アプリスキーマ + 接続スキーマ分離パターン)
-- Step 1: オブジェクト所有用スキーマを作成(接続不可)
CREATE USER app_owner IDENTIFIED BY "OwnerPass#2024"
    DEFAULT TABLESPACE app_data
    QUOTA UNLIMITED ON app_data;
-- CREATE SESSION を付与しない → 直接接続不可にする

-- Step 2: アプリ接続用スキーマを作成(接続のみ、オブジェクト所有なし)
CREATE USER app_user IDENTIFIED BY "UserPass#2024"
    DEFAULT TABLESPACE app_data;
GRANT CREATE SESSION TO app_user;

-- Step 3: app_owner のオブジェクトへの権限を app_user に付与
GRANT SELECT, INSERT, UPDATE, DELETE ON app_owner.orders TO app_user;
GRANT SELECT, INSERT ON app_owner.customers TO app_user;

-- Step 4: ログオントリガーで CURRENT_SCHEMA を自動切り替え(省略記述が可能になる)
CREATE OR REPLACE TRIGGER trg_set_schema
    AFTER LOGON ON app_user.SCHEMA
BEGIN
    EXECUTE IMMEDIATE 'ALTER SESSION SET CURRENT_SCHEMA = app_owner';
END;
/

-- これ以降 app_user は "SELECT * FROM orders" で app_owner.orders を参照できる
この設計パターンのメリット
① app_owner に CREATE SESSION を付与しないことで、所有者スキーマへの直接接続を禁止できる
② アプリに必要な最小権限だけを app_user に付与できる
③ パスワード変更は app_user のみ行えばよく、オブジェクトの所有権は変わらない
④ 複数の接続ユーザー(app_readonly / app_writer 等)を作り分けて同一スキーマに対して異なる権限を設定できる

パターン②:Data Pump でスキーマ単位にエクスポート・インポート

Oracle の Data Pump(expdp/impdp)はスキーマ単位での移行・複製に対応しています。開発スキーマを本番に昇格させたり、スキーマ名を変えて別環境に複製したりする場合に使います。

コマンド(スキーマ単位の Data Pump エクスポート・インポート)
-- HR スキーマ全体をエクスポート
expdp system/password SCHEMAS=hr DIRECTORY=DATA_PUMP_DIR DUMPFILE=hr_schema.dmp LOGFILE=hr_exp.log

-- 別スキーマ名(HR_NEW)でインポート(REMAP_SCHEMA)
impdp system/password SCHEMAS=hr REMAP_SCHEMA=hr:hr_new DIRECTORY=DATA_PUMP_DIR DUMPFILE=hr_schema.dmp LOGFILE=hr_imp.log

必要な権限

操作 必要な権限
CREATE USER(スキーマ作成) CREATE USER システム権限(DBA ロールに含まれる)
DROP USER CASCADE(スキーマ削除) DROP USER システム権限(DBA ロールに含まれる)
他スキーマのオブジェクトに SELECT 権限付与 対象オブジェクトの所有者、または GRANT ANY OBJECT PRIVILEGE
CREATE SYNONYM(プライベート) CREATE SYNONYM システム権限
CREATE PUBLIC SYNONYM CREATE PUBLIC SYNONYM システム権限(DBA 権限が必要)
DBA_OBJECTS を参照 SELECT ANY DICTIONARY または SELECT_CATALOG_ROLE
DBA_SEGMENTS を参照 SELECT ANY DICTIONARY または SELECT_CATALOG_ROLE
ユーザー権限の確認(USER_SYS_PRIVS / USER_ROLE_PRIVS / USER_TAB_PRIVS)については【Oracle】ユーザ権限を確認する方法完全ガイドを参照してください。

よくある質問

Oracle で CREATE SCHEMA を実行するとエラーになります
Oracle の CREATE SCHEMACREATE SCHEMA AUTHORIZATION ユーザー名 という構文で、新しいスキーマを作るコマンドではありません。新しいスキーマを作るには CREATE USER スキーマ名 IDENTIFIED BY パスワード; を実行してください。MySQL や PostgreSQL の感覚で CREATE SCHEMA と書いてもスキーマは作れません。
Oracle で 1 ユーザーが複数のスキーマを持つことはできますか?
できません。Oracle では 1 ユーザー = 1 スキーマが固定の仕様です。複数の論理的なスキーマを扱いたい場合は、それぞれのスキーマ用に別のユーザーを作成し、必要に応じてスキーマ間アクセスを GRANT と SYNONYM で設定するのが Oracle の標準的な設計です。
スキーマ名とユーザー名は異なっても問題ありませんか?
Oracle ではスキーマ名は必ずユーザー名と同じです。「スキーマ名を変えたい」場合は、新しいユーザーを作成し Data Pump の REMAP_SCHEMA でデータを移行するか、シノニムでアクセス名を変える方法をとります。
他スキーマのオブジェクトを参照する際に ORA-00942 が発生します
ORA-00942: テーブルまたはビューが存在しません は、オブジェクトが存在しないか権限がない場合に発生します。①スキーマ名を含めたフルパス(schema.table)で指定しているか、②対象オブジェクトへの SELECT 権限が付与されているか(SELECT * FROM dba_tab_privs で確認)、③スキーマ名・テーブル名の大文字小文字に誤りがないかを確認してください。
CURRENT_SCHEMA を変えると接続ユーザーも変わりますか?
変わりません。ALTER SESSION SET CURRENT_SCHEMA はデフォルトのオブジェクト解決先を変えるだけで、ログイン中のユーザー(SYS_CONTEXT('USERENV', 'SESSION_USER'))は変わりません。権限もログインユーザーの権限が引き続き使われます。
スキーマを削除したらデータも消えますか?
はい。DROP USER スキーマ名 CASCADE を実行すると、そのスキーマが所有するすべてのオブジェクト(テーブル・データ・インデックス・プロシージャなど)が完全に削除されます。取り消しはできないため、削除前に必ず Data Pump でバックアップを取ってください。

まとめ

Oracle スキーマの要点をまとめます。

やりたいこと 方法・ポイント
スキーマを作成する CREATE USER スキーマ名 IDENTIFIED BY パスワード DEFAULT TABLESPACE … で作成(スキーマは自動生成)
複数のオブジェクトを原子的に作成する CREATE SCHEMA AUTHORIZATION(自分のスキーマのみ・TABLE/VIEW/GRANT に限定)
他スキーマのオブジェクトを参照する スキーマ名.オブジェクト名 + GRANT でアクセス権限を付与
スキーマ名を省略してアクセスする CREATE SYNONYM でシノニムを作成(プライベート or パブリック)
デフォルト参照スキーマを切り替える ALTER SESSION SET CURRENT_SCHEMA = スキーマ名(ユーザーは変わらない)
スキーマのオブジェクト一覧を確認する USER_OBJECTS(自分のみ)/ ALL_OBJECTS(アクセス可能)/ DBA_OBJECTS(全体)
スキーマの使用容量を確認する DBA_SEGMENTS の owner で絞り込み、SUM(bytes) で集計
スキーマを削除する DROP USER スキーマ名 CASCADE(オブジェクトごと削除。取り消し不可)
接続ユーザーとオブジェクト所有者を分離する app_owner(所有・CREATE SESSION なし)+ app_user(接続のみ)パターン

CREATE USER の詳細な構文・権限付与・プロファイルについては【Oracle】新規ユーザー作成と権限付与の完全ガイド、スキーマの権限確認方法については【Oracle】ユーザ権限を確認する方法完全ガイドを参照してください。