10.2 リモートLOBでのデータ・インタフェースの使用
データ・インタフェースを使用すると、CLOB列に対してCHARACTERバッファをバインドおよび定義し、BLOB列に対してRAWバッファをバインドおよび定義できます。このインタフェースは、リモートLOB列でもサポートされます。
LOBロケータを使用するよりもデータ・インタフェースを使用する利点は、LOBデータをフェッチするためにリモート・サーバーへのラウンドトリップを1回のみ行うことです。配列のバインドまたは定義の一部として使用する場合、配列操作全体に対して1回のラウンドトリップのみが使用されます。
このマニュアルで説明されている例では、dbs1スキーマとdbs2スキーマで作成されたprint_media表を使用します。例で使用されているprint_media表のCLOB列は、ad_finaltextです。次の各項のPL/SQL、OCIおよびJavaの例では、この列のバインドおよび定義を使用していますが、複数の列にアクセスすることもできます。サポートされる機能は次のとおりです。
-
CLOBをVARCHAR2として、BLOBをRAWとしてバインドおよび定義できます。 - 配列のバインドおよび定義はサポートされています。
この項では、PL/SQLでLOBとリモート・データ・インタフェースを使用する方法について説明します。
PL/SQLにおけるデータ・インタフェースでは、サイズが32KB未満のデータのみがサポートされています。次にPL/SQLの例を示します。
CONNECT pm/pm declare my_ad varchar(6000) := lpad('b', 6000, 'b'); BEGIN INSERT INTO print_media@dbs2(product_id, ad_id, ad_finaltext) VALUES (10000, 10, my_ad); -- Reset the buffer value my_ad := 'a'; SELECT ad_finaltext INTO my_ad FROM print_media@dbs2 WHERE product_id = 10000; END; /
ad_finaltextがCLOBではなくBLOB列である場合、my_adはRAW型である必要があります。LOBのサイズが32KB - 1を超えている場合、PL/SQLでは切捨てエラーが発生し、バッファの内容は未定義になります。
この項では、JDBCでLOBと一緒にリモート・データ・インタフェースを使用する方法を示します。
次のコード・スニペットは、すべてのJDBCドライバで機能します。
バインド:
非ストリーミング・モードの場合:
... String sql = "insert into print_media@dbs2 (product_id, ad_id, ad_final_text)" + " values (:1, :2, :3)"; PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setInt( 1, 2 ); pstmt.setInt( 2, 20); pstmt.setString( 3, "Java string" ); int rows = pstmt.executeUpdate(); ...
ノート: Oracleでは、最大2GBのサイズの文字列に対して非ストリーミング・モードがサポートされます。ただし、コンピュータのメモリー・サイズが制限要因になる場合があります。
ストリーミング・モードの場合、前述と同じコードが機能しますが、setString()文は次のいずれかで置き換えられます。
pstmt.setCharacterStream( 3, new LabeledReader(), 1000000 ); pstmt.setAsciiStream( 3, new LabeledAsciiInputStream(), 1000000 );
ノート: ストリーミング・インタフェースを使用して、ギガバイト・サイズの文字およびバイナリ・データをLOB列に挿入できます。
ここで、LabeledReader()およびLabeledAsciiInputStream()により、それぞれ文字ストリームおよびASCIIストリームが生成されます。ad_finaltextがCLOBではなくBLOB列である場合、前述の例は、バインドがRAW型である場合に機能します。
pstmt.setBytes( 3, <some byte[] array> ); pstmt.setBinaryStream( 3, new LabeledInputStream(), 1000000 );
ここで、LabeledInputStream()によってバイナリ・ストリームが生成されます。
定義:
非ストリーミング・モードの場合:
OracleStatement stmt = (OracleStatement)(conn.createStatement());
stmt.defineColumnType( 1, Types.VARCHAR );
ResultSet rst = stmt.executeQuery("select ad_finaltext from print_media@dbs2" );
while( rst.next() )
{
String s = rst.getString( 1 );
System.out.println( s );
}
ノート: LOBサイズが32767バイトより大きい場合、データは切り捨てられ、エラーはスローされません。
ストリーミング・モードの場合:
OracleStatement stmt = (OracleStatement)(conn.createStatement());
stmt.defineColumnType( 1, Types.LONGVARCHAR );
ResultSet rs = stmt.executeQuery("select ad_finaltext from print_media@dbs2" );
while(rs.next()) {
Reader reader = rs.getCharacterStream( 1 );
int data = 0;
data = reader.read();
while( -1 != data ){
System.out.print( (char)(data) );
data = reader.read();
}
reader.close();
}ノート: データ型をLONGVARCHARとして指定すると、LOB全体を選択できます。定義タイプがLONGVARCHARではなくVARCHARに設定されている場合、データは32kで切り捨てられます。
ad_finaltextがCLOBではなくBLOB列である場合、前述の例は、定義がLONGVARBINARY型である場合に機能します。
...
OracleStatement stmt = (OracleStatement)conn.createStatement();
stmt.defineColumnType( 1, Types.INTEGER );
stmt.defineColumnType( 2, Types.LONGVARBINARY );
ResultSet rset = stmt.executeQuery("SELECT ID, LOBCOL FROM LOBTAB@MYSELF");
while(rset.next())
{
/* using getBytes() */
/*
byte[] b = rset.getBytes("LOBCOL");
System.out.println("ID: " + rset.getInt("ID") + " length: " + b.length);
*/
/* using getBinaryStream() */
InputStream byte_stream = rset.getBinaryStream("LOBCOL");
byte [] b = new byte [100000];
int b_len = byte_stream.read(b);
System.out.println("ID: " + rset.getInt("ID") + " length: " + b_len);
byte_stream.close();
}
...この項では、OCIでLOBと一緒にリモート・データ・インタフェースを使用する方法を示します。
OCIにおけるデータ・インタフェースでは、サイズが2 GB未満(sb4として宣言された変数の可能な最大値)のデータのみがサポートされます。次の疑似コードは、OCIプログラムの一部として拡張できます。
... text *sql = (text *)"insert into print_media@dbs2 (product_id, ad_id, ad_finaltext) values (:1, :2, :3)"; OCIStmtPrepare(...); OCIBindByPos(...); /* Bind data for positions 1 and 2 * which are independent of LOB */ OCIBindByPos(stmthp, &bndhp[2], errhp, (ub4) 3, (dvoid *) charbuf1, (sb4) len_charbuf1, SQLT_CHR, (dvoid *) 0, (ub2 *)0, (ub2 *)0, 0, 0, OCI_DEFAULT); OCIStmtExecute(...); ... text *sql = (text *)"select ad_finaltext from print_media@dbs2 where product_id = 10000"; OCIStmtPrepare(...); OCIDefineByPos(stmthp, &dfnhp[2], errhp, (ub4) 1, (dvoid *) charbuf2, (sb4) len_charbuf2, SQLT_CHR, (dvoid *) 0, (ub2 *)0, (ub2 *)0, OCI_DEFAULT); OCIStmtExecute(...); ...
BLOB列には、SQLT_BIN型を使用する必要があります。たとえば、ad_finaltext列をCLOB列ではなくBLOB列として定義する場合、SQLT_BIN型を使用して列データをバインドおよび定義する必要があります。LOBのサイズが2GB - 1バイトを超えている場合、OCIでは切捨てエラーが発生し、バッファの内容は未定義になります。
この項では、リモートLOBでのデータ・インタフェースの使用に関する制限事項について説明します。
特定の構文はリモートLOBではサポートされていません。
-
複数のデータベースを使用する問合せはサポートされていません。
SELECT t1.lobcol, a2.lobcol FROM t1, t2.lobcol@dbs2 a2 WHERE LENGTH(t1.lobcol) = LENGTH(a2.lobcol);
次の問合せもサポートされていません(PL/SQLブロック内)。
SELECT t1.lobcol INTO varchar_buf1 FROM t1@dbs1 UNION ALL SELECT t2.lobcol INTO varchar_buf2 FROM t2@dbs2;
-
リモートの永続LOB列に移動するデータに対するバインドおよび定義のみがサポートされているため、リモートLOBに対して
CHARデータがバインドまたは定義されているPL/SQLで渡されるパラメータは、サポートされていないリモートの一時LOBが発生する可能性があるので許可されません。次の文ではすべて、エラーが生成されます。SELECT foo() INTO varchar_buf FROM table1@dbs2; -- foo returns a LOB SELECT foo()@dbs INTO char_val FROM DUAL; -- foo returns a LOB SELECT XMLType().getclobval INTO varchar_buf FROM table1@dbs2;
-
リモート・オブジェクトが次のようなビューである場合。
CREATE VIEW v AS SELECT foo() a FROM ... ; -- foo returns a LOB /* The local database then tries to get the CLOB data and returns an error */ SELECT a INTO varchar_buf FROM v@dbs2;
これによってサポートされていないリモートの一時LOBが発生するため、エラーが戻されます。
-
RETURNINGINTOでは、CHARとCLOBの間の暗黙的な変換はサポートされていません。 -
実引数がLOB型であり、リモート引数が
VARCHAR2、NVARCHAR2、CHAR、NCHARまたはRAWである場合、PL/SQLパラメータの受渡しは許可されません。
- PL/SQLにおけるリモート・データ・インタフェースの例
この項では、PL/SQLのLOBでリモート・データ・インタフェースを使用する方法について説明します。 - JDBCにおけるリモート・データ・インタフェースの例
この項では、JDBCにおけるLOBでリモート・データ・インタフェースを使用する方法を示します。 - OCIにおけるリモート・データ・インタフェースの例
この項では、OCIにおけるLOBでのリモート・データ・インタフェースの使用方法を示します。 - リモートLOBでのデータ・インタフェースに関する制限事項
この項では、リモートLOBでのデータ・インタフェースの使用に関する制限事項について説明します。
親トピック: 分散LOB
10.2.1 PL/SQLにおけるリモート・データ・インタフェースの例
この項では、PL/SQLでLOBとリモート・データ・インタフェースを使用する方法について説明します。
PL/SQLにおけるデータ・インタフェースでは、サイズが32KB未満のデータのみがサポートされています。次にPL/SQLの例を示します。
CONNECT pm/pm declare my_ad varchar(6000) := lpad('b', 6000, 'b'); BEGIN INSERT INTO print_media@dbs2(product_id, ad_id, ad_finaltext) VALUES (10000, 10, my_ad); -- Reset the buffer value my_ad := 'a'; SELECT ad_finaltext INTO my_ad FROM print_media@dbs2 WHERE product_id = 10000; END; /
ad_finaltextがCLOBではなくBLOB列である場合、my_adはRAW型である必要があります。LOBのサイズが32KB - 1を超えている場合、PL/SQLでは切捨てエラーが発生し、バッファの内容は未定義になります。
親トピック: リモートLOBでのデータ・インタフェースの使用
10.2.2 JDBCにおけるリモート・データ・インタフェースの例
この項では、JDBCでLOBと一緒にリモート・データ・インタフェースを使用する方法を示します。
次のコード・スニペットは、すべてのJDBCドライバで機能します。
バインド:
非ストリーミング・モードの場合:
... String sql = "insert into print_media@dbs2 (product_id, ad_id, ad_final_text)" + " values (:1, :2, :3)"; PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setInt( 1, 2 ); pstmt.setInt( 2, 20); pstmt.setString( 3, "Java string" ); int rows = pstmt.executeUpdate(); ...
ノート:
Oracleでは、最大2 GBのサイズの文字列に対して非ストリーミング・モードがサポートされます。ただし、コンピュータのメモリー・サイズが制限要因になる場合があります。ストリーミング・モードの場合、前述と同じコードが機能しますが、setString()文は次のいずれかで置き換えられます。
pstmt.setCharacterStream( 3, new LabeledReader(), 1000000 ); pstmt.setAsciiStream( 3, new LabeledAsciiInputStream(), 1000000 );
ノート:
ストリーミング・インタフェースを使用して、ギガバイト・サイズの文字およびバイナリ・データをLOB列に挿入できます。ここで、LabeledReader()およびLabeledAsciiInputStream()により、それぞれ文字ストリームおよびASCIIストリームが生成されます。ad_finaltextがCLOBではなくBLOB列である場合、前述の例は、バインドがRAW型である場合に機能します。
pstmt.setBytes( 3, <some byte[] array> ); pstmt.setBinaryStream( 3, new LabeledInputStream(), 1000000 );
ここで、LabeledInputStream()によってバイナリ・ストリームが生成されます。
定義:
非ストリーミング・モードの場合:
OracleStatement stmt = (OracleStatement)(conn.createStatement());
stmt.defineColumnType( 1, Types.VARCHAR );
ResultSet rst = stmt.executeQuery("select ad_finaltext from print_media@dbs2" );
while( rst.next() )
{
String s = rst.getString( 1 );
System.out.println( s );
}
ノート:
LOBサイズが32767バイトより大きい場合、データは切り捨てられ、エラーはスローされません。ストリーミング・モードの場合:
OracleStatement stmt = (OracleStatement)(conn.createStatement());
stmt.defineColumnType( 1, Types.LONGVARCHAR );
ResultSet rs = stmt.executeQuery("select ad_finaltext from print_media@dbs2" );
while(rs.next()) {
Reader reader = rs.getCharacterStream( 1 );
int data = 0;
data = reader.read();
while( -1 != data ){
System.out.print( (char)(data) );
data = reader.read();
}
reader.close();
}ノート:
データ型をLONGVARCHARとして指定すると、LOB全体を選択できます。定義タイプがLONGVARCHARではなくVARCHARに設定されている場合、データは32kで切り捨てられます。
ad_finaltextがCLOBではなくBLOB列である場合、前述の例は、定義がLONGVARBINARY型である場合に機能します。
...
OracleStatement stmt = (OracleStatement)conn.createStatement();
stmt.defineColumnType( 1, Types.INTEGER );
stmt.defineColumnType( 2, Types.LONGVARBINARY );
ResultSet rset = stmt.executeQuery("SELECT ID, LOBCOL FROM LOBTAB@MYSELF");
while(rset.next())
{
/* using getBytes() */
/*
byte[] b = rset.getBytes("LOBCOL");
System.out.println("ID: " + rset.getInt("ID") + " length: " + b.length);
*/
/* using getBinaryStream() */
InputStream byte_stream = rset.getBinaryStream("LOBCOL");
byte [] b = new byte [100000];
int b_len = byte_stream.read(b);
System.out.println("ID: " + rset.getInt("ID") + " length: " + b_len);
byte_stream.close();
}
...親トピック: リモートLOBでのデータ・インタフェースの使用
10.2.3 OCIにおけるリモート・データ・インタフェースの例
この項では、OCIでLOBと一緒にリモート・データ・インタフェースを使用する方法を示します。
OCIにおけるデータ・インタフェースでは、サイズが2 GB未満(sb4として宣言された変数の可能な最大値)のデータのみがサポートされます。次の疑似コードは、OCIプログラムの一部として拡張できます。
... text *sql = (text *)"insert into print_media@dbs2 (product_id, ad_id, ad_finaltext) values (:1, :2, :3)"; OCIStmtPrepare(...); OCIBindByPos(...); /* Bind data for positions 1 and 2 * which are independent of LOB */ OCIBindByPos(stmthp, &bndhp[2], errhp, (ub4) 3, (dvoid *) charbuf1, (sb4) len_charbuf1, SQLT_CHR, (dvoid *) 0, (ub2 *)0, (ub2 *)0, 0, 0, OCI_DEFAULT); OCIStmtExecute(...); ... text *sql = (text *)"select ad_finaltext from print_media@dbs2 where product_id = 10000"; OCIStmtPrepare(...); OCIDefineByPos(stmthp, &dfnhp[2], errhp, (ub4) 1, (dvoid *) charbuf2, (sb4) len_charbuf2, SQLT_CHR, (dvoid *) 0, (ub2 *)0, (ub2 *)0, OCI_DEFAULT); OCIStmtExecute(...); ...
BLOB列には、SQLT_BIN型を使用する必要があります。たとえば、ad_finaltext列をCLOB列ではなくBLOB列として定義する場合、SQLT_BIN型を使用して列データをバインドおよび定義する必要があります。LOBのサイズが2GB - 1バイトを超えている場合、OCIでは切捨てエラーが発生し、バッファの内容は未定義になります。
親トピック: リモートLOBでのデータ・インタフェースの使用
10.2.4 リモートLOBでのデータ・インタフェースに関する制限事項
この項では、リモートLOBでのデータ・インタフェースの使用に関する制限事項について説明します。
特定の構文はリモートLOBではサポートされていません。
-
複数のデータベースを使用する問合せはサポートされていません。
SELECT t1.lobcol, a2.lobcol FROM t1, t2.lobcol@dbs2 a2 WHERE LENGTH(t1.lobcol) = LENGTH(a2.lobcol);
次の問合せもサポートされていません(PL/SQLブロック内)。
SELECT t1.lobcol INTO varchar_buf1 FROM t1@dbs1 UNION ALL SELECT t2.lobcol INTO varchar_buf2 FROM t2@dbs2;
-
RETURNINGINTOでは、CHARとCLOBの間の暗黙的な変換はサポートされていません。 -
実引数がLOB型であり、リモート引数が
VARCHAR2、NVARCHAR2、CHAR、NCHARまたはRAWである場合、PL/SQLパラメータの受渡しは許可されません。
親トピック: リモートLOBでのデータ・インタフェースの使用