【完全ガイド】ORA-06512: at “…” line X の原因と解決方法|PL/SQL スタックトレース・DBMS_UTILITY.FORMAT_ERROR_BACKTRACE 徹底解説
- 作成日 2026.08.20
- Oracle Database
Oracle PL/SQL 開発者が実行時に必ず遭遇するエラー出力:
BEGIN my_proc; END;
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at "SCOTT.MY_PROC", line 42
ORA-06512: at line 1
「line X で発生」というシンプルなメッセージ。実は極めて重要な特性があります:
ORA-06512はPL/SQL 実行時のスタックトレース(呼び出し履歴の位置情報)ORA-06512単独では原因不明、併記されるORA-06502,ORA-01403,ORA-01422等が実際の原因- エラースタックの最初の実質エラーが根本原因
- 後続の
ORA-06512は呼び出し履歴を辿る位置情報
姉妹エラー ORA-06550 との決定的違い:
ORA-06550: PL/SQL コンパイル時の位置情報(PLS-xxx と組み合わせ)
ORA-06512: PL/SQL 実行時のスタックトレース(ORA-xxxx と組み合わせ)
現場で最も典型的なのは、ORA-06502 との組み合わせ:
ORA-06502: PL/SQL: numeric or value error ← 根本原因
ORA-06512: at "SCOTT.MY_PKG", line 42 ← パッケージの line 42 で発生
ORA-06512: at "SCOTT.WRAPPER", line 15 ← WRAPPER の line 15 から呼ばれた
ORA-06512: at line 1 ← 匿名ブロックの line 1 から呼ばれた
スタックトレースを下から上に読むことで、呼び出し経路が判明します:
line 1(匿名ブロック)
→ line 15(WRAPPER プロシージャ)
→ line 42(MY_PKG パッケージ)← ここでエラー発生
多くの日本語記事が「line 42 を見よ」で終わりますが、実務では:
ORA-06512は実際のエラーではないという原理- スタックトレースの正しい読み方(下から上)
DBMS_UTILITY.FORMAT_ERROR_BACKTRACEの活用DBMS_UTILITY.FORMAT_ERROR_STACKvsSQLERRMUTL_CALL_STACK(12c+) の高度な使用EXCEPTIONブロックの適切な設計RAISE_APPLICATION_ERRORによるカスタム例外- ネストブロックでの例外伝播
- トリガー内でのエラー処理
- Rails / Java / Python からの受信メッセージ解析
さらに、Oracle 10g で追加された DBMS_UTILITY.FORMAT_ERROR_BACKTRACE は、**「ORA-06512 の悩みを根本解決」**する画期的機能:
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error Stack: ' || DBMS_UTILITY.FORMAT_ERROR_STACK);
DBMS_OUTPUT.PUT_LINE('Backtrace: ' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
RAISE;
END;
これにより、例外発生元の完全な追跡が可能になります。
本記事では、ORA-06512: at "..." line X の完全な原因と解決方法を、リファレンスとして実用的に整理します。スタックトレースの読み方、10大発生パターン、DBMS_UTILITY の活用、5つの解決策、Rails/Java/Python 対応、実践シナリオ、FAQまで完全網羅。この1本で ORA-06512 に冷静に対処できるようになります。
- 1. 結論:スタックトレースの最初の実質エラーを見る
- 2. ORA-06512 の本質:ランタイムスタックトレース
- 3. 【原因①】ORA-06502 との組み合わせ(最頻出)
- 4. 【原因②】ORA-01403 NO_DATA_FOUND
- 5. 【原因③】ORA-01422 TOO_MANY_ROWS
- 6. 【原因④】ORA-04068 パッケージ状態破棄
- 7. 【原因⑤】ORA-00001 UNIQUE 制約違反
- 8. 【原因⑥】ORA-20xxx カスタム例外
- 9. 【原因⑦】ZERO_DIVIDE
- 10. 【原因⑧】VALUE_ERROR
- 11. 【原因⑨】トリガー内のエラー
- 12. 【原因⑩】ネストブロックでの例外伝播
- 13. スタックトレースの正しい読み方
- 14. 診断ツール完全リファレンス
- 15. 5つの解決策 完全リファレンス
- 16. Rails / Java / Python 対応
- 17. 実践シナリオ
- 18. トラブルシューティング
- 19. よくある質問(FAQ)
- 19.1. Q1. ORA-06512 と ORA-06550 の違い
- 19.2. Q2. line X はソースの何行目?
- 19.3. Q3. スタックトレースの読み方
- 19.4. Q4. DBMS_UTILITY.FORMAT_ERROR_STACK vs FORMAT_ERROR_BACKTRACE
- 19.5. Q5. UTL_CALL_STACK 使うべき?
- 19.6. Q6. Rails での対応
- 19.7. Q7. Java での対応
- 19.8. Q8. Python での対応
- 19.9. Q9. RAISE すべきか
- 19.10. Q10. RAISE_APPLICATION_ERROR の範囲
- 19.11. Q11. パッケージ状態エラーとの併発
- 19.12. Q12. Autonomous DB での違い
- 20. 参考リンク
- 21. まとめ
結論:スタックトレースの最初の実質エラーを見る
時間がない方向けに、最速の対処を先に示します。
エラーメッセージの構造
ORA-XXXX: <実際のエラー内容> ← 根本原因(これを見る)
ORA-06512: at "SCHEMA.OBJECT", line X ← 発生位置
ORA-06512: at "SCHEMA.CALLER", line Y ← 呼び出し元
ORA-06512: at line 1 ← 匿名ブロック
ORA-06512 は位置情報のみ、その直前の ORA-XXXX が実際のエラー。
スタックトレースの読み方
1. 最初の非-06512 エラー = 根本原因
2. 最初の ORA-06512 = エラー発生位置
3. 後続の ORA-06512 = 呼び出し履歴(下から上へ辿る)
姉妹エラー
| エラー | タイミング |
|---|---|
| ORA-06512 | PL/SQL 実行時(ランタイムスタック) |
| ORA-06550 | PL/SQL コンパイル時(位置情報) |
最速の診断
-- EXCEPTION で詳細情報取得
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('SQLCODE: ' || SQLCODE);
DBMS_OUTPUT.PUT_LINE('SQLERRM: ' || SQLERRM);
DBMS_OUTPUT.PUT_LINE('Error Stack: ' || DBMS_UTILITY.FORMAT_ERROR_STACK);
DBMS_OUTPUT.PUT_LINE('Backtrace: ' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
RAISE;
END;
5つの解決策
| # | 手法 | 使う場面 |
|---|---|---|
| ① | 最初の実質エラーを解決 | 基本 |
| ② | DBMS_UTILITY で詳細取得 | ログ強化 |
| ③ | EXCEPTION ハンドリング | 例外制御 |
| ④ | RAISE_APPLICATION_ERROR | カスタム例外 |
| ⑤ | UTL_CALL_STACK 使用 | 12c+ 高度診断 |
詳細は以下で解説します。
ORA-06512 の本質:ランタイムスタックトレース
位置情報のみ
ORA-06512 自体には固有の意味なし:
ORA-06512: at "SCHEMA.OBJECT", line X
↑
PL/SQL ソース内の位置
実際のエラーは併記される
ORA-XXXX: <実際のエラーメッセージ> ← これが原因
ORA-06512: at ... ← 位置
*多くの ORA- エラー**と組み合わせ:
- ORA-06502: 数値/値エラー
- ORA-01403: NO_DATA_FOUND
- ORA-01422: TOO_MANY_ROWS
- ORA-00001: UNIQUE 制約違反
- ORA-04068: パッケージ状態破棄
- ORA-20xxx: ユーザー定義例外
スタックの深さ
ORA-06502: PL/SQL: numeric or value error
ORA-06512: at "SCOTT.PKG_A", line 100 ← 最深部(エラー発生元)
ORA-06512: at "SCOTT.PKG_B", line 50 ← PKG_B から PKG_A 呼び出し
ORA-06512: at "SCOTT.PKG_C", line 20 ← PKG_C から PKG_B 呼び出し
ORA-06512: at line 1 ← 匿名ブロック(最上位)
下から上へ辿ることで呼び出し経路判明。
【原因①】ORA-06502 との組み合わせ(最頻出)
症状
DECLARE
v_name VARCHAR2(3);
BEGIN
v_name := 'John Doe'; -- 8 文字を 3 に代入
END;
/
-- ORA-06502: PL/SQL: numeric or value error: character string buffer too small
-- ORA-06512: at line 4
診断
ORA-06502 が根本原因、line 4 が発生位置。
解決
DECLARE
v_name VARCHAR2(100); -- 十分なサイズ
BEGIN
v_name := 'John Doe';
END;
/
ORA-06502 の詳細は ORA-06502: PL/SQL numeric or value error の記事も参照してください。
【原因②】ORA-01403 NO_DATA_FOUND
症状
DECLARE
v_name VARCHAR2(100);
BEGIN
SELECT name INTO v_name FROM emp WHERE id = 99999;
-- id=99999 が存在しない
END;
/
-- ORA-01403: no data found
-- ORA-06512: at line 4
解決A: EXCEPTION ハンドラ
DECLARE
v_name VARCHAR2(100);
BEGIN
SELECT name INTO v_name FROM emp WHERE id = 99999;
EXCEPTION
WHEN NO_DATA_FOUND THEN
v_name := 'N/A';
END;
/
解決B: 事前チェック
DECLARE
v_count NUMBER;
v_name VARCHAR2(100);
BEGIN
SELECT COUNT(*) INTO v_count FROM emp WHERE id = 99999;
IF v_count > 0 THEN
SELECT name INTO v_name FROM emp WHERE id = 99999;
END IF;
END;
/
【原因③】ORA-01422 TOO_MANY_ROWS
症状
DECLARE
v_name VARCHAR2(100);
BEGIN
SELECT name INTO v_name FROM emp WHERE dept_id = 10;
-- dept_id=10 に複数行
END;
/
-- ORA-01422: exact fetch returns more than requested number of rows
-- ORA-06512: at line 4
解決
A. ROWNUM で 1 件に:
SELECT name INTO v_name FROM emp
WHERE dept_id = 10 AND ROWNUM = 1;
B. カーソル使用:
FOR r IN (SELECT name FROM emp WHERE dept_id = 10) LOOP
-- 各行を処理
END LOOP;
C. EXCEPTION:
EXCEPTION
WHEN TOO_MANY_ROWS THEN
-- 複数行対応
END;
【原因④】ORA-04068 パッケージ状態破棄
症状
BEGIN
my_pkg.some_proc;
END;
/
-- ORA-04068: existing state of packages has been discarded
-- ORA-06512: at "SCOTT.MY_PKG", line 20
-- ORA-06512: at line 2
解決
再度実行(自動的にパッケージ再初期化):
-- 再実行で解消
BEGIN
my_pkg.some_proc;
END;
/
ORA-04068 の詳細は ORA-04068: existing state of packages の記事も参照してください。
【原因⑤】ORA-00001 UNIQUE 制約違反
症状
BEGIN
INSERT INTO users (id, email) VALUES (100, 'existing@example.com');
-- email が UNIQUE 制約に違反
END;
/
-- ORA-00001: unique constraint (SCOTT.UK_USERS_EMAIL) violated
-- ORA-06512: at line 2
解決
EXCEPTION ハンドラ:
BEGIN
INSERT INTO users (id, email) VALUES (100, 'existing@example.com');
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
-- 既存の場合の処理
UPDATE users SET email_verified = 1 WHERE email = 'existing@example.com';
END;
/
UNIQUE 制約は ORA-00001: unique constraint violated の記事も参照してください。
【原因⑥】ORA-20xxx カスタム例外
症状
CREATE OR REPLACE PROCEDURE validate_age(p_age NUMBER) IS
BEGIN
IF p_age < 0 OR p_age > 150 THEN
RAISE_APPLICATION_ERROR(-20001, '年齢が無効: ' || p_age);
END IF;
END;
/
BEGIN
validate_age(-5);
END;
/
-- ORA-20001: 年齢が無効: -5
-- ORA-06512: at "SCOTT.VALIDATE_AGE", line 4
-- ORA-06512: at line 2
解決
呼び出し元で EXCEPTION:
BEGIN
validate_age(-5);
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -20001 THEN
DBMS_OUTPUT.PUT_LINE('年齢エラー: ' || SQLERRM);
END IF;
END;
【原因⑦】ZERO_DIVIDE
症状
DECLARE
v_result NUMBER;
BEGIN
v_result := 100 / 0;
END;
/
-- ORA-01476: divisor is equal to zero
-- ORA-06512: at line 4
解決
DECLARE
v_result NUMBER;
v_divisor NUMBER := 0;
BEGIN
IF v_divisor != 0 THEN
v_result := 100 / v_divisor;
ELSE
v_result := 0;
END IF;
END;
/
ZERO_DIVIDE は ORA-01476: divisor is zero の記事も参照してください。
【原因⑧】VALUE_ERROR
症状
DECLARE
v_num NUMBER(3); -- 3 桁
BEGIN
v_num := 9999; -- 4 桁
END;
/
-- ORA-06502: PL/SQL: numeric or value error
-- ORA-06512: at line 4
解決
DECLARE
v_num NUMBER(4); -- 4 桁に拡張
BEGIN
v_num := 9999;
END;
/
【原因⑨】トリガー内のエラー
症状
CREATE TRIGGER trg_before_insert
BEFORE INSERT ON orders
FOR EACH ROW
DECLARE
v_customer_name VARCHAR2(100);
BEGIN
SELECT name INTO v_customer_name
FROM customers WHERE id = :NEW.customer_id;
-- 存在しない場合 NO_DATA_FOUND
END;
/
INSERT INTO orders (id, customer_id) VALUES (1, 99999);
-- ORA-01403: no data found
-- ORA-06512: at "SCOTT.TRG_BEFORE_INSERT", line 5
-- ORA-04088: error during execution of trigger 'SCOTT.TRG_BEFORE_INSERT'
解決
トリガー内で EXCEPTION:
CREATE OR REPLACE TRIGGER trg_before_insert
BEFORE INSERT ON orders
FOR EACH ROW
DECLARE
v_customer_name VARCHAR2(100);
BEGIN
BEGIN
SELECT name INTO v_customer_name
FROM customers WHERE id = :NEW.customer_id;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20001,
'顧客不在: ' || :NEW.customer_id);
END;
END;
/
トリガー系は ORA-04091: mutating table の記事も参照してください。
【原因⑩】ネストブロックでの例外伝播
症状
BEGIN
BEGIN
SELECT name INTO v_name FROM emp WHERE id = 999;
END;
-- 内側の例外がキャッチされず、外側に伝播
END;
/
-- ORA-01403: no data found
-- ORA-06512: at line 3
-- ORA-06512: at line 5
解決
適切なレベルで EXCEPTION:
BEGIN
BEGIN
SELECT name INTO v_name FROM emp WHERE id = 999;
EXCEPTION
WHEN NO_DATA_FOUND THEN
v_name := 'Unknown';
END;
-- 外側は正常続行
END;
/
スタックトレースの正しい読み方
基本原則
1. 最初の非-06512 エラー = 根本原因
2. 最初の ORA-06512 = エラー発生位置(最深部)
3. 続く ORA-06512 = 呼び出し履歴(下から上)
実例
ORA-06502: PL/SQL: numeric or value error ← 根本原因
ORA-06512: at "SCOTT.PKG_INNER", line 25 ← ここで発生(最深部)
ORA-06512: at "SCOTT.PKG_MIDDLE", line 15 ← ここから呼ばれた
ORA-06512: at "SCOTT.PKG_OUTER", line 5 ← ここから呼ばれた
ORA-06512: at line 1 ← 匿名ブロックから呼ばれた
呼び出し経路:
匿名ブロック line 1
→ PKG_OUTER.something line 5
→ PKG_MIDDLE.something line 15
→ PKG_INNER.something line 25 ← ここで ORA-06502 発生
診断ツール完全リファレンス
SQLERRM / SQLCODE
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('SQLCODE: ' || SQLCODE);
-- -6502, -1403 等の数値
DBMS_OUTPUT.PUT_LINE('SQLERRM: ' || SQLERRM);
-- ORA-06502: PL/SQL: numeric...
END;
DBMS_UTILITY.FORMAT_ERROR_STACK
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(
'Error Stack: ' || CHR(10) ||
DBMS_UTILITY.FORMAT_ERROR_STACK
);
END;
出力例:
Error Stack:
ORA-06502: PL/SQL: numeric or value error
DBMS_UTILITY.FORMAT_ERROR_BACKTRACE
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(
'Backtrace: ' || CHR(10) ||
DBMS_UTILITY.FORMAT_ERROR_BACKTRACE
);
END;
出力例:
Backtrace:
ORA-06512: at "SCOTT.PKG_INNER", line 25
ORA-06512: at "SCOTT.PKG_MIDDLE", line 15
Oracle 10g+ で追加。呼び出しスタック完全表示。
UTL_CALL_STACK (12c+)
DECLARE
v_depth PLS_INTEGER;
BEGIN
-- ... エラー発生 ...
EXCEPTION
WHEN OTHERS THEN
v_depth := UTL_CALL_STACK.error_depth;
FOR i IN 1..v_depth LOOP
DBMS_OUTPUT.PUT_LINE(
'Error ' || i || ': ' ||
UTL_CALL_STACK.error_number(i) || ' - ' ||
UTL_CALL_STACK.error_msg(i)
);
END LOOP;
END;
12c+ の高度な API、構造化されたスタック情報。
5つの解決策 完全リファレンス
解決策① 最初の実質エラーを解決
ORA-06512 は無視して、その前の ORA-XXXX を見る
根本原因を解決 → ORA-06512 も自動的に消える
解決策② DBMS_UTILITY で詳細取得
CREATE OR REPLACE PROCEDURE log_error IS
BEGIN
-- 業務ロジック
EXCEPTION
WHEN OTHERS THEN
-- 詳細ログ
INSERT INTO error_log (
error_time, error_code, error_message, backtrace
) VALUES (
SYSTIMESTAMP,
SQLCODE,
DBMS_UTILITY.FORMAT_ERROR_STACK,
DBMS_UTILITY.FORMAT_ERROR_BACKTRACE
);
COMMIT;
RAISE; -- 上位に伝播
END;
/
解決策③ EXCEPTION ハンドリング
BEGIN
-- 処理
EXCEPTION
WHEN NO_DATA_FOUND THEN
-- データなし対応
WHEN TOO_MANY_ROWS THEN
-- 複数行対応
WHEN VALUE_ERROR THEN
-- 値エラー対応
WHEN OTHERS THEN
-- その他
RAISE;
END;
解決策④ RAISE_APPLICATION_ERROR
IF invalid_condition THEN
RAISE_APPLICATION_ERROR(
-20001,
'意味のあるエラーメッセージ'
);
END IF;
アプリ層で捕捉しやすいカスタム例外。
解決策⑤ UTL_CALL_STACK (12c+)
FOR i IN 1..UTL_CALL_STACK.error_depth LOOP
DBMS_OUTPUT.PUT_LINE(
UTL_CALL_STACK.error_number(i) || ' - ' ||
UTL_CALL_STACK.error_msg(i)
);
END LOOP;
Rails / Java / Python 対応
Rails ActiveRecord
エラースタック解析:
begin
ActiveRecord::Base.connection.execute("BEGIN my_proc; END;")
rescue ActiveRecord::StatementInvalid => e
# エラースタック全体
Rails.logger.error e.message
# 根本原因(06512 以外の最初)を抽出
lines = e.message.split("\n")
root_cause = lines.find { |l| l.match(/ORA-/) && !l.match(/ORA-06512/) }
Rails.logger.error "根本原因: #{root_cause}"
# ORA-06512 で位置情報
positions = lines.select { |l| l.match(/ORA-06512/) }
positions.each { |p| Rails.logger.error "位置: #{p}" }
end
Rails 8 系の詳細は Rails 8 アップグレードガイドの記事、find/find_by/where の記事も参照してください。
Java (JDBC)
try {
stmt.execute("BEGIN my_proc; END;");
} catch (SQLException e) {
logger.error("Error: " + e.getMessage());
// スタック解析
String[] lines = e.getMessage().split("\n");
// 根本原因
for (String line : lines) {
if (line.matches(".*ORA-\\d+.*") && !line.contains("ORA-06512")) {
logger.error("根本原因: " + line);
break;
}
}
// 位置情報
for (String line : lines) {
if (line.contains("ORA-06512")) {
logger.error("位置: " + line);
}
}
}
Python (oracledb)
import oracledb
import re
def parse_plsql_error(message):
lines = message.split('\n')
root_cause = None
positions = []
for line in lines:
if 'ORA-06512' in line:
positions.append(line.strip())
elif re.search(r'ORA-\d+', line) and not root_cause:
root_cause = line.strip()
return root_cause, positions
try:
cursor.execute("BEGIN my_proc; END;")
except oracledb.DatabaseError as e:
error_obj, = e.args
root, positions = parse_plsql_error(error_obj.message)
print(f"根本原因: {root}")
for pos in positions:
print(f"位置: {pos}")
実践シナリオ
シナリオ1:本番エラーの緊急診断
-- 1. エラーログテーブル作成
CREATE TABLE error_log (
error_time TIMESTAMP DEFAULT SYSTIMESTAMP,
error_code NUMBER,
error_msg VARCHAR2(4000),
backtrace VARCHAR2(4000),
call_stack VARCHAR2(4000)
);
-- 2. 全プロシージャで統一エラーハンドリング
CREATE OR REPLACE PROCEDURE log_error IS
BEGIN
-- 実装
EXCEPTION
WHEN OTHERS THEN
INSERT INTO error_log VALUES (
SYSTIMESTAMP, SQLCODE, SQLERRM,
DBMS_UTILITY.FORMAT_ERROR_BACKTRACE,
DBMS_UTILITY.FORMAT_CALL_STACK
);
COMMIT;
RAISE;
END;
シナリオ2:スタックトレース解析
本番エラー:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at "APP.PKG_INVOICE", line 145
ORA-06512: at "APP.PKG_ORDER", line 67
ORA-06512: at "APP.WEB_HANDLER", line 25
ORA-06512: at line 1
解析:
1. 根本原因: ORA-06502(文字列バッファ)
2. 発生位置: APP.PKG_INVOICE line 145
3. 呼び出し履歴:
line 1 (匿名) → WEB_HANDLER:25 → PKG_ORDER:67 → PKG_INVOICE:145
シナリオ3:DBMS_UTILITY で詳細ログ
CREATE OR REPLACE PROCEDURE process_order(p_id NUMBER) IS
BEGIN
-- 業務ロジック
UPDATE orders SET status = 'processed' WHERE id = p_id;
EXCEPTION
WHEN OTHERS THEN
INSERT INTO error_log VALUES (
SYSTIMESTAMP,
SQLCODE,
DBMS_UTILITY.FORMAT_ERROR_STACK,
DBMS_UTILITY.FORMAT_ERROR_BACKTRACE
);
COMMIT;
RAISE;
END;
/
シナリオ4:Rails ログでの詳細化
class ApplicationController < ActionController::Base
rescue_from ActiveRecord::StatementInvalid do |e|
if e.message.include?("ORA-06512")
# 詳細ログ
Rails.logger.error("PL/SQL Error:")
e.message.split("\n").each do |line|
Rails.logger.error(" #{line}")
end
# ユーザー向けエラー
render json: { error: "システムエラーが発生しました" }, status: 500
else
raise
end
end
end
シナリオ5:Java Spring Boot での統一
@ControllerAdvice
public class GlobalExceptionHandler {
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler(SQLException.class)
public ResponseEntity<?> handleSQLException(SQLException e) {
if (e.getMessage().contains("ORA-06512")) {
log.error("PL/SQL Runtime Error:");
for (String line : e.getMessage().split("\n")) {
log.error(" {}", line);
}
}
return ResponseEntity.status(500).body("Internal Error");
}
}
シナリオ6:Python での詳細ログ
import oracledb
import logging
logger = logging.getLogger(__name__)
def call_stored_proc(cursor, proc_name):
try:
cursor.callproc(proc_name)
except oracledb.DatabaseError as e:
error_obj, = e.args
logger.error(f"PL/SQL Runtime Error in {proc_name}:")
for line in error_obj.message.split('\n'):
logger.error(f" {line}")
raise
シナリオ7:UTL_CALL_STACK (12c+)
CREATE OR REPLACE PROCEDURE detailed_error_log IS
v_depth PLS_INTEGER;
BEGIN
-- 業務処理
EXCEPTION
WHEN OTHERS THEN
v_depth := UTL_CALL_STACK.error_depth;
FOR i IN 1..v_depth LOOP
DBMS_OUTPUT.PUT_LINE(
'Error ' || i || ': [' ||
UTL_CALL_STACK.error_number(i) || '] ' ||
UTL_CALL_STACK.error_msg(i)
);
END LOOP;
RAISE;
END;
/
シナリオ8:Docker Oracle テスト
docker exec -it oracle-xe sqlplus scott/tiger <<EOF
CREATE PROCEDURE test_proc IS
v_x NUMBER;
BEGIN
SELECT id INTO v_x FROM emp WHERE id = 99999;
END;
/
BEGIN test_proc; END;
/
-- ORA-01403: no data found
-- ORA-06512: at "SCOTT.TEST_PROC", line 4
-- ORA-06512: at line 1
EOF
Docker 関連は docker daemon 接続エラーの記事、Docker no space left on device の記事も参照してください。
シナリオ9:CI/CD パイプラインでの例外検出
- name: Run PL/SQL tests
run: |
sqlplus -s $DB_USER/$DB_PW <<EOF
SET SERVEROUTPUT ON
BEGIN
run_tests;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('TEST FAILED');
DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
RAISE;
END;
/
EOF
Kamal 2 デプロイの詳細は Kamal 2 デプロイの記事を参照してください。
シナリオ10:Autonomous DB
-- Autonomous DB でも同じ動作
-- SQL Developer Web でスタックトレース確認
-- APEX でエラーログ管理
トラブルシューティング
ORA-06512 だけ見て解決できない
そもそも ORA-06512 は位置情報のみ。その前の ORA-XXXX を確認。
スタックが長すぎる
根本原因(最初の非-06512) を優先、他は無視可能。
line 番号がずれる
パッケージ本体のみ再コンパイル、またはソースコードとの照合。
RAISE の使い所
EXCEPTION
WHEN OTHERS THEN
-- ログ記録
RAISE; -- 上位に伝播(推奨)
END;
ログだけで無視は問題を隠蔽、RAISE で伝播が原則。
アプリからのエラー受信
JDBC / oracledb は全スタックを含む。改行で分割して解析。
PostgreSQL からの移行
PG の RAISE EXCEPTION は Oracle の RAISE_APPLICATION_ERROR に対応。
よくある質問(FAQ)
Q1. ORA-06512 と ORA-06550 の違い
- 06512: 実行時スタックトレース
- 06550: コンパイル時の位置情報
Q2. line X はソースの何行目?
PL/SQL ソースの行番号、CREATE OR REPLACE 部分から数える。
Q3. スタックトレースの読み方
下から上(呼び出し順)、最上部が最深部(エラー発生元)。
Q4. DBMS_UTILITY.FORMAT_ERROR_STACK vs FORMAT_ERROR_BACKTRACE
- ERROR_STACK: エラーメッセージ全体
- ERROR_BACKTRACE: ORA-06512 の履歴のみ
Q5. UTL_CALL_STACK 使うべき?
12c+ で複雑な例外解析に有用、単純なら FORMAT_ERROR_BACKTRACE で十分。
Q6. Rails での対応
エラーメッセージ改行分割 + 06512 除外で根本原因抽出。
Q7. Java での対応
SQLException.getMessage() を改行で split、正規表現で解析。
Q8. Python での対応
oracledb.DatabaseError の message を解析。
Q9. RAISE すべきか
推奨、例外を無視すると問題隠蔽。
Q10. RAISE_APPLICATION_ERROR の範囲
-20000 〜 -20999 のカスタム例外。
Q11. パッケージ状態エラーとの併発
ORA-04068 + ORA-06512 の組み合わせ、再実行で解消することが多い。
Q12. Autonomous DB での違い
同じ動作、SQL Developer Web / APEX で管理。
参考リンク
Oracle 公式
- Oracle Database Error Messages: ORA-06512
- Oracle PL/SQL Language Reference: Error Handling
- DBMS_UTILITY Package
- UTL_CALL_STACK Package
まとめ
ORA-06512: at "..." line X の要点を再整理します。
エラーの本質
PL/SQL 実行時のスタックトレース(位置情報)
→ それ単独では意味なし
→ 併記される ORA-XXXX が実際の原因
エラーメッセージの構造
ORA-XXXX: <実際のエラー> ← 根本原因
ORA-06512: at "SCHEMA.OBJECT", line X ← 発生位置(最深部)
ORA-06512: at "SCHEMA.CALLER", line Y ← 呼び出し元
ORA-06512: at line 1 ← 匿名ブロック
スタックトレースの読み方
1. 最初の非-06512 エラー = 根本原因
2. 最初の ORA-06512 = エラー発生位置
3. 続く ORA-06512 = 呼び出し履歴(下から上)
姉妹エラー
| エラー | タイミング |
|---|---|
| ORA-06512 | PL/SQL 実行時 |
| ORA-06550 | PL/SQL コンパイル時 |
10大原因
| # | 併発エラー | 対処 |
|---|---|---|
| ① | ORA-06502 (数値/値) | 型・サイズ確認 |
| ② | ORA-01403 (NO_DATA_FOUND) | EXCEPTION or 事前チェック |
| ③ | ORA-01422 (TOO_MANY_ROWS) | ROWNUM=1 or カーソル |
| ④ | ORA-04068 (パッケージ状態) | 再実行 |
| ⑤ | ORA-00001 (UNIQUE) | DUP_VAL_ON_INDEX ハンドラ |
| ⑥ | ORA-20xxx (カスタム) | 呼び出し元で捕捉 |
| ⑦ | ORA-01476 (ZERO_DIVIDE) | 事前チェック |
| ⑧ | VALUE_ERROR | 型・サイズ調整 |
| ⑨ | トリガー内 | 内部 EXCEPTION |
| ⑩ | ネストブロック伝播 | 適切なレベルで捕捉 |
診断ツール
-- エラースタック(メッセージ)
DBMS_UTILITY.FORMAT_ERROR_STACK
-- バックトレース(06512 履歴)
DBMS_UTILITY.FORMAT_ERROR_BACKTRACE
-- 12c+ 構造化 API
UTL_CALL_STACK.error_number(i)
UTL_CALL_STACK.error_msg(i)
-- 従来
SQLCODE
SQLERRM
5つの解決策
-- ① 最初の実質エラー解決
-- ② DBMS_UTILITY で詳細取得
EXCEPTION
WHEN OTHERS THEN
INSERT INTO error_log VALUES (
SYSTIMESTAMP, SQLCODE,
DBMS_UTILITY.FORMAT_ERROR_STACK,
DBMS_UTILITY.FORMAT_ERROR_BACKTRACE
);
RAISE;
-- ③ EXCEPTION ハンドリング
EXCEPTION
WHEN NO_DATA_FOUND THEN ...
WHEN TOO_MANY_ROWS THEN ...
-- ④ RAISE_APPLICATION_ERROR
RAISE_APPLICATION_ERROR(-20001, 'エラー');
-- ⑤ UTL_CALL_STACK (12c+)
FOR i IN 1..UTL_CALL_STACK.error_depth LOOP
DBMS_OUTPUT.PUT_LINE(UTL_CALL_STACK.error_msg(i));
END LOOP;
各言語での対応
Rails: e.message.split('\n') で解析
Java: SQLException.getMessage() 分割
Python: oracledb.DatabaseError.message 分割
共通: ORA-06512 除外して根本原因抽出
予防のポイント
1. 全プロシージャで EXCEPTION ハンドラ
2. DBMS_UTILITY.FORMAT_ERROR_BACKTRACE でログ
3. RAISE で上位に例外伝播
4. RAISE_APPLICATION_ERROR で意味のあるエラー
5. アプリ側で解析ロジック実装
6. 統一されたエラーログテーブル
7. CI/CD でエラー検証
8. UTL_CALL_STACK (12c+) 活用
9. スタックトレースを下から読む
10. 根本原因を修正、隠蔽しない
これらの知識は、Oracle での PL/SQL 開発・デバッグ・DBA 業務・E-Business Suite 運用・Rails / Java / Python アプリ運用・エラーログ設計・監視体制構築・本番デプロイなど、あらゆる場面で活用できます。本記事をブックマークしておけば、ORA-06512 に出会っても冷静に的確に対処できるようになります。
本記事は2026年6月時点の情報をもとに、Oracle Database 19c〜23ai での動作確認・公式ドキュメントに基づき作成しています。Oracle のバージョンにより挙動が異なる場合があるため、最新の情報は Oracle 公式ドキュメント(docs.oracle.com)もあわせてご確認ください。
-
前の記事
【完全ガイド】ORA-01455: converting column overflows integer datatype の原因と解決方法|NUMBER 変換・JDBC getInt・PL/SQL 徹底解説 2026.08.19
-
次の記事
【完全ガイド】ORA-00257: archiver error. Connect internal only, until freed の原因と解決方法|FRA フル・RMAN・Data Guard 徹底解説 2026.08.20
コメントを書く