【Oracle】PLS-00306の原因と解決方法|wrong number or types of arguments in call

【Oracle】PLS-00306の原因と解決方法|wrong number or types of arguments in call Oracle

PLS-00306: wrong number or types of arguments in call to 'xxx' は、PL/SQLでプロシージャ、ファンクション、パッケージ内サブプログラムを呼び出した時に、実際に渡した引数が宣言と一致しない場合に発生するコンパイルエラーです。

原因は、引数の個数違い、型違い、順番違い、OUT / IN OUT にリテラルを渡している、名前付き記法のパラメータ名ミス、デフォルト値の誤解、オーバーロード解決の失敗などです。

先に結論
PLS-00306が出たら、呼び出しているサブプログラム名を確認し、ALL_ARGUMENTS または USER_ARGUMENTS で宣言側の引数を見ます。そのうえで、呼び出し側の引数の数、型、順番、IN/OUT/IN OUT、名前付き記法の名前、デフォルト値の有無を照合します。ORA-06550 と一緒に出る場合も、直すべき中心は後続のPLS-00306です。
スポンサーリンク

PLS-00306とは

Oracle公式の説明では、PLS-00306は、呼び出し先のサブプログラムに対して引数の数または型が合っていない時に発生します。サブプログラム名の綴り、宣言位置、呼び出し方、引数のデータ型が正しいかを確認する必要があります。

PLS-00201が「識別子が見えない」エラーなら、PLS-00306は「呼び出し先は見えているが、渡し方が合っていない」エラーです。識別子解決の問題は PLS-00201の原因と解決方法 も確認してください。

表示例 よくある意味 最初に見る場所
PLS-00306: wrong number or types of arguments in call to 'SYNC_ORDER' 引数の数または型が違う ALL_ARGUMENTS
PLS-00306 + ORA-06550 PL/SQLブロック内の呼び出し失敗 後続のPLS-00306行
パッケージ内プロシージャで発生 仕様部の宣言と呼び出しが不一致 USER_ARGUMENTS / パッケージ仕様部
アプリからだけ発生 バインド型やOUT引数の扱いが違う 実行SQL、ドライバのbind設定

まず確認する順番

PLS-00306では、呼び出し側だけ眺めても原因が見えないことがあります。宣言側と呼び出し側を並べて確認するのが近道です。

順番 確認すること 使うもの
1 呼び出し先の名前 エラー内の call to 'xxx'
2 宣言側の引数一覧 ALL_ARGUMENTS / USER_ARGUMENTS
3 呼び出し側の引数数 位置指定の個数、名前付き記法の数
4 引数の型 DATA_TYPETYPE_NAME%TYPE
5 引数モード IN / OUT / IN/OUT
6 デフォルト値の有無 DEFAULTED
7 オーバーロードの有無 OVERLOAD

ALL_ARGUMENTSで引数定義を確認する

まず、呼び出し先の引数定義を ALL_ARGUMENTS で確認します。POSITIONARGUMENT_NAMEDATA_TYPEIN_OUTDEFAULTED を見ると、呼び出し側との差分が分かります。

all-arguments.sql
SELECT owner,
       package_name,
       object_name,
       overload,
       position,
       argument_name,
       data_type,
       type_owner,
       type_name,
       in_out,
       defaulted
FROM all_arguments
WHERE owner = 'APP_SCHEMA'
  AND object_name = 'SYNC_ORDER'
ORDER BY package_name, object_name, overload, sequence;

ALL_ARGUMENTS は、現在のユーザーが参照できるプロシージャ・ファンクションの引数情報を返します。パッケージ内サブプログラムの場合は PACKAGE_NAME も確認してください。

パッケージ内のプロシージャを探す時の注意
パッケージ内の PKG_ORDER.SYNC_ORDER を調べる場合、OBJECT_NAME はパッケージ名、PACKAGE_NAME はNULLになる環境やバージョン差を想定して、実データを見ながら条件を調整します。検索で出ない時は、まず対象スキーマの ALL_ARGUMENTS を広めに絞り込んで、列の入り方を確認してください。
package-argument-search.sql
SELECT owner,
       package_name,
       object_name,
       argument_name,
       position,
       sequence,
       data_type,
       in_out
FROM all_arguments
WHERE owner = 'APP_SCHEMA'
  AND (package_name = 'PKG_ORDER' OR object_name = 'PKG_ORDER')
ORDER BY package_name, object_name, overload, sequence;

関数の場合、戻り値が POSITION = 0 として表示されることがあります。引数の1つとして数えないようにし、POSITIONARGUMENT_NAME を見ながら実引数だけを照合します。

引数の数が違うケース

最も単純なのは、宣言より多い、または少ない引数を渡しているケースです。位置指定で呼び出している場合は、引数を1つ増減しただけで以降の意味もずれます。

wrong-number.sql
CREATE OR REPLACE PROCEDURE p_sync_order(
  p_order_id IN NUMBER,
  p_status   IN VARCHAR2
) AS
BEGIN
  NULL;
END;
/

-- NG: 第2引数が足りない
BEGIN
  p_sync_order(1001);
END;
/
-- PLS-00306

-- OK
BEGIN
  p_sync_order(1001, 'DONE');
END;
/

引数の型が違うケース

引数の数が合っていても、型が合わなければPLS-00306になります。暗黙変換で通ることもありますが、DATE、BOOLEAN、レコード型、コレクション型では意図通りに解決されないことがあります。

wrong-type.sql
CREATE OR REPLACE PROCEDURE p_set_due_date(
  p_due_date IN DATE
) AS
BEGIN
  NULL;
END;
/

-- NGになりやすい: 文字列を日付として渡している
BEGIN
  p_set_due_date('2026-05-14');
END;
/

-- OK: DATEリテラルまたは明示変換
BEGIN
  p_set_due_date(DATE '2026-05-14');
END;
/

日付文字列の扱いで別エラーになる場合は、日付変換系の記事もあわせて確認します。PLS-00306では、まず呼び出し先の型と実際に渡している値の型を合わせるのが基本です。

OUT / IN OUT引数にリテラルを渡しているケース

OUTIN OUT 引数には、結果を書き戻せる変数が必要です。リテラル、式、関数戻り値を渡すと、引数として適切に扱えずPLS-00306や関連エラーになります。

out-parameter.sql
CREATE OR REPLACE PROCEDURE p_get_status(
  p_order_id IN  NUMBER,
  p_status   OUT VARCHAR2
) AS
BEGIN
  p_status := 'DONE';
END;
/

-- NG: OUT引数に文字列リテラルは渡せない
BEGIN
  p_get_status(1001, '');
END;
/

-- OK: 変数を渡す
DECLARE
  v_status VARCHAR2(20);
BEGIN
  p_get_status(1001, v_status);
  DBMS_OUTPUT.PUT_LINE(v_status);
END;
/

IN、OUT、IN OUTの違いは PL/SQLのIN・OUT・IN OUTパラメータ でも詳しく整理しています。

位置指定と名前付き記法を間違えているケース

PL/SQLでは、位置指定、名前付き記法、混合記法で引数を渡せます。名前付き記法は順番ミスを減らせますが、パラメータ名を間違えるとPLS-00306につながります。

named-notation.sql
CREATE OR REPLACE PROCEDURE p_create_user(
  p_user_id IN NUMBER,
  p_email   IN VARCHAR2,
  p_status  IN VARCHAR2 DEFAULT 'ACTIVE'
) AS
BEGIN
  NULL;
END;
/

-- OK: 名前付き記法
BEGIN
  p_create_user(
    p_user_id => 10,
    p_email   => 'a@example.com'
  );
END;
/

-- NG: パラメータ名が違う
BEGIN
  p_create_user(
    user_id => 10,
    email   => 'a@example.com'
  );
END;
/

デフォルト値を誤解しているケース

DEFAULT がある引数は省略できますが、すべての引数を自由に省略できるわけではありません。位置指定で途中の引数を飛ばしたい場合は、名前付き記法を使うのが安全です。

default-arguments.sql
CREATE OR REPLACE PROCEDURE p_search_order(
  p_customer_id IN NUMBER,
  p_status      IN VARCHAR2 DEFAULT 'ACTIVE',
  p_limit       IN NUMBER   DEFAULT 100
) AS
BEGIN
  NULL;
END;
/

-- OK: 末尾側のデフォルト引数を省略
BEGIN
  p_search_order(10);
END;
/

-- OK: 途中を飛ばすなら名前付き記法
BEGIN
  p_search_order(
    p_customer_id => 10,
    p_limit       => 50
  );
END;
/

オーバーロードで解決できないケース

同じ名前で引数違いのプロシージャやファンクションを複数定義している場合、Oracleは引数からどの定義を使うか解決します。型が曖昧だったり、どの定義にも一致しない場合にPLS-00306になります。

overload-check.sql
SELECT package_name,
       object_name,
       overload,
       position,
       argument_name,
       data_type,
       in_out
FROM all_arguments
WHERE owner = 'APP_SCHEMA'
  AND package_name = 'PKG_ORDER'
  AND object_name = 'SYNC_ORDER'
ORDER BY overload, sequence;

OVERLOAD が複数ある場合は、呼び出し側の引数がどの定義に一致するかを1つずつ照合します。文字列リテラルやNULLは型が曖昧になりやすいため、明示的に CAST する方法もあります。

overload-null-cast.sql
CREATE OR REPLACE PACKAGE pkg_notify AS
  PROCEDURE send(p_user_id IN NUMBER);
  PROCEDURE send(p_email   IN VARCHAR2);
END pkg_notify;
/

-- NGになりやすい: NULLだけではどちらのsendか決められない
BEGIN
  pkg_notify.send(NULL);
END;
/

-- OK: 呼びたい定義の型を明示する
BEGIN
  pkg_notify.send(CAST(NULL AS VARCHAR2));
END;
/

レコード型・コレクション型の引数で発生するケース

レコード型やコレクション型は、見た目の構造が同じでも、別の型として定義されていれば互換とは限りません。パッケージ内で定義した型、SQLオブジェクト型、ローカル型を混同するとPLS-00306になります。

composite-type.sql
CREATE OR REPLACE PACKAGE pkg_order AS
  TYPE t_order_ids IS TABLE OF NUMBER;
  PROCEDURE close_orders(p_ids IN t_order_ids);
END pkg_order;
/

-- OK: パッケージで定義された型を使う
DECLARE
  v_ids pkg_order.t_order_ids := pkg_order.t_order_ids(1, 2, 3);
BEGIN
  pkg_order.close_orders(v_ids);
END;
/

Oracle公式の ALL_ARGUMENTS 説明では、複合型引数の詳細確認には TYPE_NAME からPL/SQL型関連ビューを確認する流れも示されています。型名が一致しているか、パッケージ名まで含めて確認してください。

呼び出し先のパッケージやプロシージャを変更した直後に発生する場合は、依存オブジェクトの再コンパイル状況も確認します。無効オブジェクトの調査は ORA-04063の原因と解決方法、実行時に呼び出し先を見失う場合は ORA-06508の原因と解決方法 が近い確認先です。

アプリケーションから呼び出す時の注意

Java、C#、PHP、Pythonなどのアプリケーションからストアドプロシージャを呼ぶ場合も、バインド変数の数、型、方向が合っていないとPLS-00306になります。特に OUT 引数の登録漏れ、NUMBERとVARCHAR2の取り違え、DATE/TIMESTAMPの渡し方に注意します。

ストアドプロシージャとファンクションの使い分け自体を整理したい場合は、Oracleのストアドプロシージャとファンクションの違い も参考になります。PL/SQLの基本構文から確認したい場合は PL/SQLの基本 もあわせて確認してください。

確認項目 よくあるミス 対処
バインド数 プロシージャ引数より少ない/多い 宣言と同じ数にする
バインド型 NUMBERに文字列、DATEに文字列 ドライバ側の型指定を合わせる
OUT引数 OUTパラメータを登録していない 出力パラメータとして登録する
名前付き呼び出し パラメータ名がDB側と違う ALL_ARGUMENTS.ARGUMENT_NAME を確認
パッケージ名 スキーマやパッケージ修飾漏れ 完全修飾名で呼ぶ

ORA-06550と一緒に出る場合

PLS-00306は、匿名ブロックやアプリケーション経由の呼び出しで ORA-06550 と一緒に出ることが多いです。この場合、ORA-06550はPL/SQLブロック全体の失敗を示す入口で、後続のPLS-00306を直します。

ora-06550-pls00306.sql
BEGIN
  p_sync_order(1001);
END;
/

-- ORA-06550: line 2, column 3:
-- PLS-00306: wrong number or types of arguments in call to 'P_SYNC_ORDER'
-- ORA-06550: line 2, column 3:
-- PL/SQL: Statement ignored

本番障害時の調査SQLセット

本番でPLS-00306が出た場合は、呼び出し先の引数定義をすぐ確認できるSQLを用意しておくと早いです。

pls-00306-investigation.sql
DEFINE owner_name = 'APP_SCHEMA'
DEFINE proc_name  = 'SYNC_ORDER'

SELECT owner,
       package_name,
       object_name,
       overload,
       position,
       argument_name,
       data_type,
       type_owner,
       type_name,
       in_out,
       defaulted
FROM all_arguments
WHERE owner = UPPER('&owner_name')
  AND object_name = UPPER('&proc_name')
ORDER BY package_name, object_name, overload, sequence;

よくある原因と対処一覧

原因 確認すること 対処
引数の数が違う POSITION と呼び出し引数数 不足/過剰な引数を直す
型が違う DATA_TYPE / TYPE_NAME 型を合わせる、明示変換する
OUT/IN OUTにリテラルを渡した IN_OUT 変数を渡す
名前付き記法の名前ミス ARGUMENT_NAME 正式な引数名を使う
デフォルト値の誤解 DEFAULTED 名前付き記法で省略する
オーバーロード不一致 OVERLOAD 一致する定義に合わせる
NULLで型が曖昧 複数の候補に一致するか CAST(NULL AS ...) で型を明示する
関数戻り値を引数に数えた POSITION = 0 戻り値と実引数を分けて見る
複合型が違う TYPE_OWNER / TYPE_NAME 同じ型定義を使う

PLS-00306と関連エラーの違い

エラー 意味 見るべき場所
PLS-00306 引数の数または型が合わない ALL_ARGUMENTS と呼び出し側
ORA-06550 PL/SQLブロック全体の失敗を示す入口 後続の PLS- エラー
PLS-00201 識別子が宣言されていない、または見えない 名前、権限、スコープ
PLS-00905 参照しているオブジェクトが無効 USER_ERRORS
PLS-00323 仕様部で宣言したサブプログラムの本体がない PACKAGE仕様部と本体

オブジェクトが無効な場合は PLS-00905の原因と解決方法、呼び出し先が見えない場合は PLS-00201の原因と解決方法 も確認してください。

修正チェックリスト

項目 確認内容 OKの状態
呼び出し先 プロシージャ/関数名が正しいか 対象が特定できている
引数定義 ALL_ARGUMENTS を確認したか 宣言側を把握済み
引数数が一致しているか 不足/過剰なし
データ型・TYPE_NAMEが一致しているか 明示変換または同型
方向 OUT/IN OUTに変数を渡しているか 書き戻し可能な変数
名前付き記法 引数名が正しいか ARGUMENT_NAMEと一致
デフォルト 省略可能な引数か DEFAULTEDを確認済み

よくある質問

引数の数は合っているのにPLS-00306になります

型、OUT/IN OUT、オーバーロード、レコード型やコレクション型の違いを確認してください。見た目が同じでも別の型なら一致しないことがあります。

名前付き記法なら順番は関係ありませんか?

順番の影響は減りますが、引数名が宣言と一致している必要があります。ALL_ARGUMENTS.ARGUMENT_NAME を確認してください。

OUT引数にNULLを渡してもよいですか?

OUT引数には値を書き戻せる変数を渡します。NULL や文字列リテラルではなく、変数を宣言して渡してください。

アプリから呼ぶ時だけPLS-00306になります

ドライバ側のバインド数、型、OUTパラメータ登録、パッケージ名・スキーマ名を確認してください。DB側の宣言は ALL_ARGUMENTS で確認します。

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

ORA-06550はPL/SQLブロック全体の失敗を示す入口です。後続のPLS-00306に出ている呼び出し先と引数を直してください。

まとめ

PLS-00306は、PL/SQLのサブプログラム呼び出しで、引数の数または型が宣言と一致しない時に発生します。引数の個数だけでなく、型、順番、OUT/IN OUT、名前付き記法、デフォルト値、オーバーロード、複合型まで確認します。

対応の基本は、ALL_ARGUMENTS で宣言側を確認し、呼び出し側の実引数と1つずつ照合することです。アプリケーション経由で発生する場合は、DB側の宣言だけでなく、ドライバ側のバインド型やOUTパラメータ登録も確認してください。

参考

PLS-00306 – Oracle Database Error Help

ALL_ARGUMENTS – Oracle Database Reference

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