質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Oracle Database 11g

Oracle DatabaseはRDBMSの商品です。具体的な発売商品として知られているのが、 Oracle9i、Oracle10g、Oracle 11gとOracle 12cです。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

2回答

12186閲覧

Oracleの「BULK COLLECT INTO」構文について

kurori

総合スコア111

Oracle Database 11g

Oracle DatabaseはRDBMSの商品です。具体的な発売商品として知られているのが、 Oracle9i、Oracle10g、Oracle 11gとOracle 12cです。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

0クリップ

投稿2016/11/02 09:15

###前提・実現したいこと
環境:Oracle11g

SQLの勉強中です。

プロシージャの中で
SELECT INTO ~ で複数行を取得する処理を行いたいのですが、
INTOではクエリの結果が1行でなければエラーになる為、
BULK COLLECT INTO を使用してみたいのですが、今一つ使い方がわかりません。

###質問
1.BULK COLLECT INTO で格納するレコード型配列について。
どのサイトを見ても既にあるテーブルのROWTYPEから定義を作っているようですが、
レコード型配列の型宣言時に独自に型定義する方法は有りますでしょうか。
DUALテーブルの様に実体無しで宣言する方法を探しています。

2.BULK COLLECT INTOで格納されたレコードについて
格納したオブジェクトを取り出す際に、格納時に指定したソートキーの順番で取り出せると考えてよいでしょうか?
(配列なので問題ないと思いますが...)

SELECT結果をカーソルで扱えばいいじゃない、と言われそうではありますが、
ご存知の方は情報提供をお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

ご質問1について

どのサイトを見ても既にあるテーブルのROWTYPEから定義を作っているようです

例えば こちら の解説ページはいかがでしょうか。RECORD型のTABLE型を宣言するやり方が記載されています。記事中の「コード・リスト5」がそうです。
上記記事のコードとは異なりますが、以下のような感じです。(emp表が必要です。)

sql

1DECLARE 2 TYPE emp_row_t IS RECORD( 3 empno emp.empno%TYPE, 4 ename emp.ename%TYPE, 5 deptno emp.deptno%TYPE 6 ); 7 TYPE emp_list_t IS TABLE OF emp_row_t; 8 emp_list emp_list_t := emp_list_t(); 9BEGIN 10 SELECT e.empno, 11 e.ename, 12 e.deptno 13 BULK COLLECT INTO emp_list 14 FROM emp e 15 ORDER BY e.empno; 16 FOR i IN 1..emp_list.COUNT LOOP 17 DBMS_OUTPUT.PUT_LINE( 18 UTL_LMS.FORMAT_MESSAGE( 19 '(i = %d) empno = %s, ename = %s, deptno = %s', 20 i, TO_CHAR(emp_list(i).empno), emp_list(i).ename, TO_CHAR(emp_list(i).deptno))); 21 END LOOP; 22END;
(i = 1) empno = 7369, ename = SMITH, deptno = 20 (i = 2) empno = 7499, ename = ALLEN, deptno = 30 (i = 3) empno = 7521, ename = WARD, deptno = 30 (i = 4) empno = 7566, ename = JONES, deptno = 20 (i = 5) empno = 7654, ename = MARTIN, deptno = 30 (i = 6) empno = 7698, ename = BLAKE, deptno = 30 (i = 7) empno = 7782, ename = CLARK, deptno = 10 (i = 8) empno = 7839, ename = KING, deptno = 10 (i = 9) empno = 7844, ename = TURNER, deptno = 30 (i = 10) empno = 7900, ename = JAMES, deptno = 30 (i = 11) empno = 7902, ename = FORD, deptno = 20 (i = 12) empno = 7934, ename = MILLER, deptno = 10

BULK COLLECT自体は、カーソルの代わりに使うものではありません。組み合わせて使うことも可能です。
5行ずつフェッチする例です。

sql

1DECLARE 2 CURSOR cur_emp IS 3 SELECT e.empno, 4 e.ename, 5 e.deptno 6 FROM emp e 7 ORDER BY e.empno; 8 TYPE emp_list_t IS TABLE OF cur_emp%ROWTYPE; 9 emp_list emp_list_t := emp_list_t(); 10 i PLS_INTEGER := 1; 11BEGIN 12 OPEN cur_emp; 13 LOOP 14 FETCH cur_emp BULK COLLECT INTO emp_list LIMIT 5; 15 EXIT WHEN emp_list.COUNT = 0; 16 FOR j IN 1..emp_list.COUNT LOOP 17 DBMS_OUTPUT.PUT_LINE( 18 UTL_LMS.FORMAT_MESSAGE( 19 '(i = %d, j = %d) empno = %s, ename = %s, deptno = %s', 20 i, j, TO_CHAR(emp_list(j).empno), emp_list(j).ename, TO_CHAR(emp_list(j).deptno))); 21 END LOOP; 22 i := i + 1; 23 END LOOP; 24END;
(i = 1, j = 1) empno = 7369, ename = SMITH, deptno = 20 (i = 1, j = 2) empno = 7499, ename = ALLEN, deptno = 30 (i = 1, j = 3) empno = 7521, ename = WARD, deptno = 30 (i = 1, j = 4) empno = 7566, ename = JONES, deptno = 20 (i = 1, j = 5) empno = 7654, ename = MARTIN, deptno = 30 (i = 2, j = 1) empno = 7698, ename = BLAKE, deptno = 30 (i = 2, j = 2) empno = 7782, ename = CLARK, deptno = 10 (i = 2, j = 3) empno = 7839, ename = KING, deptno = 10 (i = 2, j = 4) empno = 7844, ename = TURNER, deptno = 30 (i = 2, j = 5) empno = 7900, ename = JAMES, deptno = 30 (i = 3, j = 1) empno = 7902, ename = FORD, deptno = 20 (i = 3, j = 2) empno = 7934, ename = MILLER, deptno = 10

ご質問2について

格納したオブジェクトを取り出す際に、格納時に指定したソートキーの順番で取り出せると考えてよいでしょうか?

Oracleのマニュアルにはっきりとした記載を見つけられませんでしたが、BULK COLLECTした結果の添字が1からCOUNTまでと言った記載が随所にあるのと、サンプルコードのいくつかを見る限り、問題ないでしょう。(そうでないと、使い物になりませんので・・・。)

投稿2016/11/03 13:20

q1701

総合スコア274

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kurori

2016/11/04 00:41

サンプルのご提示も含め、ご丁寧な説明、ありがとうございます。 ご提示いただいたサイトの「コード・リスト4:increase_salaryプロシージャのバルク処理 」は まさに探していた情報です。 特に質問1に関しての明確な回答を頂けたという事で、ベストアンサーとさせて頂きます。
guest

0

実際に使えるサンプルコードをググると解りますが、
PL/SQLによるバルクフェッチ処理

PL/SQL の カーソル処理 には 1レコード単位にレコードを取り出す方式 だけではなく 複数のレコードを1回の処理で行うバルク処理がある。

複数のレコードを1回の処理することで処理時間を短縮する方法です。

投稿2016/11/03 03:14

Orlofsky

総合スコア16415

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問