【Oracle】ORA-00955 完全ガイド|name is already used by an existing object の原因・解決・OR REPLACE の使い方まで解説

ORA-00955: name is already used by an existing objectは、作成しようとしたオブジェクト(テーブル・ビュー・シーケンス・シノニムなど)の名前が同じスキーマ内でほかのオブジェクトに既に使われている場合に発生します。

Oracle ではスキーマ内でオブジェクトの種類に関係なく名前が一意である必要があります。つまり EMPLOYEES という名前のテーブルが存在する場合、同名のビューもシノニムも作成できません。

この記事でわかること

  • ORA-00955 が発生する原因パターン(オブジェクト種類をまたいだ名前衝突含む)
  • CREATE OR REPLACE で安全に置き換えられるオブジェクトの種類
  • USER_OBJECTS で既存オブジェクト名を確認する方法
  • DROP してから再作成する手順と IF EXISTS(23ai 以降)の使い方
  • PL/SQL で存在チェックをしてから CREATE/DROP を実行するパターン
スポンサーリンク

ORA-00955 が発生するパターン

操作 原因 対処法
CREATE TABLE 同名のテーブル・ビュー・シノニム・シーケンスがある DROP TABLE または別名を使う
CREATE VIEW 同名のビューがある(OR REPLACE なしで再作成しようとした) CREATE OR REPLACE VIEW を使う
CREATE SEQUENCE 同名のシーケンスがある DROP SEQUENCE → CREATE か ALTER SEQUENCE で変更する
CREATE SYNONYM 同名のシノニムまたは他のオブジェクトがある DROP SYNONYM → CREATE か CREATE OR REPLACE SYNONYM を使う
CREATE INDEX 同名のインデックスがある DROP INDEX → CREATE か別名を付ける(インデックス名はスキーマ内で一意)
重要: Oracle のオブジェクト名空間

Oracle では テーブル・ビュー・シノニム・シーケンス・プロシージャ・関数・パッケージ・マテリアライズドビューは同一の名前空間を共有します。EMPLOYEES というテーブルが存在する場合、同名のビューやシノニムも作成できません。インデックス・制約・トリガーは別の名前空間(スキーマ内で一意)です。

既存オブジェクトを確認して原因を特定する

USER_OBJECTS で同名オブジェクトを確認する
-- 作成しようとした名前と同じオブジェクトを検索する
SELECT object_name, object_type, status, created, last_ddl_time
FROM USER_OBJECTS
WHERE object_name = 'EMPLOYEES'    -- 大文字で検索(Oracle はオブジェクト名を大文字で格納)
ORDER BY object_type;

-- 別スキーマも含めて確認する場合(DBA権限)
SELECT owner, object_name, object_type
FROM DBA_OBJECTS
WHERE object_name = 'EMPLOYEES'
ORDER BY owner, object_type;

-- 自スキーマのシノニムが隠れている可能性も確認する
SELECT synonym_name, table_owner, table_name
FROM USER_SYNONYMS
WHERE synonym_name = 'EMPLOYEES';

-- 名前が似ているオブジェクトを一覧する(タイポなど)
SELECT object_name, object_type
FROM USER_OBJECTS
WHERE object_name LIKE 'EMPLOY%'
ORDER BY object_name;

CREATE OR REPLACE で安全に置き換える

CREATE OR REPLACE を使うと既存のオブジェクトを DROP せずに再作成できます。ただし テーブルは CREATE OR REPLACE に対応していない点に注意が必要です。

OR REPLACE が使えるオブジェクトと使えないオブジェクト
-- OR REPLACE が使えるオブジェクト(既存を上書き)
CREATE OR REPLACE VIEW emp_summary_v AS
SELECT employee_id, last_name, salary FROM employees;

CREATE OR REPLACE PROCEDURE update_salary(p_emp_id NUMBER, p_new_salary NUMBER) AS
BEGIN
    UPDATE employees SET salary = p_new_salary WHERE employee_id = p_emp_id;
END;
/

CREATE OR REPLACE FUNCTION get_salary(p_emp_id NUMBER) RETURN NUMBER AS
    v_salary NUMBER;
BEGIN
    SELECT salary INTO v_salary FROM employees WHERE employee_id = p_emp_id;
    RETURN v_salary;
END;
/

CREATE OR REPLACE PACKAGE salary_pkg AS
    PROCEDURE update_salary(p_emp_id NUMBER, p_new_salary NUMBER);
    FUNCTION get_salary(p_emp_id NUMBER) RETURN NUMBER;
END salary_pkg;
/

CREATE OR REPLACE SYNONYM emp FOR hr.employees;        -- シノニムも OR REPLACE 可
CREATE OR REPLACE TYPE address_t AS OBJECT (           -- 型も OR REPLACE 可
    street VARCHAR2(100), city VARCHAR2(50)
);
/

-- OR REPLACE が使えないオブジェクト(DROP → CREATE が必要)
-- TABLE: CREATE OR REPLACE TABLE は存在しない
-- INDEX: OR REPLACE は使えない
-- SEQUENCE: ALTER SEQUENCE で変更する
-- TRIGGER: CREATE OR REPLACE TRIGGER は使える(12c 以降)

-- テーブルの再作成が必要な場合
DROP TABLE employees PURGE;          -- リサイクルビンを経由しない完全削除
CREATE TABLE employees (...);        -- 再作成

存在チェックをしてから DROP / CREATE を実行する

PL/SQL で存在チェックしてから DROP を実行するパターン
-- テーブルが存在する場合のみ DROP してから再作成する
BEGIN
    EXECUTE IMMEDIATE 'DROP TABLE work_temp PURGE';
EXCEPTION
    WHEN OTHERS THEN
        IF SQLCODE = -942 THEN   -- ORA-00942: table or view does not exist
            NULL;   -- テーブルが存在しない場合は無視
        ELSE
            RAISE;  -- それ以外のエラーは再送出
        END IF;
END;
/

-- 上記の後で CREATE TABLE
CREATE TABLE work_temp (
    id     NUMBER,
    value  VARCHAR2(100)
);

-- シーケンスの存在チェック
DECLARE
    v_count NUMBER;
BEGIN
    SELECT COUNT(*) INTO v_count FROM USER_OBJECTS
    WHERE object_name = 'ORDER_ID_SEQ' AND object_type = 'SEQUENCE';

    IF v_count > 0 THEN
        EXECUTE IMMEDIATE 'DROP SEQUENCE order_id_seq';
    END IF;
END;
/
CREATE SEQUENCE order_id_seq START WITH 1 INCREMENT BY 1 NOCACHE;

-- Oracle 23ai 以降: IF EXISTS / IF NOT EXISTS が使える
DROP TABLE IF EXISTS work_temp;        -- 23ai 以降: 存在しなくてもエラーにならない
CREATE TABLE IF NOT EXISTS work_temp (id NUMBER, value VARCHAR2(100));  -- 23ai 以降

まとめ

  • ORA-00955 の原因:同じスキーマ内でオブジェクト名が重複している。テーブル・ビュー・シノニム・シーケンスは同じ名前空間を共有するため、種類が違っても衝突する
  • 確認方法:USER_OBJECTS で同名オブジェクトを検索する。object_name = ‘名前’ は大文字で検索する
  • VIEW / PROCEDURE / FUNCTION / PACKAGE / SYNONYM:CREATE OR REPLACE で既存オブジェクトを DROP せずに置き換えられる
  • TABLE / SEQUENCE / INDEX:CREATE OR REPLACE は使えない。DROP してから再作成するか、ALTER で変更する
  • DROP → CREATE パターン:PL/SQL でエラーハンドリングしながら DROP してから CREATE するのが安全。Oracle 23ai 以降は DROP TABLE IF EXISTS が使えるのでシンプルになる

ビュー(VIEW)の作成については Oracle ビュー完全ガイドを参照してください。データディクショナリビューの使い方は Oracle データディクショナリ完全ガイドも参照してください。