【Oracle】ORA-06576の原因と解決方法|not a valid function or procedure name の直し方

【Oracle】ORA-06576の原因と解決方法|not a valid function or procedure name の直し方 Oracle

ORA-06576: not a valid function or procedure name は、Oracleが呼び出すべき関数またはプロシージャを、指定された呼び出し形式では見つけられない時に発生するエラーです。名前が間違っているだけでなく、関数をプロシージャの形で呼んでいる、プロシージャを関数の形で呼んでいる、スキーマ名やシノニム、権限、パッケージ名が合っていない場合にも起きます。

Oracle公式のORA-06576説明では、INTO 句がある場合は関数、INTO 句がない場合はプロシージャを探すが、該当する呼び出し先が見つからないことが原因とされています。そのため、対処では「呼び出し構文」と「実体オブジェクトの種類」を合わせます。

先に結論
ORA-06576が出たら、まず対象が関数なのかプロシージャなのかを確認します。関数は SELECT function_name(...) FROM dual または CALL function_name(...) INTO ...、プロシージャは EXEC procedure_name(...)CALL procedure_name(...)BEGIN procedure_name(...); END; の形で呼びます。対象がINVALIDなら ORA-06575、未宣言なら PLS-00201 も確認します。
スポンサーリンク

ORA-06576とは

ORA-06576は、名前解決や呼び出し形式の問題です。対象オブジェクトが存在していても、関数をプロシージャとして呼ぶ、プロシージャを関数として呼ぶ、パッケージ内サブプログラムを単体名で呼ぶ、といった場合に発生します。

確認点 よくある原因 見る場所
関数かプロシージャか 呼び出し構文が合っていない USER_OBJECTS、仕様書
名前が正しいか タイプミス、パッケージ名漏れ USER_PROCEDURES
スキーマが正しいか 別スキーマの同名/未修飾呼び出し ALL_OBJECTS
シノニムが正しいか シノニム先が違う/存在しない USER_SYNONYMS
権限があるか 実行権限がない GRANT EXECUTE
INVALIDではないか コンパイルエラー付き USER_ERRORS

関数とプロシージャの作り方・呼び出し方は ストアドプロシージャ・ファンクション作成ガイド にまとめています。この記事では、ORA-06576の切り分けに必要な呼び出し形式を中心に整理します。

関数をプロシージャの形で呼んでいる

関数は戻り値を返すため、SQLから値として使うか、CALL ... INTO のように戻り先を指定します。戻り値を受け取らずに CALL すると、Oracleはプロシージャとして探すためORA-06576になることがあります。

ora06576-call-function-without-into.sql
CREATE OR REPLACE FUNCTION calc_tax(p_amount NUMBER)
RETURN NUMBER
IS
BEGIN
  RETURN p_amount * 0.1;
END;
/

-- NG: 戻り値を受け取っていない
CALL calc_tax(1000);
-- ORA-06576: not a valid function or procedure name

関数なら、SQLで値として呼び出します。

ora06576-call-function-fixed.sql
-- SELECTで呼ぶ
SELECT calc_tax(1000) AS tax
FROM dual;

-- SQL*PlusなどでCALLを使う場合は戻り値を受ける
VARIABLE v_tax NUMBER
CALL calc_tax(1000) INTO :v_tax;
PRINT v_tax

プロシージャを関数の形で呼んでいる

プロシージャは戻り値を返しません。SELECT procedure_name(...) FROM dual のように値として呼ぶと、関数として探されるため失敗します。

ora06576-select-procedure.sql
CREATE OR REPLACE PROCEDURE refresh_cache
IS
BEGIN
  NULL;
END;
/

-- NG: プロシージャを関数のように呼んでいる
SELECT refresh_cache()
FROM dual;

プロシージャは、EXECCALL、またはPL/SQLブロックで呼びます。

ora06576-procedure-fixed.sql
EXEC refresh_cache;

CALL refresh_cache();

BEGIN
  refresh_cache;
END;
/

CALL / EXEC / SELECTの使い分け

呼び出し方法を間違えないために、関数・プロシージャ・パッケージ内サブプログラムの基本形を押さえます。

対象 呼び出し例 ポイント
単体関数 SELECT f(x) FROM dual 戻り値を値として使う
単体関数 CALL f(x) INTO :v CALLなら戻り値の受け取り先が必要
単体プロシージャ EXEC p(x) SQL*Plus/SQL Developerでよく使う
単体プロシージャ CALL p(x) 戻り値なしで呼ぶ
パッケージ関数 SELECT pkg.f(x) FROM dual パッケージ名を付ける
パッケージプロシージャ BEGIN pkg.p(x); END; 複雑な呼び出しに向く

スキーマ名・パッケージ名が足りない

開発環境では同じスキーマにいるため動いていても、本番や別ユーザーから実行すると名前解決に失敗することがあります。別スキーマの関数やプロシージャは、必要に応じて schema.object_name の形で修飾します。

schema-qualified-call.sql
-- 別スキーマの関数を呼ぶ
SELECT app_user.calc_tax(1000)
FROM dual;

-- パッケージ内プロシージャを呼ぶ
BEGIN
  app_user.pkg_batch.refresh_cache;
END;
/

パッケージ内のサブプログラムは、単体名ではなく package_name.subprogram_name で呼びます。パッケージ仕様に公開されていない内部サブプログラムは、外部から直接呼べません。

CURRENT_SCHEMAとダブルクォート名に注意する

ALTER SESSION SET CURRENT_SCHEMA で見ているスキーマを切り替えている環境では、アプリ、SQL Developer、バッチで CURRENT_SCHEMA が違うだけで、同じSQLでも解決先が変わります。また、"Calc_Tax" のようにダブルクォート付きで作成した名前は大文字小文字を区別するため、通常の CALC_TAX と同じ名前として扱われません。

check-current-schema-and-quoted-name.sql
SELECT sys_context('USERENV', 'CURRENT_SCHEMA') AS current_schema
FROM dual;

-- ダブルクォート付きで作成された名前は、表示された文字種のまま確認する
SELECT owner,
       object_name,
       object_type,
       status
FROM all_objects
WHERE object_name IN ('CALC_TAX', 'Calc_Tax');

名前と種類をデータディクショナリで確認する

対象が関数なのかプロシージャなのか、単体なのかパッケージ内なのかは、データディクショナリで確認できます。まず USER_OBJECTS、別スキーマなら ALL_OBJECTS を確認します。

check-function-procedure-name.sql
SELECT owner,
       object_name,
       object_type,
       status
FROM all_objects
WHERE object_name IN ('CALC_TAX', 'REFRESH_CACHE', 'PKG_BATCH')
  AND object_type IN ('FUNCTION', 'PROCEDURE', 'PACKAGE');

パッケージ内のプロシージャや関数は、ALL_PROCEDURES で確認できます。

check-package-subprograms.sql
SELECT owner,
       object_name,
       procedure_name,
       object_type
FROM all_procedures
WHERE owner = 'APP_USER'
  AND object_name = 'PKG_BATCH'
ORDER BY procedure_name;

名前と種類が合っているのに失敗する場合は、引数の数や型が合っているかも確認します。特に同名のオーバーロードがあるパッケージでは、呼び出し側の引数がどの定義にも一致しないと、ORA-06576ではなく PLS-00306 として表面化することがあります。

check-arguments-and-overloads.sql
SELECT owner,
       package_name,
       object_name,
       overload,
       argument_name,
       position,
       in_out,
       data_type
FROM all_arguments
WHERE owner = 'APP_USER'
  AND object_name IN ('CALC_TAX', 'REFRESH_CACHE')
ORDER BY package_name, object_name, overload, position;

シノニム経由で呼ぶ場合

シノニムを使っている場合、呼んでいる名前と実体が一致しているか確認します。シノニムが古いオブジェクトを指している、別スキーマの同名オブジェクトを見ている、実体が削除されている、というケースがあります。

check-synonym-for-ora06576.sql
SELECT synonym_name,
       table_owner,
       table_name,
       db_link
FROM all_synonyms
WHERE synonym_name = 'CALC_TAX';

シノニム先が他スキーマなら、実体側の ALL_OBJECTS と実行権限も確認します。権限不足の切り分けは ORA-01031の権限不足ガイド も参考になります。

権限不足・未宣言との違い

ORA-06576は名前が有効な関数/プロシージャとして解決できないエラーですが、周辺には似たエラーがあります。権限不足や未宣言が根本原因の場合、PLS-00201ORA-01031 として出ることもあります。

ORA-06576

主な意味: 有効な関数/プロシージャ名として呼べない

確認先: 呼び出し構文、名前解決、スキーマ修飾

関連記事: この記事

ORA-06575

主な意味: 関数/パッケージがINVALID状態

確認先: USER_ERRORSUSER_OBJECTS

関連記事: ORA-06575

ORA-06550

主な意味: PL/SQLコンパイル/実行呼び出しのエラー

確認先: PLSエラー、行番号、実際に失敗しているSQLやPL/SQL

関連記事: ORA-06550

PLS-00201

主な意味: 識別子が宣言されていない、または現在のユーザーから見えない

確認先: 名前、権限、スキーマ、シノニム

関連記事: PLS-00201

ORA-06508

主な意味: 呼び出すプログラムユニットが見つからない、または使えない

確認先: 依存先、INVALID状態、再コンパイル結果

関連記事: ORA-06508

DBMS_SCHEDULERで起きる場合

DBMS_SCHEDULERのジョブでORA-06576が出る場合、job_action の名前解決やジョブタイプが原因のことがあります。引数付きで複雑に呼ぶ場合は、STORED_PROCEDURE より PLSQL_BLOCK にして明示的に呼ぶ方が分かりやすいことがあります。

scheduler-stored-procedure-action.sql
BEGIN
  DBMS_SCHEDULER.CREATE_JOB(
    job_name   => 'JOB_REFRESH_CACHE',
    job_type   => 'STORED_PROCEDURE',
    job_action => 'APP_USER.PKG_BATCH.REFRESH_CACHE',
    enabled    => TRUE
  );
END;
/
scheduler-plsql-block-action.sql
BEGIN
  DBMS_SCHEDULER.CREATE_JOB(
    job_name   => 'JOB_REFRESH_CACHE',
    job_type   => 'PLSQL_BLOCK',
    job_action => 'BEGIN APP_USER.PKG_BATCH.REFRESH_CACHE; END;',
    enabled    => TRUE
  );
END;
/

DBMS_SCHEDULERの基本は DBMS_SCHEDULERガイド、運用寄りのジョブ管理は DBMS_SCHEDULERジョブ管理ガイド も参考になります。

JDBCやアプリから呼ぶ場合

Javaや.NETなどのアプリから呼ぶ場合も、関数とプロシージャの呼び分けが重要です。JDBCの CallableStatement では、関数は戻り値を登録する呼び方、プロシージャは戻り値なしの呼び方になります。

jdbc-function-vs-procedure.java
// function
CallableStatement f = conn.prepareCall("{ ? = call CALC_TAX(?) }");
f.registerOutParameter(1, java.sql.Types.NUMERIC);
f.setBigDecimal(2, amount);
f.execute();

// procedure
CallableStatement p = conn.prepareCall("{ call REFRESH_CACHE() }");
p.execute();

SQL Developerでは動くのにアプリで失敗する場合、接続ユーザー、カレントスキーマ、シノニム、権限、呼び出し構文が違っていないか確認します。

調査手順

ORA-06576は、呼び出し構文の間違いと名前解決の問題を分けると早く切り分けられます。

ora06576-investigation-flow.sql
-- 1. 対象名と種類を確認
SELECT owner, object_name, object_type, status
FROM all_objects
WHERE object_name = 'CALC_TAX';

-- 2. パッケージ内サブプログラムを確認
SELECT owner, object_name, procedure_name
FROM all_procedures
WHERE object_name = 'PKG_BATCH';

-- 3. シノニムを確認
SELECT synonym_name, table_owner, table_name
FROM all_synonyms
WHERE synonym_name = 'CALC_TAX';

-- 4. INVALIDならエラーを確認
SELECT name, type, line, text
FROM user_errors
WHERE name IN ('CALC_TAX', 'PKG_BATCH')
ORDER BY sequence;

エラースタックに ORA-06512 が出ている場合は、ORA-06512の読み方 で呼び出し元の行番号も確認します。

チェックリスト

項目 OKの状態
関数/プロシージャの種類を確認した 呼び出し構文が種類に合っている
スキーマ名を確認した 必要ならschema.objectで修飾している
パッケージ名を付けている pkg.proc / pkg.funcで呼んでいる
シノニム先を確認した 実体のOWNERとOBJECT_NAMEが正しい
実行権限を確認した GRANT EXECUTEがある
INVALIDではない USER_OBJECTS.STATUS = VALID
アプリの接続ユーザーを確認した SQL Developerと同じ前提で実行している

よくある質問

関数をEXECで呼べますか?

戻り値を使わない形では混乱しやすいです。関数は SELECT function(...) FROM dual で値として呼ぶか、CALL ... INTO で戻り値を受けます。

SQL Developerでは動くのにアプリではORA-06576になります

接続ユーザー、カレントスキーマ、シノニム、権限、JDBCの呼び出し構文が違う可能性があります。アプリと同じユーザーで再現確認します。

パッケージ内の関数を単体名で呼べますか?

通常は呼べません。package_name.function_name の形で呼びます。また、パッケージ仕様に公開されている必要があります。

ORA-06575との違いは何ですか?

ORA-06576は有効な関数/プロシージャ名として呼べない問題です。ORA-06575は対象が見つかっているもののINVALID状態で実行できない問題です。

まとめ

ORA-06576は、関数やプロシージャの名前、種類、呼び出し構文が合っていない時に発生します。関数は戻り値を受ける、プロシージャは戻り値なしで呼ぶ、パッケージ内ならパッケージ名を付ける、別スキーマならスキーマ名やシノニムを確認する、という順で切り分けます。

対象が存在するのに解決できない場合は、ALL_OBJECTSALL_PROCEDURESALL_ARGUMENTSALL_SYNONYMS、権限、INVALID状態を確認します。DBMS_SCHEDULERやJDBCから呼ぶ場合は、ジョブタイプやCallableStatementの構文も合わせて確認してください。

参考

ORA-06576 – Oracle Database Error Help

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

ALL_PROCEDURES – Oracle Database Reference

ALL_ARGUMENTS – Oracle Database Reference