Oracle PL/SQLで SELECT INTO を実行した際に、想定より多くの行が返ってしまうと発生するエラーが ORA-01422 です。
特に「必ず1件しか返らないはず」というロジック前提で処理を書いた場合に多く発生します。
この記事では、ORA-01422の意味、原因、発生しやすいケース、そして実務で使える解決方法を例付きで解説します。

▼エラーメッセージ例
英語環境
|
1 2 |
ORA-01422: exact fetch returns more than requested number of rows Expected single row |
日本語環境
|
1 2 |
ORA-01422: 完全フェッチがリクエストより多くの行を戻しました<code class="whitespace-pre!"> |
ORA-01422 の意味
このエラーは簡単に言うと、
「1行だけ返るはずのクエリなのに、複数行返ってきた」
ときに発生します。
Oracleの SELECT INTO 文は、戻り値が「必ず1件」であることが前提です。
つまり複数行返った場合、自動的に例外がスローされます。
発生原因と典型パターン
❌ エラーになる例
|
1 2 3 4 5 6 7 8 |
DECLARE v_name VARCHAR2(100); BEGIN SELECT name INTO v_name FROM employee WHERE department_id = 10; END; / |
department_id = 10 の従業員が複数存在すると、複数行が返りORA-01422 になります。
解決方法
状況に応じて複数の修正方法があります。
代表的な対策パターンを紹介します。
① データが本来1件であるべきなら WHERE条件の見直し
ロジック誤りが原因の場合は、SQLを修正すべきケースです。
キー項目(PKやUniqueキー)で絞ることで、意図通り1件にできます。
② 1件だけ取れれば良いなら ROWNUM 1
※順序に意味がある場合は ORDER BY と組み合わせます。
③ 複数件を想定するなら SELECT INTO をやめてカーソルに変更
|
1 2 3 4 5 6 7 8 9 10 11 |
DECLARE CURSOR c_emp IS SELECT name FROM employee WHERE department_id = 10; v_name employee.name%TYPE; BEGIN FOR rec IN c_emp LOOP v_name := rec.name; DBMS_OUTPUT.PUT_LINE(v_name); END LOOP; END; / |
④ 例外処理 TOO_MANY_ROWS を活用する
ORA-01422 は TOO_MANY_ROWS 例外として扱えます。
|
1 2 3 4 5 6 7 8 9 |
BEGIN SELECT name INTO v_name FROM employee WHERE department_id = 10; EXCEPTION WHEN TOO_MANY_ROWS THEN DBMS_OUTPUT.PUT_LINE('複数件ヒットしました。条件を確認してください。'); END; / |
他の類似エラーとの違い
| エラーコード | 発生条件 | 原因 |
|---|---|---|
| ORA-01422 | 戻り値が複数行 | SELECT INTO で1件に絞れない |
| ORA-01403 | 戻り値が0件(空) | データが存在しない |
| ORA-00942 等 | SQL自体の構文/テーブル問題 | テーブル・ビューが存在しない |
まとめ
-
ORA-01422 は SELECT INTO で複数行返ってしまった時のエラー
-
英語メッセージは Expected single row
-
日本語メッセージは 完全フェッチがリクエストより多くの行を戻しました
-
対処方法は目的に応じて次のいずれか
✔ WHERE句の見直し
✔ ROWNUMで1行化
✔ カーソル使用
✔ 例外処理 TOO_MANY_ROWS の補足
