【Oracle】PLS-00103の原因と解決方法|Encountered the symbolの読み方

【Oracle】PLS-00103の原因と解決方法|Encountered the symbolの読み方 Oracle

PLS-00103: Encountered the symbol ... は、Oracle PL/SQLの構文が崩れている時に出るコンパイルエラーです。直訳すると「予期していない記号に遭遇した」という意味で、セミコロン忘れ、BEGIN / END の対応ミス、IF / LOOP / CASE の閉じ忘れ、SQLとPL/SQL構文の混同などでよく発生します。

このエラーは、表示された行だけを直せば終わるとは限りません。Oracle公式のエラー説明でも、line/columnは壊れた構文の終端を指すことがあるとされています。つまり、エラー行の少し前から構文のまとまりを読み直すのが近道です。

先に結論
PLS-00103が出たら、まずエラー文の Encountered the symbolwhen expecting one of the following を分けて読みます。実際に出てきた記号と、Oracleが期待していた候補を見比べ、直前のセミコロン、キーワード、閉じ忘れを確認します。PL/SQL全体の基本構文は PL/SQLの基本構文 も参考になります。
スポンサーリンク

PLS-00103とは

PLS-00103は、PL/SQLのパーサーが「ここに来るはずではない記号やキーワード」を見つけた時に発生します。PL/SQLでは、宣言部、実行部、例外処理部、制御構文の並びが決まっています。そのルールから外れると、Encountered the symbol として検出されます。

よくあるエラーメッセージは次の形です。

pls-00103-message.txt
ORA-06550: line 7, column 3:
PLS-00103: Encountered the symbol "END" when expecting one of the following:
   ;
メッセージの部分 意味 見ること
line 7, column 3 Oracleが異常に気づいた位置 その行だけでなく直前の構文も見る
Encountered the symbol "END" 実際に出てきた記号やキーワード END の前に不足がないか
when expecting ... ; Oracleが期待していた候補 セミコロンやキーワードの不足
ORA-06550 PL/SQLブロック全体の失敗 後続のPLS-00103を直す

Encountered と expecting の読み方

PLS-00103のエラー文は、出てきた記号と、Oracleが期待していた記号を分けて読むと原因を絞りやすくなります。Encountered は実際に現れたもの、expecting はその位置に来るはずだった候補です。

エラー文の見方 意味 疑う場所
Encountered the symbol "END" END が早く出てきた 直前の文末、IF / LOOP の閉じ方
when expecting one of the following: ; セミコロンが必要だった 1つ前のSQL文・PL/SQL文
Encountered the symbol "ELSE" ELSE の位置がおかしい IF ... THEN の形、直前の文末
Encountered the symbol "LOOP" LOOP の前が崩れている FOR / WHILE の条件部
Encountered the symbol "SELECT" PL/SQL内のSQL文が想定外 SELECT INTO、直前文のセミコロン
Encountered the symbol "end-of-file" ファイル末尾まで読んでも閉じられなかった END;END IF;END LOOP; の不足

まず確認する順番

PLS-00103は原因が広いため、構文のまとまりごとに確認します。エラー行の前後だけでなく、直前の IFLOOPBEGIN、SQL文の終わりを見ます。

順番 確認すること よくある原因
1 エラー文の Encountered the symbol 実際に出てきた記号を確認
2 直前のSQL/PLSQL文 セミコロン忘れ
3 制御構文の開始と終了 IFEND IF がない
4 宣言部と実行部の境界 DECLAREBEGIN の位置ミス
5 SQLとPL/SQLの混同 PL/SQLで直接使えない書き方
6 全角文字や見えない文字 全角セミコロン、ノーブレークスペース

期待候補別の直し方

when expecting one of the following の後ろには、Oracleがその位置で受け付けられる候補が並びます。全部を暗記する必要はありません。まずは、期待候補から直前の構文を逆算します。

期待候補 よくある不足 最初に直す場所
; 直前の文末セミコロン エラー行の1つ前
THEN IF 条件の終端 IF 条件 THEN の形
LOOP FOR / WHILE の後ろ FOR i IN ... LOOP
IS / AS プロシージャ・関数見出しの終端 CREATE PROCEDURE ... IS
INTO PL/SQL内のSELECT結果受け取り SELECT ... INTO 変数 FROM ...
END 制御構文やブロックの閉じ ネストした IF / LOOP

セミコロン忘れのケース

最も多いのは、直前の文末にセミコロンがないケースです。エラーは次の行の ENDIF で出ることがありますが、原因はその前の行にあります。

missing-semicolon.sql
BEGIN
  DBMS_OUTPUT.PUT_LINE('start')
  DBMS_OUTPUT.PUT_LINE('end');
END;
/
-- PLS-00103: Encountered the symbol "DBMS_OUTPUT" ...
missing-semicolon-fixed.sql
BEGIN
  DBMS_OUTPUT.PUT_LINE('start');
  DBMS_OUTPUT.PUT_LINE('end');
END;
/

Oracle SQLの構文エラーとして出る ORA-00936ORA-00933 と似ていますが、PLS-00103はPL/SQLブロック内の構文として検出されます。

BEGIN / ENDの対応が崩れているケース

PL/SQLブロックは、宣言部、BEGIN から始まる実行部、必要に応じた例外処理部、最後の END; で構成されます。この対応が崩れるとPLS-00103になります。

begin-end-mismatch.sql
DECLARE
  v_count NUMBER := 0;
-- NG: BEGINがない
  v_count := v_count + 1;
END;
/
begin-end-fixed.sql
DECLARE
  v_count NUMBER := 0;
BEGIN
  v_count := v_count + 1;
END;
/

IF / THEN / END IFのミス

IF 文では、THENEND IF; が必要です。どちらかが抜けると、別の行でPLS-00103として検出されます。

if-then-missing.sql
BEGIN
  IF SYSDATE > DATE '2026-01-01'
    DBMS_OUTPUT.PUT_LINE('after 2026');
  END IF;
END;
/
-- NG: THENがない
if-then-fixed.sql
BEGIN
  IF SYSDATE > DATE '2026-01-01' THEN
    DBMS_OUTPUT.PUT_LINE('after 2026');
  END IF;
END;
/

ELSIFELSE IF と書いてしまうミスもあります。PL/SQLの分岐では ELSIF 条件 THEN を使います。

LOOP / END LOOPのミス

ループでは、LOOPEND LOOP; の対応を確認します。FORWHILE の後に LOOP を書き忘れるミスもよくあります。

for-loop-missing-loop.sql
BEGIN
  FOR i IN 1..3
    DBMS_OUTPUT.PUT_LINE(i);
  END LOOP;
END;
/
-- NG: FORの後にLOOPがない
for-loop-fixed.sql
BEGIN
  FOR i IN 1..3 LOOP
    DBMS_OUTPUT.PUT_LINE(i);
  END LOOP;
END;
/

CASE文の閉じ方を間違えているケース

PL/SQLには、式として使う CASE と、文として使う CASE があります。PL/SQLのCASE文では END CASE; を使います。

case-statement.sql
DECLARE
  v_status VARCHAR2(10) := 'A';
BEGIN
  CASE v_status
    WHEN 'A' THEN
      DBMS_OUTPUT.PUT_LINE('active');
    ELSE
      DBMS_OUTPUT.PUT_LINE('other');
  END CASE;
END;
/

SQLの CASE WHEN ... END の感覚で書くと混乱しやすい部分です。PL/SQL文としてのCASEなのか、SQL式のCASEなのかを分けて考えます。

SQLとPL/SQL構文を混同しているケース

SQLとしては自然に見えても、PL/SQLブロックの中では書き方を変える必要があるものがあります。特に SELECT は、PL/SQL内では結果の受け取り先が必要です。

select-without-into.sql
DECLARE
  v_name VARCHAR2(100);
BEGIN
  -- NG: PL/SQL内のSELECTにはINTOが必要
  SELECT user FROM dual;
END;
/
select-into-fixed.sql
DECLARE
  v_name VARCHAR2(100);
BEGIN
  SELECT user
  INTO v_name
  FROM dual;

  DBMS_OUTPUT.PUT_LINE(v_name);
END;
/

通常のSQL文の終わり方や句の順序で迷う場合は、ORA-00933ORA-00907 の考え方も役立ちます。

IS / ASを書き忘れたケース

プロシージャやファンクション、パッケージ本体では、見出しの後に IS または AS が必要です。このキーワードが抜けると、BEGIN の位置でPLS-00103になることがあります。

procedure-missing-is.sql
CREATE OR REPLACE PROCEDURE p_test
BEGIN
  NULL;
END;
/
-- NG: ISまたはASがない
procedure-with-is.sql
CREATE OR REPLACE PROCEDURE p_test IS
BEGIN
  NULL;
END;
/

DECLARE部に実行文を書いているケース

DECLARE から BEGIN までの間は、変数、定数、型、カーソル、サブプログラムなどを宣言する場所です。代入や DBMS_OUTPUT.PUT_LINE などの実行文を書くと構文エラーになります。

statement-in-declare.sql
DECLARE
  v_count NUMBER := 0;
  -- NG: 実行文はBEGIN以降に書く
  v_count := v_count + 1;
BEGIN
  DBMS_OUTPUT.PUT_LINE(v_count);
END;
/

CREATE文をブロック内に直接書いているケース

PL/SQLブロック内に CREATE TABLECREATE INDEX をそのまま書くと、PLS-00103になることがあります。DDLを動的に実行する場合は EXECUTE IMMEDIATE を使います。

ddl-in-plsql.sql
BEGIN
  -- NG: DDLを直接書いている
  CREATE TABLE work_log (
    id NUMBER
  );
END;
/
ddl-execute-immediate.sql
BEGIN
  EXECUTE IMMEDIATE '
    CREATE TABLE work_log (
      id NUMBER
    )';
END;
/

全角文字・見えない文字が混ざっているケース

コピーしたSQLに全角セミコロン、全角スペース、ノーブレークスペース、見えない制御文字が混ざると、PLS-00103になることがあります。見た目では分からないため、エディタで不可視文字を表示するか、該当行を手入力し直します。

混入しやすい文字 症状 対処
全角セミコロン 文末を認識しない 半角 ; に直す
全角カンマ 引数や列の区切りでエラー 半角 , に直す
全角スペース キーワードが分断される 半角スペースに置換
ノーブレークスペース 通常の空白に見える 不可視文字表示で確認
スマートクォート 文字列リテラルが崩れる 半角シングルクォートに直す

ORA-06550と一緒に出る場合

PLS-00103は、匿名ブロックやアプリケーション経由の実行で ORA-06550 と一緒に表示されることが多いです。この場合、ORA-06550はPL/SQLブロック全体が失敗したことを示す入口で、実際に直すべき中心は後続のPLS-00103です。

ora-06550-pls00103.txt
ORA-06550: line 4, column 3:
PLS-00103: Encountered the symbol "END" when expecting one of the following:
   ;
ORA-06550: line 4, column 3:
PL/SQL: Statement ignored

コンパイルエラーをDB上で確認する場合は、PL/SQLのコンパイル時エラーと警告 も参考になります。

エラー行番号がずれる時の読み方

PLS-00103では、エラー行が原因行そのものではなく、Oracleが構文の破綻に気づいた位置を指すことがあります。たとえばセミコロン忘れの場合、原因は前の行なのに、次のキーワードでエラーになることがあります。

表示された記号 直前で疑うこと
END 直前の文末セミコロン、閉じ忘れ DBMS_OUTPUT.PUT_LINE(...); 忘れ
ELSE IFTHEN、前の文末 IF 条件 THEN の崩れ
LOOP FOR / WHILE の形 FOR i IN ... LOOP
SELECT PL/SQL内での INTO、直前文の終端 SELECT ... INTO ...
end-of-file 最後の END;END IF; 漏れ ブロック終端の不足

USER_ERRORSで確認する

プロシージャ、ファンクション、パッケージ、トリガーの作成時にPLS-00103が出た場合は、USER_ERRORSALL_ERRORS でエラーを確認できます。

user-errors-pls00103.sql
SELECT name,
       type,
       line,
       position,
       text
FROM user_errors
WHERE text LIKE '%PLS-00103%'
ORDER BY name, sequence;

パッケージ本体の不一致や無効オブジェクトが関係する場合は、PLS-00323PLS-00302PLS-00905 も近い確認先です。

パッケージやトリガーで出る場合

パッケージ、プロシージャ、ファンクション、トリガーでPLS-00103が出る場合は、匿名ブロックよりも範囲が広くなります。対象オブジェクトの USER_ERRORS を確認し、仕様部と本体、サブプログラム単位、トリガー本文のどこで構文が崩れているかを切り分けます。

対象 よく見る場所 関連して確認する記事
パッケージ仕様部 型宣言、サブプログラム宣言、セミコロン PLS-00323
パッケージ本体 IS / AS、各プロシージャの END ORA-04063
プロシージャ/関数 見出し、宣言部、実行部の境界 PLS-00306
トリガー BEGIN:NEW / :OLD、セミコロン PLS-00905

よくある原因と対処一覧

原因 エラーで出やすい記号 対処
セミコロン忘れ END、次の文 直前の文末に ; を付ける
THEN 忘れ DBMS_OUTPUT、実行文 IF 条件 THEN にする
LOOP 忘れ DBMS_OUTPUTEND FOR ... LOOP にする
END IF 忘れ end-of-fileEND 制御構文を閉じる
BEGIN 忘れ 代入文、実行文 宣言部の後に BEGIN を置く
SQLとPL/SQLの混同 SELECTCREATE INTOEXECUTE IMMEDIATE を使う
全角文字混入 見慣れない記号、空白 半角文字に置換する

修正チェックリスト

項目 OKの状態
エラー文を分解した Encounteredexpecting を読んだ
直前行を見た 表示行の前の文末も確認済み
セミコロンを確認した 各文が ; で終わっている
制御構文を閉じた END IF;END LOOP;END CASE; がある
宣言部と実行部を分けた DECLAREBEGIN の役割が合っている
SQLとPL/SQLを分けた SELECT INTOEXECUTE IMMEDIATE を使っている
不可視文字を確認した 全角記号や見えない空白を除去済み

よくある質問

エラー行に問題が見つかりません

PLS-00103の行番号は、原因行ではなく構文の破綻に気づいた位置を指すことがあります。表示行の直前から確認してください。

Encountered the symbolの後に出る記号を直せばよいですか?

必ずしもそうではありません。その記号自体より、直前に不足しているセミコロンやキーワードが原因のことが多いです。

ORA-06550も一緒に出ています

ORA-06550はPL/SQLブロック全体の失敗を示します。後続のPLS-00103の行・列・期待候補を中心に直します。

SQL Developerではどこを見ればよいですか?

エラー表示のline/columnを起点にしつつ、直前の文末、制御構文の閉じ、SQL文の句順を確認します。オブジェクト作成後なら USER_ERRORS も見ます。

パッケージでPLS-00103が出ています

仕様部と本体の境界、IS / AS、サブプログラムの閉じ忘れを確認してください。パッケージ系の不一致ならPLS-00323やPLS-00302も確認します。

まとめ

PLS-00103は、Oracle PL/SQLで想定外の記号やキーワードに遭遇した時の構文エラーです。原因は、セミコロン忘れ、BEGIN / END の対応ミス、IF / LOOP / CASE の閉じ忘れ、SQLとPL/SQL構文の混同、全角文字の混入などが中心です。

直し方の基本は、エラー文の Encountered the symbol と期待候補を読み、表示行の直前から構文のまとまりを確認することです。行番号だけに引っ張られず、前の文の終端と制御構文の対応を見ると解決が早くなります。

参考

PLS-00103 – Oracle Database Error Help

Block – Oracle Database PL/SQL Language Reference

PL/SQL Language Elements – Oracle Database PL/SQL Language Reference