「Oracle でスキーマを作るには?」と調べると、CREATE USER で作れると書いてあって戸惑う方は多いと思います。MySQL や PostgreSQL では CREATE SCHEMA や CREATE 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 では
CREATE USER hr IDENTIFIED BY password; を実行した瞬間に、同名の「HR スキーマ」が自動的に作られます。HR ユーザーが作成したすべてのオブジェクト(テーブル・インデックスなど)は自動的に HR スキーマに属します。逆に言うと、スキーマだけを独立して作ることはできません。スキーマを作る = ユーザーを作る、という理解が Oracle では正確です。
スキーマ(ユーザー)の作成:CREATE USER
Oracle でスキーマを作るには CREATE USER 文を実行します。ユーザーを作ると、同名のスキーマが自動的に使用可能になります。
-- ユーザーを作成すると同名のスキーマが自動生成される
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 SCHEMA AUTHORIZATION:原子的なオブジェクト作成
Oracle には CREATE SCHEMA AUTHORIZATION という構文があります。これは「新しいスキーマを作る」コマンドではなく、既存のスキーマ内に複数のオブジェクト(テーブル・ビュー)と権限付与を1 トランザクションで原子的に実行するための構文です。
-- 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;
①
AUTHORIZATION の後に指定できるスキーマ名は自分自身のユーザー名のみです。他のユーザーのスキーマに作成することはできません。② 作成できるのは TABLE・VIEW・GRANT のみです(INDEX・SEQUENCE・PROCEDURE 等は含められない)。
③ ブロック内のいずれかの文が失敗すると、ブロック全体がロールバックされます(原子性の保証)。
④ 実際の開発現場では個別の DDL を順番に実行する方が多く、この構文の使用頻度は低いです。
スキーマ間アクセス:他スキーマのオブジェクトを参照する
Oracle では スキーマ名.オブジェクト名 の形式で他スキーマのオブジェクトを参照できます。ただし、参照するには適切な権限が必要です。
スキーマ間アクセスの権限付与
-- 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:権限の委譲
-- 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 テーブルもパブリックシノニム) |
-- プライベートシノニム: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 内でスキーマ名を省略したときに参照するデフォルトスキーマを変更できます。ログイン中のユーザーは変わらないため、権限もそのままです。
-- 現在のスキーマを確認
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;
① テスト・開発環境で別スキーマのオブジェクトを頻繁に参照する場合
② アプリケーションスキーマ分離パターン(後述)で、接続ユーザーがアプリスキーマのオブジェクトをスキーマ名なしで参照するログオントリガーに使う
③ Data Pump インポート時のスキーマ名変換
CURRENT_SCHEMA を変更してもログインユーザーは変わらないため、CURRENT_USER とは別物であることに注意してください。
スキーマ内のオブジェクトを確認する
USER_OBJECTS / ALL_OBJECTS / DBA_OBJECTS
| ビュー名 | 参照範囲 | 主な用途 |
|---|---|---|
| USER_OBJECTS | 自分のスキーマのオブジェクトのみ | 自分のスキーマの確認(DBA 権限不要) |
| ALL_OBJECTS | 自分がアクセス権限を持つすべてのオブジェクト | 他スキーマの参照可能オブジェクトを確認 |
| DBA_OBJECTS | データベース内のすべてのオブジェクト | DBA がスキーマ横断で全オブジェクトを確認 |
-- 自分のスキーマのオブジェクト一覧(種別・状態含む)
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;
-- 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;
スキーマの使用容量を確認する
-- スキーマごとの合計使用容量(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 オプションが必要です。
-- パターン①: スキーマにオブジェクトがない場合 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';
① スキーマ内のすべてのオブジェクト(テーブル・データ含む)が削除されます
② ユーザーが現在接続中の場合はエラーになります。
SELECT username, sid, serial# FROM v$session WHERE username = 'APP_SCHEMA' で確認し、接続中のセッションをすべて切断してから実行してください③ 本番環境では必ず Data Pump でスキーマのバックアップを取ってから実行してください
実践的なスキーマ設計パターン
パターン①:アプリスキーマ + 接続スキーマの分離
Oracle のよくある設計パターンとして、「オブジェクトを所有するスキーマ」と「接続するスキーマ」を分離する方法があります。アプリケーションの接続アカウントに直接オブジェクトを所有させないため、最小権限の原則を実現しやすくなります。
-- 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)はスキーマ単位での移行・複製に対応しています。開発スキーマを本番に昇格させたり、スキーマ名を変えて別環境に複製したりする場合に使います。
-- 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 |
よくある質問
CREATE SCHEMA は CREATE SCHEMA AUTHORIZATION ユーザー名 という構文で、新しいスキーマを作るコマンドではありません。新しいスキーマを作るには CREATE USER スキーマ名 IDENTIFIED BY パスワード; を実行してください。MySQL や PostgreSQL の感覚で CREATE SCHEMA と書いてもスキーマは作れません。REMAP_SCHEMA でデータを移行するか、シノニムでアクセス名を変える方法をとります。ORA-00942: テーブルまたはビューが存在しません は、オブジェクトが存在しないか権限がない場合に発生します。①スキーマ名を含めたフルパス(schema.table)で指定しているか、②対象オブジェクトへの SELECT 権限が付与されているか(SELECT * FROM dba_tab_privs で確認)、③スキーマ名・テーブル名の大文字小文字に誤りがないかを確認してください。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】ユーザ権限を確認する方法完全ガイドを参照してください。

