Hatena::ブログ(Diary)

ねら〜ITエンジニア雑記

2017-09-03

単純なINSERT文でもバインド変数のサイズの違いで複数の子カーソルが生成される(Oracle Database)


表題の通り、やってみるやで彡(゚)(゚)

INSERTするバインド変数の大きさの順番/組み合わせで挙動が変わるので、
まずはバイト数が小さい順にINSERTしてみるやで。

バイト数の小さい順にINSERT

実行するSQLは下記

-- 共有プールをFLUSH
ALTER SYSTEM FLUSH SHARED_POOL;

-- テーブル作成
DROP TABLE TBL_A PURGE;
CREATE TABLE TBL_A(C1 VARCHAR2(4000));

-- 1バイトのバインド変数でINSERT
VAR B1 VARCHAR2(1);
EXEC :B1 := 'A';
-- sql_id = 'g47kmy54uf3nm'
INSERT INTO TBL_A VALUES(:B1);
COMMIT;

-- 40バイトのバインド変数でINSERT
VAR B1 VARCHAR2(40);
EXEC :B1 := 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
-- sql_id = 'g47kmy54uf3nm'
INSERT INTO TBL_A VALUES(:B1);
COMMIT;

-- 200バイトのバインド変数でINSERT
VAR B1 VARCHAR2(200);
EXEC :B1 := 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
-- sql_id = 'g47kmy54uf3nm'
INSERT INTO TBL_A VALUES(:B1);
COMMIT;

-- V$SQLで子カーソルを確認
SET LINESIZE 300;
SET PAGESIZE 100;
COLUMN SQL_TEXT FORMAT A60;
SELECT SQL_ID, CHILD_NUMBER, PLAN_HASH_VALUE, CHILD_ADDRESS, SQL_TEXT FROM V$SQL
WHERE SQL_ID = 'g47kmy54uf3nm';

-- V$SQL_BIND_METADATAで子カーソルのバインド変数を確認
COLUMN BIND_NAME FORMAT A30;
SELECT ADDRESS, POSITION, DATATYPE, MAX_LENGTH, BIND_NAME FROM V$SQL_BIND_METADATA
WHERE ADDRESS IN (SELECT CHILD_ADDRESS FROM V$SQL WHERE SQL_ID = 'g47kmy54uf3nm');

-- V$SQL_SHARED_CURSORで子カーソルの生成理由を確認
SELECT SQL_ID, CHILD_ADDRESS, CHILD_NUMBER, HASH_MATCH_FAILED, BIND_LENGTH_UPGRADEABLE
FROM V$SQL_SHARED_CURSOR WHERE SQL_ID = 'g47kmy54uf3nm';

結果は以下の通り

:
SQL> -- V$SQLで子カーソルを確認
SQL> SET LINESIZE 300;
SQL> SET PAGESIZE 100;
SQL> COLUMN SQL_TEXT FORMAT A60;
SQL> SELECT SQL_ID, CHILD_NUMBER, PLAN_HASH_VALUE, CHILD_ADDRESS, SQL_TEXT FROM V$SQL
  2  WHERE SQL_ID = 'g47kmy54uf3nm';

SQL_ID        CHILD_NUMBER PLAN_HASH_VALUE CHILD_ADDRESS    SQL_TEXT
------------- ------------ --------------- ---------------- -----------------------------
g47kmy54uf3nm            0               0 000000006C45E450 INSERT INTO TBL_A VALUES(:B1) ★1つ目の子カーソル
g47kmy54uf3nm            1               0 000000006CD519E0 INSERT INTO TBL_A VALUES(:B1) ★2つ目の子カーソル
g47kmy54uf3nm            2               0 000000006ECC0660 INSERT INTO TBL_A VALUES(:B1) ★3つ目の子カーソル

SQL> -- V$SQL_BIND_METADATAで子カーソルのバインド変数を確認
SQL> COLUMN BIND_NAME FORMAT A30;
SQL> SELECT ADDRESS, POSITION, DATATYPE, MAX_LENGTH, BIND_NAME FROM V$SQL_BIND_METADATA
  2  WHERE ADDRESS IN (SELECT CHILD_ADDRESS FROM V$SQL WHERE SQL_ID = 'g47kmy54uf3nm');

ADDRESS            POSITION   DATATYPE MAX_LENGTH BIND_NAME
---------------- ---------- ---------- ---------- ---------
000000006C45E450          1          1         32 B1        ★バインド変数のMAX_LENGTH値が  32バイト
000000006CD519E0          1          1        128 B1        ★バインド変数のMAX_LENGTH値が 128バイト
000000006ECC0660          1          1       2000 B1        ★バインド変数のMAX_LENGTH値が2000バイト

SQL> -- V$SQL_SHARED_CURSORで子カーソルの生成理由を確認
SQL> SELECT SQL_ID, CHILD_ADDRESS, CHILD_NUMBER, HASH_MATCH_FAILED, BIND_LENGTH_UPGRADEABLE
  2  FROM V$SQL_SHARED_CURSOR WHERE SQL_ID = 'g47kmy54uf3nm';

SQL_ID        CHILD_ADDRESS    CHILD_NUMBER H B
------------- ---------------- ------------ - -
g47kmy54uf3nm 000000006C45E450            0 N N
g47kmy54uf3nm 000000006CD519E0            1 Y Y ★HASH_MATCH_FAILED列 と BIND_LENGTH_UPGRADEABLE列が N
g47kmy54uf3nm 000000006ECC0660            2 Y Y ★HASH_MATCH_FAILED列 と BIND_LENGTH_UPGRADEABLE列が N

バイト数の大きい順にINSERT

実行するSQLは下記

-- 共有プールをFLUSH
ALTER SYSTEM FLUSH SHARED_POOL;

-- テーブル作成
DROP TABLE TBL_A PURGE;
CREATE TABLE TBL_A(C1 VARCHAR2(4000));

-- 200バイトのバインド変数でINSERT
VAR B1 VARCHAR2(200);
EXEC :B1 := 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
-- sql_id = 'g47kmy54uf3nm'
INSERT INTO TBL_A VALUES(:B1);
COMMIT;

-- 40バイトのバインド変数でINSERT
VAR B1 VARCHAR2(40);
EXEC :B1 := 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
-- sql_id = 'g47kmy54uf3nm'
INSERT INTO TBL_A VALUES(:B1);
COMMIT;

-- 1バイトのバインド変数でINSERT
VAR B1 VARCHAR2(1);
EXEC :B1 := 'A';
-- sql_id = 'g47kmy54uf3nm'
INSERT INTO TBL_A VALUES(:B1);
COMMIT;

-- V$SQLで子カーソルを確認
SET LINESIZE 300;
SET PAGESIZE 100;
COLUMN SQL_TEXT FORMAT A60;
SELECT SQL_ID, CHILD_NUMBER, PLAN_HASH_VALUE, CHILD_ADDRESS, SQL_TEXT FROM V$SQL
WHERE SQL_ID = 'g47kmy54uf3nm';

-- V$SQL_BIND_METADATAで子カーソルのバインド変数を確認
COLUMN BIND_NAME FORMAT A30;
SELECT ADDRESS, POSITION, DATATYPE, MAX_LENGTH, BIND_NAME FROM V$SQL_BIND_METADATA
WHERE ADDRESS IN (SELECT CHILD_ADDRESS FROM V$SQL WHERE SQL_ID = 'g47kmy54uf3nm');

-- V$SQL_SHARED_CURSORで子カーソルの生成理由を確認
SELECT SQL_ID, CHILD_ADDRESS, CHILD_NUMBER, HASH_MATCH_FAILED, BIND_LENGTH_UPGRADEABLE
FROM V$SQL_SHARED_CURSOR WHERE SQL_ID = 'g47kmy54uf3nm';

結果は以下の通りで、子カーソルは1つだけなんですやね彡(゚)(゚)

SQL> -- V$SQLで子カーソルを確認
SQL> SET LINESIZE 300;
SQL> SET PAGESIZE 100;
SQL> COLUMN SQL_TEXT FORMAT A60;
SQL> SELECT SQL_ID, CHILD_NUMBER, PLAN_HASH_VALUE, CHILD_ADDRESS, SQL_TEXT FROM V$SQL
  2  WHERE SQL_ID = 'g47kmy54uf3nm';

SQL_ID        CHILD_NUMBER PLAN_HASH_VALUE CHILD_ADDRESS    SQL_TEXT
------------- ------------ --------------- ---------------- -----------------------------
g47kmy54uf3nm            0               0 000000006EE9F7B8 INSERT INTO TBL_A VALUES(:B1) ★子カーソルは1つだけ

SQL>
SQL> -- V$SQL_BIND_METADATAで子カーソルのバインド変数を確認
SQL> COLUMN BIND_NAME FORMAT A30;
SQL> SELECT ADDRESS, POSITION, DATATYPE, MAX_LENGTH, BIND_NAME FROM V$SQL_BIND_METADATA
  2  WHERE ADDRESS IN (SELECT CHILD_ADDRESS FROM V$SQL WHERE SQL_ID = 'g47kmy54uf3nm');

ADDRESS            POSITION   DATATYPE MAX_LENGTH BIND_NAME
---------------- ---------- ---------- ---------- ---------
000000006EE9F7B8          1          1       2000 B1       ★バインド変数のMAX_LENGTH値が2000バイト

SQL>
SQL> -- V$SQL_SHARED_CURSORで子カーソルの生成理由を確認
SQL> SELECT * FROM V$SQL_SHARED_CURSOR WHERE SQL_ID = 'g47kmy54uf3nm';

SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER U S O O S L F E B P I S T A B D L T B I I R L I O E M U T N F A P T D L D B P C S C P T M B M R O P M F L P L A F L R L H P B U REASON                                                                             CON_ID
------------- ---------------- ---------------- ------------ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------------------------------------------------------------------------- ----------
g47kmy54uf3nm 0000000070E32AF8 000000006EE9F7B8            0 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N                                                                                         0

SQL> SELECT SQL_ID, CHILD_ADDRESS, CHILD_NUMBER, HASH_MATCH_FAILED, BIND_LENGTH_UPGRADEABLE
  2  FROM V$SQL_SHARED_CURSOR WHERE SQL_ID = 'g47kmy54uf3nm';

SQL_ID        CHILD_ADDRESS    CHILD_NUMBER H B
------------- ---------------- ------------ - -
g47kmy54uf3nm 000000006EE9F7B8            0 N N

複数バインド変数の組み合わせで小さい順にINSERT

複数バインド変数の場合は、それぞれのバインド変数の組み合わせでも
子カーソルが生成されます。以下のSQLを実行してみます。

-- 共有プールをFLUSH
ALTER SYSTEM FLUSH SHARED_POOL;

-- テーブル作成
DROP TABLE TBL_B PURGE;
CREATE TABLE TBL_B(
    C1 VARCHAR2(4000)
  , C2 VARCHAR2(4000)
);

-- 1バイトのバインド変数*2でINSERT
VAR B1 VARCHAR2(1);
VAR B2 VARCHAR2(1);
EXEC :B1 := 'A';
EXEC :B2 := 'B';
-- sql_id = '5f5u0gky3kjpc'
INSERT INTO TBL_B VALUES(:B1, :B2);
COMMIT;

-- 1バイト&40バイトのバインド変数でINSERT
VAR B1 VARCHAR2(1);
VAR B2 VARCHAR2(40);
EXEC :B1 := 'A';
EXEC :B2 := 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
-- sql_id = '5f5u0gky3kjpc'
INSERT INTO TBL_B VALUES(:B1, :B2);
COMMIT;

-- 40バイト&1バイトのバインド変数でINSERT
VAR B1 VARCHAR2(40);
VAR B2 VARCHAR2(1);
EXEC :B1 := 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
EXEC :B2 := 'A';
-- sql_id = '5f5u0gky3kjpc'
INSERT INTO TBL_B VALUES(:B1, :B2);
COMMIT;

-- 40バイトのバインド変数*2でINSERT
VAR B1 VARCHAR2(40);
VAR B2 VARCHAR2(40);
EXEC :B1 := 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
EXEC :B2 := 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
-- sql_id = 'g47kmy54uf3nm'
INSERT INTO TBL_B VALUES(:B1, :B2);
COMMIT;

-- V$SQLで子カーソルを確認
SET LINESIZE 300;
SET PAGESIZE 100;
COLUMN SQL_TEXT FORMAT A60;
SELECT SQL_ID, CHILD_NUMBER, PLAN_HASH_VALUE, CHILD_ADDRESS, SQL_TEXT FROM V$SQL
WHERE SQL_ID = '5f5u0gky3kjpc';

-- V$SQL_BIND_METADATAで子カーソルのバインド変数を確認
COLUMN BIND_NAME FORMAT A30;
SELECT ADDRESS, POSITION, DATATYPE, MAX_LENGTH, BIND_NAME FROM V$SQL_BIND_METADATA
WHERE ADDRESS IN (SELECT CHILD_ADDRESS FROM V$SQL WHERE SQL_ID = '5f5u0gky3kjpc')
ORDER BY ADDRESS, POSITION;

-- V$SQL_SHARED_CURSORで子カーソルの生成理由を確認
SELECT SQL_ID, CHILD_ADDRESS, CHILD_NUMBER, HASH_MATCH_FAILED, BIND_LENGTH_UPGRADEABLE
FROM V$SQL_SHARED_CURSOR WHERE SQL_ID = '5f5u0gky3kjpc';

結果は以下の通りで、複数の子カーソルが生成されるんやで彡(゚)(゚)

SQL> -- V$SQLで子カーソルを確認
SQL> SET LINESIZE 300;
SQL> SET PAGESIZE 100;
SQL> COLUMN SQL_TEXT FORMAT A60;
SQL> SELECT SQL_ID, CHILD_NUMBER, PLAN_HASH_VALUE, CHILD_ADDRESS, SQL_TEXT FROM V$SQL
  2  WHERE SQL_ID = '5f5u0gky3kjpc';

SQL_ID        CHILD_NUMBER PLAN_HASH_VALUE CHILD_ADDRESS    SQL_TEXT
------------- ------------ --------------- ---------------- ----------------------------------
5f5u0gky3kjpc            0               0 000000006EB29608 INSERT INTO TBL_B VALUES(:B1, :B2) ★1つ目の子カーソル
5f5u0gky3kjpc            1               0 000000006C94E5C0 INSERT INTO TBL_B VALUES(:B1, :B2) ★2つ目の子カーソル
5f5u0gky3kjpc            2               0 000000006E6F3638 INSERT INTO TBL_B VALUES(:B1, :B2) ★3つ目の子カーソル

SQL>
SQL> -- V$SQL_BIND_METADATAで子カーソルのバインド変数を確認
SQL> COLUMN BIND_NAME FORMAT A30;
SQL> SELECT ADDRESS, POSITION, DATATYPE, MAX_LENGTH, BIND_NAME FROM V$SQL_BIND_METADATA
  2  WHERE ADDRESS IN (SELECT CHILD_ADDRESS FROM V$SQL WHERE SQL_ID = '5f5u0gky3kjpc')
  3  ORDER BY ADDRESS, POSITION;

ADDRESS            POSITION   DATATYPE MAX_LENGTH BIND_NAME
---------------- ---------- ---------- ---------- ---------
000000006C94E5C0          1          1         32 B1 ★2つ目の子カーソルのバインド変数定義
000000006C94E5C0          2          1        128 B2 ★2つ目の子カーソルのバインド変数定義
000000006E6F3638          1          1        128 B1 ★3つ目の子カーソルのバインド変数定義
000000006E6F3638          2          1        128 B2 ★3つ目の子カーソルのバインド変数定義
000000006EB29608          1          1         32 B1 ★1つ目の子カーソルのバインド変数定義
000000006EB29608          2          1         32 B2 ★1つ目の子カーソルのバインド変数定義

6 rows selected.

SQL>
SQL> -- V$SQL_SHARED_CURSORで子カーソルの生成理由を確認
SQL> SELECT SQL_ID, CHILD_ADDRESS, CHILD_NUMBER, HASH_MATCH_FAILED, BIND_LENGTH_UPGRADEABLE
  2  FROM V$SQL_SHARED_CURSOR WHERE SQL_ID = '5f5u0gky3kjpc';

SQL_ID        CHILD_ADDRESS    CHILD_NUMBER H B
------------- ---------------- ------------ - -
5f5u0gky3kjpc 000000006EB29608            0 N N
5f5u0gky3kjpc 000000006C94E5C0            1 Y Y
5f5u0gky3kjpc 000000006E6F3638            2 Y Y

という訳で単純なINSERT文でも複数の子カーソルが生成されることを確認できました。

参考資料(マニュアル)

マニュアルも見とくんやで!彡(^)(^)

カーソルの不一致およびV$SQL_SHARED_CURSOR
http://docs.oracle.com/cd/E82638_01/TGSQL/improving-rwp-cursor-sharing.htm#GUID-5AC5DAC7-D5D0-4FF6-85E6-9A4C3B28C890
V$SQL_SHARED_CURSOR http://docs.oracle.com/cd/E82638_01/REFRN/V-SQL_SHARED_CURSOR.htm#GUID-4993A6DE-5658-4745-B43E-F5AD9DB8DCCC

2017-08-10

java の CallableStatementインタフェース で ストアド・プロシージャ をコールして、V$ACTIVE_SESSION_HISTORY の PROGRAM列 や MODULE列を見てみる。(Oracle Database + java)


java の CallableStatementインタフェースOracle Database の
ストアド・プロシージャ を コールして、V$ACTIVE_SESSION_HISTORY の
PROGRAM列 や MODULE列 に何がセットされるかを見てみるやで彡(゚)(゚)

下記サイトを参考にしながら書いてみたやで。
相変わらずjava不慣れマンなんで、そこは勘弁や彡(-)(-)

JDBCからストアドプロシージャを呼び出す(OracleSQL ServerMySQL
http://hito4-t.hatenablog.com/entry/2015/04/06/185902

インタフェースCallableStatement
https://docs.oracle.com/javase/jp/8/docs/api/java/sql/CallableStatement.html

try-with-resources文 ※8/11追記
http://docs.oracle.com/javase/jp/7/technotes/guides/language/try-with-resources.html


ストアド・プロシージャの定義は下記彡(゚)(゚)

CREATE OR REPLACE PROCEDURE PRC_CALL_SP
IS
  d_date DATE;
BEGIN
  FOR i IN 1..1000000
  LOOP
    SELECT SYSDATE INTO d_date FROM DUAL;
  END LOOP;
END;
/

javaソースのサンプルは下記彡(゚)(゚)
※8/11修正 Class.forName(〜)を削除、try-with-resources構文に変更
※8/15修正 exception廻りとかcommit廻りとかを修正

import java.sql.*;

public class StoredCall {
    public static void main(String[] args) {
        //initialize
        System.out.println("Init...");
        //DB connection info
        final String path = "jdbc:oracle:thin:@localhost:1521:orcl";  //path
        final String id = "XXXXXXXX";  //ID
        final String pw = "YYYYYYYY";  //password
        
        //try-with-resources Statement
        try (
            //DB Connect
            Connection conn = DriverManager.getConnection(path, id, pw);
            //Stored Procedure Statement Set.
            CallableStatement cs = conn.prepareCall("CALL PRC_CALL_SP()");
        ) {
            //AutoCommit Setting
            conn.setAutoCommit(false);
            //Stored Procedure Execute
            System.out.println("Call stored procedure...");
            cs.execute();
            //Commit
            conn.commit();
        } catch(SQLException ex) {
            //SQLException
            ex.printStackTrace();  //Error
        }
        //End
        System.out.println("End...");
    }
}

漢の生javacコンパイルIDEって何や?彡(゚)(゚)

javac -classpath .:${ORACLE_HOME}/jdbc/lib/ojdbc8.jar StoredCall.java

やはり漢の生java実行、IDEってn(ry

java -classpath .:${ORACLE_HOME}/jdbc/lib/ojdbc8.jar StoredCall

javaモジュールの実行結果、こちらはメッセージが出てくるだけ彡(゚)(゚)

Init...
Call stored procedure...
End...

下記は V$ACTIVE_SESSION_HISTORY の参照結果、
PROGRAM も MODULE も JDBC Thin Clientや!彡(゚)(゚)

SET LINESIZE 170;
SET PAGESIZE 300;
COLUMN sid FORMAT 9999;
COLUMN ss FORMAT A10;
COLUMN event FORMAT A30;
COLUMN program FORMAT A20;
COLUMN module FORMAT A20;
SELECT session_id AS sid
  ,    sql_id
  ,    top_level_sql_id
  ,    session_state as ss
  ,    event
  ,    program
  ,    module
FROM v$active_session_history
WHERE sample_time >= systimestamp - (3 / 24 / 60)
AND user_id = 131
ORDER BY sample_time DESC;

  SID SQL_ID        TOP_LEVEL_SQL SS         EVENT                          PROGRAM              MODULE
----- ------------- ------------- ---------- ------------------------------ -------------------- --------------------
   17 1vq4vx6n0r4cn 1vq4vx6n0r4cn ON CPU                                    JDBC Thin Client     JDBC Thin Client
   17               1vq4vx6n0r4cn ON CPU                                    JDBC Thin Client     JDBC Thin Client
   17 1vq4vx6n0r4cn 1vq4vx6n0r4cn ON CPU                                    JDBC Thin Client     JDBC Thin Client
   17 c749bc43qqfz3 1vq4vx6n0r4cn ON CPU                                    JDBC Thin Client     JDBC Thin Client
   17 c749bc43qqfz3 1vq4vx6n0r4cn ON CPU                                    JDBC Thin Client     JDBC Thin Client
   17 1vq4vx6n0r4cn 1vq4vx6n0r4cn ON CPU                                    JDBC Thin Client     JDBC Thin Client
   17 c749bc43qqfz3 1vq4vx6n0r4cn ON CPU                                    JDBC Thin Client     JDBC Thin Client
   17               1vq4vx6n0r4cn ON CPU                                    JDBC Thin Client     JDBC Thin Client
   17 c749bc43qqfz3 1vq4vx6n0r4cn ON CPU                                    JDBC Thin Client     JDBC Thin Client
   17 c749bc43qqfz3 1vq4vx6n0r4cn ON CPU                                    JDBC Thin Client     JDBC Thin Client
   17 c749bc43qqfz3 1vq4vx6n0r4cn ON CPU                                    JDBC Thin Client     JDBC Thin Client
:

SELECT sql_id, sql_text FROM V$SQL
WHERE sql_id IN ('1vq4vx6n0r4cn', 'c749bc43qqfz3');

SQL_ID        SQL_TEXT
------------- ---------------------------
c749bc43qqfz3 SELECT SYSDATE FROM DUAL
1vq4vx6n0r4cn CALL PRC_CALL_SP()

2017-07-27

2017-07-19

CLOBをSELECTして表示するjavaソース・サンプル(Oracle Database + java)

下記サイトを参考にしながら書いてみたやで。彡(゚)(゚)
ワイ java は不慣れなんで、そこは勘弁やで彡(-)(-)

SELECT文サンプル
http://java-reference.com/java_db_select.html

インタフェースClob
https://docs.oracle.com/javase/jp/8/docs/api/java/sql/Clob.html


表定義は下記彡(゚)(゚)

SQL> DESC LOB_TBL
 Name          Null?    Type
 ------------- -------- ----------------------------
 LOB_ID        NOT NULL NUMBER
 LOB_DATA               CLOB

javaソースのサンプルは下記彡(゚)(゚)

import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Clob;

public class LOBSelectSample {
    public static void main(String[] args) throws Exception{
        //initialize
        System.out.println("Init...");
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        Clob cl = null;

        //DB connection info
        String path = "jdbc:oracle:thin:@localhost:1521:orcl";  //path
        String id = "xxxxxxxx";  //ID
        String pw = "yyyyyyyy";  //password

        try{
            //JDBC Driver
            Class.forName("oracle.jdbc.driver.OracleDriver");

            //DB Connect
            System.out.println("Connect...");
            conn = DriverManager.getConnection(path, id, pw);

            //SELECT
            System.out.println("Select...");
            ps = conn.prepareStatement("SELECT * FROM LOB_TBL");
            rs = ps.executeQuery();

            //Column count
            int colCount = rs.getMetaData().getColumnCount();
            System.out.println("Get Column:" + colCount);

            //Output
            while (rs.next()) {
                System.out.print(rs.getInt("LOB_ID"));
                System.out.println();
                cl = rs.getClob("LOB_DATA");
                if (cl != null) {
                    System.out.print(cl.getSubString(1, (int)cl.length()));
                    //System.out.print(cl.getSubString(1, 2097152));
                }
                System.out.println();
            }
        } catch(Exception ex) {
            //Exception
            ex.printStackTrace();  //Error
        } finally {
            //Close
            if(rs != null) rs.close();
            if(ps != null) ps.close();
            if(conn != null) conn.close();
        }
    }
}

コンパイル、漢は黙って生javaや!彡(゚)(゚)

javac -classpath .:${ORACLE_HOME}/jdbc/lib/ojdbc8.jar LOBSelectSample.java

実行コマンド、漢は黙っt(ry

java -classpath .:${ORACLE_HOME}/jdbc/lib/ojdbc8.jar LOBSelectSample

実行結果、LOB_DATA列に突っ込んどいたSQLテキストが出て来たやで彡(^)(^)

Init...
Connect...
Select...
Get Column:2
1

2
with …
:
(中略)
:
… from dual

2017-07-14

SET FEEDBACK ONLY と SET TIMING ON で SQL の結果を表示せずに性能計測(Oracle Database 12cR2新機能)

SQL*Plus の 12cR2の新機能 で、SET FEEDBACK ONLY をセットすると、
結果を表示せずに行数だけを表示できるんやで彡(゚)(゚)

SQL*Plus ユーザーズ・ガイドおよびリファレンス リリース2 (12.2) E81324-02
SET FEED[BACK]
http://docs.oracle.com/cd/E82638_01/SQPUG/SET-system-variable-summary.htm#GUID-2C90B73B-A7E0-4357-9382-5EBAF53BF528

ONLYにより、問合せで選択された行の数が返されます。


試しに実行してみると…

SQL> SET TIMING ON;
SQL> SET FEEDBACK ONLY;
SQL> SELECT LEVEL FROM DUAL CONNECT BY LEVEL <= 100;

100 rows selected.

Elapsed: 00:00:00.00

結果を表示せずずに SET TIMING ON の Elapsed を確認できたやで彡(^)(^)