PL/SQLを書き始めたばかりのころ、私は完全に「エラーと仲良くなれないマン」でした。
実行するたびに出てくる「ORA-」の呪文。
エラー番号はやたら桁が多いし、「06512」とか見ても「それ、郵便番号?」状態。
BEGINって書いたけど、何が始まるのか誰も教えてくれない。そんな日々でした。
でも、少しずつ慣れてくると見えてくるんです。
エラーって、実は「ここが違ってるよ」「この書き方はOracle的にナシだよ」と優しく教えてくれる、不器用なツンデレ先輩みたいな存在だと(?)。
この記事では、PL/SQL初心者の方向けに
- よくあるエラーの読み方
- DBMS_OUTPUTの罠
- おすすめのデバッグ手法
などを実体験まじえてやさしく解説していきます。
「これ、昔の自分に教えてあげたかった〜!」という内容を詰め込んでいるので、今まさにハマっている方の助けになればうれしいです。
PL/SQLの“エラー怖い”問題と向き合う
PL/SQLで初めてプロシージャを書いた日のことは、今でもよく覚えています。
意気揚々とBEGINって書いたはいいけど、何が始まるのか誰も教えてくれない。
「ORA-06512 at line 3」って出てきたけど、3行目にそんな大それたこと書いてない。
──そして夜の21時。私とエラーのにらめっこはまだ続いていました。
エラーは敵か?いいえ、最初は敵です。
最初にぶつかるPL/SQLの壁、それは「エラーが何を言ってるのか全然わからん」問題ではないでしょうか。
- 数字と英語の組み合わせ(ORA-06502って何番?)
- “invalid identifier”って、どこが無効なの?(全部有効だと思ってた)
- 実行したら“何も起きない”…いや何か言って!?
そのうえ、PostgreSQLに慣れていた私にとっては、Oracleのルールが思ったより堅い。
「変数の型?そんな細かいこといいじゃない…」って呟いたら、
Oracleは静かに突き返してきます。「NO。」
でも、わからないままにしないために
実際に私は「ORAのエラーを読むのが怖い」という理由で、PL/SQLのコード修正に身が入りづらかった時期がありました。
でもあるとき、ひとつのエラーをじっくり調べてみて、「あ、このメッセージってこういう意味だったのか!」と腑に落ちた瞬間がありました。
それからは少しずつ、「PL/SQLはエラーが出てからが本番」「エラー文こそOracleが教えてくれるヒント帳」だと思えるようになってきたんです(たまに無口ですが)。
この記事では、そんな“エラーと仲良くなる第一歩”として、次の章から
- よく出るPL/SQLのエラーメッセージと読み方
- 出力ログ(DBMS_OUTPUT)を使ったデバッグ
- 本番環境でも使える実用的なログ出力の工夫
- 実際に私がやらかしたエラー実例とその対処法
などなどをご紹介していきます。
まずはここを押さえよう — PL/SQLで出るエラーメッセージの読み方
PL/SQLの開発で避けて通れないもの、それがORAエラーです。
たとえるなら、口数は少ないけどしっかりダメ出ししてくる先生のような存在。
「ORA-06512 at line 4」なんて出てきた日には、「なんか言われてるけど、その“4行目”に何があるの!?」とザワつくこともしばしば。
でもご安心を。エラーメッセージにはちゃんと意味があり、ポイントを押さえれば落ち着いて読み取ることができます。
よく出るORAエラーとその“言い分”
ORA-06512: at line ◯
「ここでエラー起きたっぽいよ」という行数のヒント。
これは実行時エラーの発生位置を教えてくれるありがたい子です。
ただし、「その行自体が原因」とは限らず、直前の文や呼び出し元の関数が原因なこともあるので焦らず周辺を確認しましょう。
ORA-06502: PL/SQL: numeric or value error
「データの型がちょっと合ってないんですけど…」という悲鳴。
これは、たとえばVARCHAR2(10)の変数に20文字突っ込んだときや、NUMBERに文字列を入れようとしたときによく出ます。
DECLARE
name VARCHAR2(5);
BEGIN
name := 'TooLong'; -- ← ここで06502
END;
数字や文字列の「入りきらなかった」問題であることが多いので、変数の型や桁数をチェックしてみてください。
ORA-00900: invalid SQL statement
「そのSQL、文法的に受け付けません」
文末のセミコロン忘れ、BEGIN/ENDの抜け、そもそもPL/SQLブロックが正しく構成されてない…といった原因で出ます。
「PL/SQLさん、文法にとっても厳しい」ことを思い出しましょう。
ORA-01403: no data found
「SELECTしたけど、データなかったです」
カーソル処理やSELECT INTO文で結果が返らないと出るエラーです。
PostgreSQLと違い、Oracleでは「1件も返らない = エラー」になります。
SELECT name INTO v_name FROM users WHERE id = 9999;
-- データが存在しなければORA-01403
回避法:EXCEPTION WHEN NO_DATA_FOUND THEN …で優しく拾ってあげる。
エラーを見たら、まず“3点セット”をチェック!
①ORAエラー番号の意味
エラー辞書(Oracle公式 or 信頼できるQiita)でざっくり確認
②発生行と実行文の関係
at line ◯を起点に、前後の処理を落ち着いて見直す
③変数の型や桁数などの定義漏れ
VARCHAR2(5)なのに20文字突っ込んでないか?など
「なんかよくわからないけど動かない」そんなときは…
「ORAエラーは出てないけど結果が出ない」「ログにも何も出ない」
──そういうときに備えて、次章ではDBMS_OUTPUT.PUT_LINEを使ったログ出力&基本の“見える化”テクニックをご紹介します。
PL/SQLさん、口下手だけど、話せるようになると仲良くなれますよ。
DBMS_OUTPUT.PUT_LINEの正しい使い方と“出ない”問題
PL/SQLで初めてログを出そうと思ったときに、出てくる魔法の言葉、 DBMS_OUTPUT.PUT_LINE。
「これを使えばログが出力できるよ!」と聞いてウキウキで書いたものの……
実行しても、出ない。
何も。
ただ、静寂。
「あれ?出ないんですけど」問題、あるあるです
実はこのDBMS_OUTPUTくん、出力してくれる準備が必要なんです。
それを知らないと、何回PUT_LINE(‘Hello’);って書いても、画面は無言。 な
ぜかというと、“出力ON”にしないと何も表示してくれないタイプの人だからです(シャイなんですね)。
ログを出すための正しいステップ
出力をONにする
使用環境 | 出力ONの方法 |
---|---|
SQL*Plus | SET SERVEROUTPUT ON を実行 |
SQL Developer | ツールバーで「DBMS Output」タブを開いて「ON」に |
その他ツール | DBMS_OUTPUTビューアを自分で確認・ONにする必要あり |
まずは、「出力しろ」って言われてることをツールに伝えるのが先ってことですね。
メッセージを送る
BEGIN
DBMS_OUTPUT.PUT_LINE('Hello, PL/SQL!');
END;
/
これで晴れて出力されるはずです!
最初は、何も表示されないと「この関数壊れてるのでは…」と疑ってしまいますが、だいたいこっちの使い方が甘いだけです(過去の自分に言いたい)。
ちょっと便利な使い方
変数を表示する
DECLARE
score NUMBER := 88;
BEGIN
DBMS_OUTPUT.PUT_LINE('スコアは: ' || score);
END;
/
→ PostgreSQLのRAISE NOTICEに近い使い方ですね!
複数行出力したいときは複数回PUT_LINEする
ループの中でもどんどん書けます。配列要素を出したり、処理の経過を追いやすくなります。
よくあるつまずきポイント
症状 | 原因例 |
---|---|
出力がなにも表示されない | SERVEROUTPUTがONになっていない |
変数名が表示されてない | 文字列連結(’’)をミスってる。数値との連結時には暗黙変換に注意 |
長すぎるメッセージで切れる | 1行の最大長(デフォルトで32767文字)を超えるとエラーになる可能性あり |
ワンポイント:「出力されない!」→「あ、設定ONにした?」で90%は解決します!
DBMS_OUTPUTは開発向け、と割り切る
本番環境ではDBMS_OUTPUTが無効化されているケースが多いです。
そのため、しっかりログを残したい場合は「ログテーブルにINSERTする方法」に切り替えるのがベター。
このあたりは次章でも詳しく取り上げますね。
PL/SQLで困ったときは、PUT_LINEでこっそりログを出してもらうのが第一歩。
でもその前に、「お願いだから出てきてね」と言ってあげるのをお忘れなく。
EXCEPTIONの使い方と“エラーと仲良くなる方法”
PL/SQLでコードを書いていると、どこかしらでエラーに出会います。
突然のORA-06502、心当たりのないORA-01403。
でも実は、PL/SQLにはエラーと“ちゃんと付き合う”仕組みが用意されているんです。
それが、EXCEPTIONセクション。
EXCEPTIONって、何を守ってくれるの?
PL/SQLブロックでは、BEGIN〜ENDの処理中にエラーが出ると、通常はその場でドーンと止まってしまいます。
でも、EXCEPTIONセクションを使えば、「エラーが出たけど、ちゃんとキャッチして次の処理に進める」ということができるんです。
つまり、暴れ馬だったエラーに手綱をつけられるということですね。
基本構造はこうなります!
BEGIN
-- 何らかの処理
EXCEPTION
WHEN エラー名 THEN
-- エラーが発生したときの処理
END;
/
たとえば「0で割ったらエラーだけど、ちゃんとメッセージ出したい」場合はこう
BEGIN
DECLARE
v_result NUMBER;
BEGIN
v_result := 100 / 0; -- ゼロ除算でエラー
EXCEPTION
WHEN ZERO_DIVIDE THEN
DBMS_OUTPUT.PUT_LINE('ゼロ除算が発生しました');
END;
END;
/
よく使う例外とその使い方
エラー名 | 説明 |
---|---|
NO_DATA_FOUND | SELECT INTOで該当行が1件もない場合に発生 |
TOO_MANY_ROWS | SELECT INTOで複数件返ってきたら発生 |
ZERO_DIVIDE | ゼロ除算しようとしたとき |
OTHERS | 上記以外のすべてのエラーをキャッチする万能枠 |
WHEN OTHERS THENだけ書いておくと、想定外の事故もひとまず止められるので安心!
エラーメッセージを表示する方法
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('エラー発生!内容: ' || SQLERRM);
このSQLERRMは直前のエラー内容を文字列で返してくれる便利な関数です。
私はこれを入れてから、エラー調査のスピードがぐっと上がりました。
ハマりポイントも少し紹介
- EXCEPTIONは“BEGIN~END”の内側に書かないと効かない → EXCEPTIONは、そのBEGINブロックの“お守り”です。範囲がずれてると無効!
- WHEN OTHERSだけでは“何が起きたか”はわからない → 必ずSQLERRMを使ってエラー内容を出力しておくのがコツです。
「とりあえず囲っておく」が大事
特に最初のころは、処理ブロックの周りにBEGIN … EXCEPTION … END;を“お守り”として書いておく癖をつけておくと、突発エラーに動じなくなってきます。
そして、「落ちたら調べればいい」ではなく、「落ちたらどう振る舞うかを最初から決めておく」。
それが“PL/SQLのエラーハンドリング力”なんですね。
次章では、いよいよ本番環境でも使えるログ出力のテクニックをご紹介します。
DBMS_OUTPUTが使えない世界でも、ちゃんと自分の処理の足跡を残せるようになりますよ!
ログテーブルを使った“本番でも効く”デバッグ術
PL/SQLのデバッグに慣れてきたころ、ついにこの瞬間がやってきました。
「このプロシージャ、本番でも使うので、DBMS_OUTPUTは削除してくださいね」
──え、君、ずっと一緒に頑張ってきたじゃん……。
開発では心の支えだったPUT_LINEも、本番環境では基本“使えません”。
出力が抑止されていたり、セキュリティの観点でOFFになっているケースが多いのです。
そこで登場するのが、ログテーブルという頼れる相棒。 「
ログは口で言わず、ちゃんと書いて残そうね」というやつです。
ログテーブルってどんなもの?
要は処理の経過や異常内容をINSERTして残すためのテーブルです。
たとえばこういった構成:
CREATE TABLE debug_log (
id NUMBER GENERATED BY DEFAULT AS IDENTITY,
log_time DATE DEFAULT SYSDATE,
procedure_name VARCHAR2(100),
message VARCHAR2(4000)
);
- procedure_name:どのプロシージャから出力されたか識別
- message:内容は自由。状況、変数値、エラー内容など
ログを残す書き方の例
BEGIN
INSERT INTO debug_log (procedure_name, message)
VALUES ('generate_invoice', '請求データの登録処理開始');
-- 通常の処理(INSERTやUPDATEなど)
INSERT INTO debug_log (procedure_name, message)
VALUES ('generate_invoice', '請求処理 正常終了');
EXCEPTION
WHEN OTHERS THEN
INSERT INTO debug_log (procedure_name, message)
VALUES ('generate_invoice', 'エラー発生: ' || SQLERRM);
ROLLBACK;
END;
/
- 成功ログとエラーログを両方記録しておくと、あとで“どこで何が起きたか”の振り返りに役立ちます。
- SQLERRMを使えば、エラーの内容も詳細に記録できます。
運用での工夫ポイント
- ログ件数が膨大にならないように、保管期間を設ける → 例:1ヶ月以上前のログは削除する定期処理を設ける
- ユーザーごと・トランザクションごとのIDを持たせると分析しやすい → session_idやuser_id列を追加すると便利
- ログ内容に変数の値を埋め込んでおく → デバッグ時の「なんでこの値?」を減らせます
実際に救われた話
あるとき、請求データの生成処理が「なぜか途中で止まる」と報告を受けました。
でもDBMS_OUTPUTは本番では無効で、通常のSELECTではわからない…。
でも、ログテーブルにはちゃんと記録が残っていました。
[generate_invoice] 請求処理開始
[generate_invoice] 顧客ID: NULL → データ整合性違反でINSERT失敗
[generate_invoice] エラー発生: ORA-01400: cannot insert NULL into (...省略)
あのときほど「ログ残してて良かった…」と思ったことはありません。
“しゃべれないPL/SQL”でも、ログテーブルがその声を残してくれるんです。
まとめ:本番に強い“ログ力”をつけておこう
- DBMS_OUTPUTは開発の友、ログテーブルは本番の味方
- INSERT一発で状況が記録できる手軽さ、あなどれません
- ログ設計は、システム全体の“可観測性”を底上げしてくれます
次章では、そんな運用の中で私が実際にハマった「エラー」や「勘違い」と、その乗り越え方をお話ししていきます。
「あ〜それあるある!」な内容、たっぷりでお届けしますね。
実録!私がつまずいたPL/SQLエラーと解決法
PL/SQLを触り始めたころ、エラーにぶつかるたびに思っていました。
「この言語、ちょっとクセ強すぎない?」
PostgreSQL育ちの私にとって、Oracleの言語仕様はまるで“いとこ同士のようで、性格が正反対”。
同じように見えてるのに、いざ手を動かすと「え、それ怒るの⁉」ということの連続でした。
というわけで今回は、私がガチでやらかしたエラーたちと、その乗り越え方をご紹介します。
ケース①:NULLとの戦いに敗北
IF user_name = NULL THEN
-- なんか処理
END IF;
動かない。なんで?…そうか、Oracleさん、NULLとの比較はIS NULLしか受け付けないんでした。
解決法
IF user_name IS NULL THEN
-- 正しく比較できた!ありがとうEXCEPTION!
END IF;
PostgreSQLでは気づきにくいこの違い、PL/SQLでは初学者殺しNo.1かもしれません。
ケース②:セミコロンひとつで地獄に落ちる
BEGIN
DBMS_OUTPUT.PUT_LINE('こんにちは')
END;
/
ORA-06550:「なんか文法がおかしいよ」 → 文の終わりにはセミコロン!セミコロン!とにかくセミコロン!
セミコロンを省略したせいで、PL/SQL様に「君の構文、もはや認められない」と言われた瞬間でした。
ケース③:変数の型、そんなに厳格でしたっけ…
DECLARE
age NUMBER := 'twenty';
BEGIN
-- なんか処理
END;
ORA-06502:「数値に変換できないよー」
文字列をNUMBERに代入しようとして、見事に拒否されました。
PL/SQLは「自動変換してくれるでしょ?」という甘えを許してくれません。
解決法
値の型を見直す or TO_NUMBER()などで明示的に変換する
ケース④:SELECT INTOが爆発
SELECT email INTO v_email FROM users WHERE id = 999;
ORA-01403: no data found
「そのIDのユーザーいませんでした…」というだけなのに、PL/SQLではそれが即・例外になるんです。
解決法
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('データが見つかりませんでした');
ケース⑤:エラーメッセージが優しくなかった
ORA-06512 at line 5
ORA-06502: numeric or value error
…何が悪いのかわからないけど、なんかご機嫌ナナメ。
でもよく読むと、エラーが起きた行数も出ていて、エラー種別もついてる。
最初はただの“呪文”に見えていたメッセージたちが、今ではちょっとしたヒントの宝庫に思えてきます。
エラーは「ダメ出し」じゃなく「進捗アラート」だった
PL/SQLを触りはじめたころは、エラー=自分が悪い=心が折れるという負の三段跳びをしていた私ですが、今は少し考えが変わりました。
「エラーが出るってことは、今、成長してる途中なんだな」と。
むしろ、“つまずいた場所”こそが覚えどころ。これを読んでいるあなたが、もし今つまずいているなら、それは次に進むサインなのかもしれません。
次章では、いよいよこの記事のまとめに入ります。
これまで学んだことを振り返りながら、PL/SQLとの付き合い方やこれからのステップについて、一緒に整理してみましょう!
まとめ 〜エラーは味方!PL/SQLと仲良くなるために〜
ここまでお付き合いいただき、ありがとうございます。
「PL/SQLはなんだかとっつきにくい」「エラーメッセージがこわい」
──そんな第一印象を持っていた方も、少しずつ“わかるかも”という実感に変わってきたのではないでしょうか。
かくいう私も、最初はOracleさんのエラーメッセージに怯えながら、DBMS_OUTPUTにしがみつく日々でした。
でもある日、ログに「ORA-06502: numeric or value error」と出たときに、 「あ、これ、値の桁数足りなかったパターンだな」とすぐに気づけたんです。
……ちょっとだけ、うれしかったです。
少しずつ慣れていく、それでじゅうぶん
PL/SQLは、いわば“慎重で律儀なパートナー”のような存在です。
勝手な処理は許してくれないけれど、そのぶん堅実で頼りになる。
そして、正しく話しかければ、ちゃんと応えてくれる言語です。
- エラーメッセージは、「ちゃんと読めば答えをくれるヒント集」
- EXCEPTIONは、「事故っても受け止めてくれるセーフティネット」
- ログテーブルは、「無口なコードの“声”を残してくれる日記帳」
少しずつ、ひとつずつ、“読めた・動いた・わかった!”という小さな成功体験を積み重ねていけば、気がつけばPL/SQLとも自然と仲良くなれているはずです。
これから学びを広げるあなたへ
もしこの先…
- 「この処理、Oracle側で自動化できないかな?」と思ったら→トリガーの出番かもしれません
- 「何度も使う処理、まとめられないかな?」と思ったら→パッケージを調べてみるのもおすすめです
- 「ログにもっと詳しい情報を残したい!」と思ったら→ユーザー定義エラーやログレベル管理にもチャレンジしてみましょう
PL/SQLは、分かるほどにできることが増え、 できることが増えるほどに業務やチームを“裏から支える力”になっていきます。

PL/SQLに初めて触れたときの戸惑いや混乱、思わず笑ってしまうようなやらかし体験── そんな試行錯誤の記録が、この記事です。
もしあなたが今、まさに「エラーが読めなくて心折れそう…」という状態だとしても、大丈夫です。 私もそうでしたし、たぶん多くの人がそうです。 だからこの記事が、あなたの“つまずきポイント”を少しでも軽くできていたら、それ以上に嬉しいことはありません。
PL/SQLは、少しずつわかるようになります。 エラーは敵じゃなくて、成長の合図。 そしてその学びは、いつか誰かの役に立つかもしれません。
コメント