【Oracle】ORA-00907の原因と解決方法|missing right parenthesis・右括弧がありませんの直し方

【Oracle】ORA-00907の原因と解決方法|missing right parenthesis・右括弧がありませんの直し方 Oracle

ORA-00907: missing right parenthesis は、SQLの括弧が閉じていない、または括弧の中にOracleが認識できない構文が入っているときに発生するエラーです。日本語環境では「右括弧がありません」と表示されます。

単純な ) の付け忘れだけでなく、関数の引数、CREATE TABLE の列定義、CHECK 制約、IN 句、CASE 式、サブクエリ、動的SQLの組み立てミスでも発生します。

先に結論
ORA-00907は、開き括弧と閉じ括弧の数を合わせるだけでなく、括弧の中身がOracleの文法として正しいかを見る必要があります。エラー位置の直前にある (、関数、列定義、制約、IN、サブクエリを順に確認すると切り分けやすいです。
スポンサーリンク

ORA-00907とは

Oracle公式のエラー説明では、ORA-00907は左括弧に対応する右括弧がない場合、または括弧内に認識できない情報が含まれている場合に発生するとされています。そのため、原因は「閉じ括弧の不足」と「括弧の中の構文ミス」の2方向で確認します。

見る場所 よくある原因 修正の方向
括弧の数 () の数が合わない 対応する閉じ括弧を追加する
関数 引数の閉じ忘れ、カンマ不足 関数の引数を正しく閉じる
CREATE TABLE 列定義、制約、カンマの位置ミス 列ごとの定義を分けて確認する
FOREIGN KEY 列定義内で FOREIGN KEY を誤用する REFERENCES または表制約で書く
IN句 候補リストやサブクエリを閉じていない IN (...) 全体を閉じる
CASE式 CASE と括弧が混在して崩れる END と括弧を分けて確認する
動的SQL 文字列連結で括弧だけ欠ける 完成したSQLをログに出して確認する

まず括弧の対応を確認する

最初に、エラーが出たSQLを整形し、開き括弧と閉じ括弧が対応しているか確認します。長いSQLを1行のまま見ると見落としやすいので、関数、サブクエリ、条件ごとに改行します。

basic-parenthesis-check.sql
-- NG: NVLの閉じ括弧が足りない
SELECT employee_id,
       NVL(commission_pct, 0 AS commission_pct
FROM employees;

-- OK: 関数呼び出しを閉じてから別名を付ける
SELECT employee_id,
       NVL(commission_pct, 0) AS commission_pct
FROM employees;

括弧の数が合っていても、閉じる位置が違うと別の構文として解釈されます。特に関数の後ろに AS、比較演算子、カンマが続く場合は、関数を先に閉じるのが基本です。

CREATE TABLEで発生するケース

CREATE TABLE は括弧が多く、ORA-00907が出やすい代表例です。列定義のカンマ不足、最後の余分なカンマ、制約定義の括弧不足を確認します。

create-table-missing-parenthesis.sql
-- NG: CHECK制約の閉じ括弧が足りない
CREATE TABLE employees_work (
    employee_id NUMBER PRIMARY KEY,
    salary NUMBER(10, 2),
    status VARCHAR2(10),
    CONSTRAINT chk_salary CHECK (salary >= 0
);

-- OK: CHECK条件とCREATE TABLE全体の括弧をそれぞれ閉じる
CREATE TABLE employees_work (
    employee_id NUMBER PRIMARY KEY,
    salary NUMBER(10, 2),
    status VARCHAR2(10),
    CONSTRAINT chk_salary CHECK (salary >= 0)
);

列定義を1列ずつコメントアウトして実行できるなら、どの列や制約で崩れているかを絞り込めます。ただし本番環境ではDDLを直接試さず、検証環境で確認してください。

FOREIGN KEY制約で発生するケース

Oracleでは、列定義の中に FOREIGN KEY というキーワードをそのまま書く形ではなく、列制約なら REFERENCES、表制約なら FOREIGN KEY (列名) REFERENCES ... の形で書きます。他DBの書き方を混ぜると、ORA-00907の原因になることがあります。

foreign-key-parenthesis.sql
-- NG: 列定義内でFOREIGN KEYを直接書いている
CREATE TABLE order_items (
    item_id NUMBER PRIMARY KEY,
    order_id NUMBER FOREIGN KEY REFERENCES orders(order_id),
    quantity NUMBER
);

-- OK: 列制約ならREFERENCESだけを書く
CREATE TABLE order_items (
    item_id NUMBER PRIMARY KEY,
    order_id NUMBER REFERENCES orders(order_id),
    quantity NUMBER
);

-- OK: 表制約ならFOREIGN KEY (列名) として書く
CREATE TABLE order_items (
    item_id NUMBER PRIMARY KEY,
    order_id NUMBER,
    quantity NUMBER,
    CONSTRAINT fk_order_items_order
        FOREIGN KEY (order_id) REFERENCES orders(order_id)
);

列定義とデータ型の括弧ミス

NUMBER(10,2)VARCHAR2(100)TIMESTAMP(6) など、データ型の精度や長さにも括弧を使います。閉じ忘れやカンマ位置の誤りでORA-00907になることがあります。

datatype-parenthesis.sql
-- NG: NUMBERの閉じ括弧がない
CREATE TABLE sales_work (
    sales_id NUMBER PRIMARY KEY,
    amount NUMBER(12, 2,
    created_at DATE
);

-- OK
CREATE TABLE sales_work (
    sales_id NUMBER PRIMARY KEY,
    amount NUMBER(12, 2),
    created_at DATE
);

CHECK制約で発生するケース

CHECK 制約では、条件式を括弧で囲むため、条件の括弧と制約の括弧が混ざりやすくなります。IN や複数条件を使う場合は、条件式全体を読みやすく分けます。

check-constraint-parenthesis.sql
-- NG: INリストとCHECKの括弧が崩れている
CREATE TABLE orders_work (
    order_id NUMBER PRIMARY KEY,
    status VARCHAR2(20),
    CONSTRAINT chk_order_status CHECK (status IN ('NEW', 'PAID', 'CANCELLED')
);

-- OK
CREATE TABLE orders_work (
    order_id NUMBER PRIMARY KEY,
    status VARCHAR2(20),
    CONSTRAINT chk_order_status CHECK (status IN ('NEW', 'PAID', 'CANCELLED'))
);

IN句で閉じ括弧が不足しているケース

IN 句は、値リストでもサブクエリでも括弧が必要です。候補値を追加・削除したあとに閉じ括弧やカンマが崩れていないか確認します。

in-list-parenthesis.sql
-- NG: INリストを閉じていない
SELECT *
FROM employees
WHERE department_id IN (10, 20, 30;

-- OK
SELECT *
FROM employees
WHERE department_id IN (10, 20, 30);

IN 句の使い方や大量リストの扱いは OracleのIN句・EXISTSの使い分け も参考になります。

サブクエリで発生するケース

サブクエリは (SELECT ...) の形で書くため、外側の条件と内側のSELECTの括弧がずれやすいです。サブクエリだけを取り出して実行できる形にすると、原因を切り分けやすくなります。

subquery-parenthesis.sql
-- NG: サブクエリの閉じ括弧が足りない
SELECT *
FROM employees e
WHERE e.department_id = (
    SELECT d.department_id
    FROM departments d
    WHERE d.department_name = 'Sales';

-- OK
SELECT *
FROM employees e
WHERE e.department_id = (
    SELECT d.department_id
    FROM departments d
    WHERE d.department_name = 'Sales'
);

サブクエリの基本は Oracleのサブクエリ完全ガイド、サブクエリが複数行返る場合は ORA-01427の原因と解決方法 も確認してください。

CASE式で括弧とENDが混ざるケース

CASE 式では、括弧だけでなく END の抜けも混ざります。ORA-00907が出ていても、実際には関数の中に書いた CASE が閉じていないことがあります。

case-expression-parenthesis.sql
-- NG: CASE式をENDで閉じていない
SELECT employee_id,
       NVL(CASE
             WHEN salary >= 500000 THEN bonus
             ELSE 0
           , 0) AS bonus_amount
FROM employees;

-- OK: CASEをENDで閉じてからNVLの引数を続ける
SELECT employee_id,
       NVL(CASE
             WHEN salary >= 500000 THEN bonus
             ELSE 0
           END, 0) AS bonus_amount
FROM employees;

関数の入れ子で発生するケース

NVLCOALESCETO_CHARTO_DATE などを入れ子にすると、どの関数の括弧を閉じているのか分かりにくくなります。内側から順に閉じるのが基本です。

nested-functions-parenthesis.sql
-- NG: NVLの第2引数と閉じ括弧の位置が崩れている
SELECT NVL(TO_CHAR(hire_date, 'YYYY-MM-DD'), '未設定' AS hire_date_text
FROM employees;

-- OK: TO_CHARを閉じ、NVLも閉じる
SELECT NVL(TO_CHAR(hire_date, 'YYYY-MM-DD'), '未設定') AS hire_date_text
FROM employees;

動的SQLで発生するケース

アプリケーションやPL/SQLでSQL文字列を組み立てる場合、条件追加の分岐によって括弧だけが欠けることがあります。この場合、ソースコード上の断片ではなく、最終的に実行しているSQL全文をログに出すのが近道です。

dynamic-sql-parenthesis.sql
-- NG: 条件追加の途中で閉じ括弧が欠けたSQLになっている
SELECT *
FROM employees
WHERE (department_id = :dept_id
  AND status = 'ACTIVE';

-- OK: 生成後のSQLで括弧が閉じているか確認する
SELECT *
FROM employees
WHERE (department_id = :dept_id
  AND status = 'ACTIVE');

動的SQLを使う場合は、文字列連結だけでなくバインド変数も確認します。Oracleの動的SQLは EXECUTE IMMEDIATE完全ガイド も参考になります。

ORA-00936やORA-00933との違い

ORA-00907ORA-00936ORA-00933 はどれも構文エラーですが、見る場所が違います。括弧が怪しければORA-00907、式や値が抜けていればORA-00936、句の順序やOracle非対応構文が怪しければORA-00933を疑います。

エラー 主な原因 確認する場所
ORA-00907 右括弧不足、括弧内の構文ミス 関数、IN、CHECK、サブクエリ、CREATE TABLE
ORA-00936 式、列、値、条件の不足 SELECT 句、WHERE 句、関数引数
ORA-00933 句の終わり方、他DB構文 LIMITUPDATE JOIN、余分な句

式不足が疑わしい場合は ORA-00936の原因と解決方法、句の終わり方が疑わしい場合は ORA-00933の原因と解決方法 を確認してください。

修正チェックリスト

手順 確認すること 見るポイント
1 SQLを整形する 関数、条件、サブクエリごとに改行する
2 括弧の数を数える () が対応しているか確認する
3 直前の関数を見る 引数、カンマ、別名の位置を確認する
4 DDLなら列定義を見る 列ごとのカンマ、データ型、制約を確認する
5 外部キー制約を見る REFERENCES と表制約の書き方を混同していないか確認する
6 IN やサブクエリを見る 候補リスト、SELECT、外側条件を閉じているか確認する
7 CASE を見る END と関数の括弧を混同していないか確認する
8 動的SQLなら完成SQLを見る 実行直前のSQL全文をログで確認する

よくある質問

ORA-00907は必ず閉じ括弧の不足ですか?

閉じ括弧の不足が多いですが、括弧の中にOracleが認識できない構文がある場合にも発生します。括弧の数だけでなく、括弧内の列定義、制約、関数引数も確認します。

エラー位置と原因の場所がずれることはありますか?

あります。Oracleが構文を読み進めた結果、後ろの位置でエラーを検出することがあります。表示位置の直前だけでなく、その前にある開き括弧や関数から確認します。

CREATE TABLEでORA-00907が出たらどこを見ますか?

列定義のカンマ、NUMBER(10,2) などのデータ型、CHECK 制約、PRIMARY KEYFOREIGN KEY の括弧を順に見ます。

FOREIGN KEYの書き方でもORA-00907になりますか?

なります。列定義内では order_id NUMBER REFERENCES orders(order_id) のように書き、表制約では FOREIGN KEY (order_id) のように列名を括弧で指定します。

アプリからだけORA-00907が出る場合は?

SQL文字列の連結で括弧が欠けている可能性があります。プレースホルダに値を入れる前後で、実際にDBへ送っているSQL全文をログに出して確認します。

まとめ

ORA-00907は、右括弧の不足や括弧内の構文ミスで発生するOracleエラーです。まずSQLを整形し、関数、DDL、制約、IN句、サブクエリ、CASE式、動的SQLの順に括弧の対応を確認しましょう。

単に ) を足すだけではなく、括弧を閉じる位置が正しいか、括弧の中身がOracleの文法として正しいかを見ることが大切です。似た構文エラーとしてORA-00936やORA-00933もあわせて切り分けると、原因に早くたどり着けます。

参考

ORA-00907 – Oracle Database Error Help

CREATE TABLE – Oracle SQL Language Reference

constraint – Oracle SQL Language Reference