PL/SQL で SELECT INTO を行なう
テーブル定義
テーブルは PLSQL による INSERT のテーブル定義をデータ使用
PL/SQL で SELECT を実行する
PL/SQL で SELECT を行なうには SELECT 〜 INTO を使用して SELECT の結果を変数に代入しなければならない。
SELECT だけを単独で記述すると以下のコンパイルエラーが出力される。
PLS-00428: INTO 句はこの SELECT 文に*入ります*。
(これは「要ります」の誤りと思われる)
PLS-00428: an INTO clause is expected in this SELECT statement (英文)
SELECT INTO を使用した単一行の取得
-- 実行してみる。
SQL> SET SERVEROUTPUT ON
SQL> CALL STEP01_SELECT();
利用者IDは0020です。
利用者名は小泉 純一さんです。
コールが完了しました。
しかし、このプログラムは抽出対象レコードが単一の場合しか使用できない。複数件になると以下のエラーが出力される。
SQL> INSERT INTO USER_MASTER ( USER_ID, USER_NAME) VALUES ('1000', 'おじゃまデータ');
1行が作成されました。
SQL> CALL STEP01_SELECT();
*
行1でエラーが発生しました。:
ORA-01422: 完全フェッチがリクエストよりも多くの行を戻しました
ORA-06512: "RIVUS.STEP01_SELECT", 行6
SQL> ROLLBACK;
ロールバックが完了しました。
(補足)データが 0 件、または、複数件のときの例外処理を作成することで処理を継続させることができる。
CREATE OR REPLACE PROCEDURE RIVUS.STEP01_SELECT
IS
vUserID USER_MASTER.USER_ID%TYPE;
vUserName USER_MASTER.USER_NAME%TYPE;
BEGIN
SELECT USER_ID, USER_NAME INTO vUserID, vUserName FROM USER_MASTER;
DBMS_OUTPUT.PUT_LINE('利用者IDは' || vUserID || 'です。');
DBMS_OUTPUT.PUT_LINE('利用者名は' || vUserName || 'さんです。');
/***** ここから例外処理 *****/
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('データが見つかりませんでした。');
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('データが複数見つかりました。');
/***** ここまで例外処理 *****/
END;
/
詳細は PLSQL の例外処理 へ
複数のレコードを取り扱う
複数のレコードを取り扱うには カーソル・ループ を使う方法と
コレクションを使用した バルク処理(バルクフェッチ) による方法がある。
複数のデータを一度に処理するケースではバルク処理の方が IO 回数が少ないために高速に処理を行うことができる。
SELECT BULK COLLECT INTO によるバルク処理
複数レコードを一括で取り扱うには SELECT BULK COLLECT INTO を使用する。この構文は比較的小さな結果セットを取り扱う場合に有用である。結果セットが一度にメモリ中で取り扱うには大きすぎる場合には、より多くの組み込みが必要ではあるが バルクフェッチ を使用したほうが良い。
CREATE OR REPLACE PROCEDURE RIVUS.STEP01_SELECT_ALL
IS
TYPE tUserList IS TABLE OF USER_MASTER%ROWTYPE;
vUsers tUserList;
BEGIN
SELECT * BULK COLLECT INTO vUsers FROM USER_MASTER;
-- ↑ コレクション(ネストした表) vUsers にすべての結果が一度に設定される。
DBMS_OUTPUT.PUT_LINE('レコード数は' || vUsers.COUNT || '件です。');
DBMS_OUTPUT.PUT_LINE('利用者IDは' || vUsers(1).USER_ID || 'です。');
DBMS_OUTPUT.PUT_LINE('利用者名は' || vUsers(1).USER_NAME || 'さんです。');
vUsers.DELETE; -- 要らなくなったから解放
DBMS_OUTPUT.PUT_LINE('配列の大きさは' || vUsers.COUNT || 'です。');
END;
/
関連事項