5 分散LOB
5.1 リモートLOBの操作
リモート表のLOBデータは次の方法で操作できます。
-
データべース・リンクを使用してアクセスされるリモート表のLOB列(リモートLOB列)を直接参照する。
-
ローカルLOBロケータ変数にリモートLOB列を選択する(リモート・ロケータ)。
内容は次のとおりです。
5.1.1 リモートLOB列の操作
リモートLOBは、次の形式でサポートされています。
5.1.1.1 AS SELECT形式での表の作成または挿入
次の形式で作成された文の選択リストでは、スタンドアロンのLOB列のみ使用できます。
CREATE TABLE t AS SELECT * FROM table1@remote_site;
INSERT INTO t SELECT * FROM table1@remote_site;
UPDATE t SET lobcol = (SELECT lobcol FROM table1@remote_site);
INSERT INTO table1@remote_site SELECT * FROM local_table;
UPDATE table1@remote_site SET lobcol = (SELECT lobcol FROM local_table);
DELETE FROM table1@remote_site <WHERE clause involving non_lob_columns>
5.1.1.2 スカラーを戻すリモートLOB上のファンクション
LOBパラメータを含み、スカラー・データ型を戻すSQLおよびPL/SQLファンクションがサポートされています。他のSQLファンクションとDBMS_LOB
APIの場合、リモートのLOB列に対する使用はサポートされていません。たとえば、次の文はサポートされています。
CREATE TABLE tab AS SELECT DBMS_LOB.GETLENGTH@dbs2(clob_col) len FROM tab@dbs2;
CREATE TABLE tab AS SELECT LENGTH(clob_col) len FROM tab@dbs2;
ただし、次の文は、DBMS_LOB.SUBSTR
がLOBを戻すため、サポートされていません。
CREATE TABLE tab AS SELECT DBMS_LOB.SUBSTR(clob_col) from tab@dbs2;
5.1.1.3 リモートLOB用のデータ・インタフェース
文字またはバイナリのバッファをリモートのCLOB
またはBLOB
に挿入、およびリモートのCLOB
またはBLOB
を選択して、(PL/SQLを使用するなどで)文字またはバイナリのバッファに挿入できます。
SELECT clobcol1, type1.blobattr INTO varchar_buf1, raw_buf2 FROM table1@remote_site;
INSERT INTO table1@remotesite (clobcol1, type1.blobattr) VALUES varchar_buf1, raw_buf2;
INSERT INTO table1@remotesite (lobcol) VALUES ('test');
UPDATE table1 SET lobcol = 'xxx';
5.1.2 リモート・ロケータの操作
ローカル変数にリモート表からの永続LOBロケータを選択できます。これはPL/SQLまたはOCIで実行できます。リモート列の型にはBLOB、CLOBまたはNCLOBのいずれかを指定できます。この章のリモートLOBロケータのすべての例は次のSQL文が基礎となっています。
CREATE TABLE lob_tab (c1 NUMBER, c2 CLOB);
次の例では、リモート・データベースで定義されている表lob_tab
(CLOB
型の列c2
とnumber型のc1
を使用)に、データベース・リンクdb2
とローカルのCLOB
変数lob_var1
を使用してアクセスできます。
SELECT c2 INTO lob_var1 FROM lob_tab@db2 WHERE c1=1;
SELECT c2 INTO lob_var1 FROM lob_tab@db2 WHERE c1=1 for update;
PL/SQLでは、ファンクションdbms_lob.isremote
を使用して特定のLOBがリモート表に属しているかどうかを確認できます。同様に、OCI
では、OCILobLocator
のOCI_ATTR_LOB_REMOTE
属性を使用して特定のLOBがリモート表に属しているかどうか確認できます。次に例を示します。
IF(dbms_lob.isremote(lob_var1)) THEN
dbms_output.put_line(‘LOB locator is remote)
ENDIF;
関連項目:
-
ISREMOTEファンクション
内容は次のとおりです。
5.1.2.1 リモート表での問合せとDMLを使用したバインドとしてのローカル・ロケータおよびリモート・ロケータの使用
バインド値でクエリおよびDML (INSERT
、UPDATE
、DELETE
)を使用する場合は、次の4つのケースが考えられます。1つ目は、ローカルの表とロケータを必要とする、標準のLOB機能です。他の3つは分散LOB機能で、このセクションの終わりにリストされている制限があります。
-
バインド値としてローカル・ロケータを使用するローカル表。
-
バインド値としてリモート・ロケータを使用するローカル表
-
バインド値としてローカル・ロケータを使用するリモート表
-
バインド値としてリモート・ロケータを使用するリモート表
リモートLOBロケータを使用する次のような形の問合せはサポートされません。
SELECT name FROM lob_tab@db2 WHERE length(c1)=length(:lob_v1);
前述の問合せでは、c1
はLOB列、lob_v1
がリモート・ロケータになります。
リモートLOBロケータを使用する次のような形のDMLはサポートされます。ここで、バインド値にはローカルまたはリモートの永続LOBロケータを指定できます。
UPDATE lob_tab@db2 SET c1=:lob_v1;
INSERT into lob_tab@db2 VALUES (:1, :2);
ノート:
returning
句を含むDMLは、スカラーおよびLOB両方の列についてリモート表でサポートされません。
5.1.2.2 リモートLOBロケータ使用時の制限
リモートLOBロケータ使用時の一般的な制限は次のとおりです。
-
SELECT
文を使用してローカル変数にリモートの一時LOBロケータを選択することはできません。次に例を示します。select substr(c2, 3, 1) from lob_tab@db2 where c1=1
前述の問合せはエラーを返します。
-
リモートLOB機能は、索引構成表(IOT)ではサポートされません。リモートからロケータを取得しようとすると、IOT表でエラーが発生します。
-
ローカル・データベースとリモート・データベースのいずれもデータベース12.2以上のバージョンであることが必要です。
-
分散LOB機能では、
from
句またはwhere
句に指定されている表は同じデータベースで収集する必要があります。リモート・ロケータをwhere
句のバインド変数として使用する場合、これらのロケータは同じリモート・データベースに属している必要があります。DB1のロケータを1つとDB2の別のロケータをバインド変数として使用できません。 -
収集した表またはロケータでは同じデータベース・リンクが使用されます。同じデータベースをポイントする2つの異なるDBリンクを使用できます。次の例では、
dblink1
とdblink2
の両方が同じリモート・データベースをポイントしていますが、認証方法が異なっている可能性があります。Oracle Databaseはこのような操作をサポートしません。INSERT into tab1@dblink1 SELECT * from tab2@dblink2;
-
バインド値は列のLOB型と同じLOB型であることが必要です。たとえば、
NCLOB
ロケータはNCLOB
列にバインドされ、CLOB
ロケータはCLOB
列にバインドされる必要があります。NCLOB
型とCLOB
型間の暗黙の変換はリモートLOBではサポートされません。 -
配列バインドでのDML (
INSERT
/UPDATE
)は、バインドにリモート・ロケータが必要な場合や関連する表にリモート表である場合はサポートされません。 -
ローカル変数にリモート表からの
BFILE
列は選択できません。
5.2 リモート表のLOBでのSQLセマンティクス
5.2.1 リモートLOBおよびBFILE用の組込みファンクション
ネストしたファンクションによって戻される最終値がLOB型でないかぎり、ローカルのLOBとBFILEでサポートされるすべてのSQL組込みファンクションおよびユーザー定義型ファンクションは、リモートのLOBとBFILEでもサポートされます。これには、リモートの永続および一時LOBとBFILE用のファンクションも含まれます。
リモート・サイトで実行されるSQL組込みファンクションは、SELECT
、INSERT
、UPDATE
およびDELETE
と同様に、SQL文内に含めることができます。次に例を示します。
SELECT LENGTH(ad_sourcetext) FROM print_media@remote_site -- CLOB
SELECT LENGTH(ad_fltextn) FROM print_media@remote_site; -- NCLOB
SELECT LENGTH(ad_composite) FROM print_media@remote_site; -- BLOB
SELECT product_id from print_media@remote_site WHERE LENGTH(ad_sourcetext) > 3;
UPDATE print_media@remote_site SET product_id = 2 WHERE LENGTH(ad_sourcetext) > 3;
SELECT TO_CHAR(foo@dbs2(...)) FROM dual@dbs2;
-- where foo@dbs2 returns a temporary LOB
SQLファンクションは、次のカテゴリに分類されます(ただし、必ずしもこれに限定されません)。
-
LOBでサポートされていないSQLファンクションは次のとおりです。
これらの関数は、
CLOB
にのみ関連します。たとえばDECODE
などです。これらのファンクションは、ローカルのLOBでサポートされないため、リモートのLOBではサポートされません。
-
1つのLOB引数のみ(その他の引数は他のデータ型)を受け入れ、LOBを戻さないファンクション:
これらのファンクションは、CLOB、NCLOBおよびBLOBのみに該当します。たとえば
LENGTH
が該当し、これはサポートされています。次に例を示します。SELECT LENGTH(ad_composite) FROM print_media@remote_site; SELECT LENGTH(ad_header.logo) FROM print_media@remote_site; -- LOB in object SELECT product_id from print_media@remote_site WHERE LENGTH(ad_sourcetext) > 3;
-
LOBを戻すファンクション:
これらのファンクションは、すべてCLOBおよびNCLOBのみに該当します。これらのファンクションは、元のLOBを戻すか、または一時LOBを生成する場合があります。これらのファンクションは、ローカル・サイトに戻される結果がLOBでないかぎり、リモート・サイトで実行できます。
一時LOBを戻すファンクションには、
REPLACE
、SUBSTR
、CONCAT
、||、TRIM
、LTRIM
、RTRIM
、LOWER
、UPPER
、NLS_LOWER
、NLS_UPPER
、LPAD
、およびRPAD
があります。元のLOBロケータを戻すファンクションには、
NVL
、DECODE
およびCASE
があります。現在、DECODE
およびCASE
ではLOBの操作はサポートされていませんが、他のデータ型を操作でき、LOBを戻すことができます。たとえば、次の文がサポートされています。
SELECT TO_CHAR(CONCAT(ad_sourcetext, ad_sourcetext)) FROM print_media@remote_site; SELECT TO_CHAR(SUBSTR(ad_fltextnfs, 1, 3)) FROM print_media@remote_site;
しかし、次の文はサポートされていません。
SELECT CONCAT(ad_sourcetext, ad_sourcetext) FROM print_media@remote_site; SELECT SUBSTR(ad_sourcetext, 1, 3) FROM print_media@remote_site;
-
1つ以上のLOB引数を受け入れるファンクション。
これらには、
INSTR
、LIKE
、REPLACE
、CONCAT
、||、SUBSTR
、TRIM
、LTRIM
、RTRIM
、LPAD
およびRPAD
があります。これらのファンクションは、すべてCLOB
およびNCLOB
のみに該当します。すべてのLOBが同じ
dblink
内にあり、戻される値がLOBでない場合にのみ、これらのファンクションがサポートされます。たとえば、次がサポートされています。SELECT TO_CHAR(CONCAT(ad_sourcetext, ad_sourcetext)) FROM print_media@remote_site; -- CLOB SELECT TO_CHAR(CONCAT(ad_fltextn, ad_fltextn)) FROM print_media@remote_site; -- NCLOB
しかし、次はサポートされていません。
SELECT TO_CHAR(CONCAT(a.ad_sourcetext, b.ad_sourcetext)) FROM print_media@db1 a, print_media@db2 b WHERE a.product_id = b.product_id;
5.3 PL/SQLでのリモートLOBの操作
内容は次のとおりです。
5.3.1 リモートLOBおよびBFILE用のPL/SQLファンクション
ネストしたファンクションによって戻される最終値がLOBでないかぎり、リモート・サイトで実行され、リモートLOBとBFILEを操作する、組込みおよびユーザー定義型PL/SQLファンクションを使用できます。
次の例では、「LOBの例の表: PMスキーマのprint_media表」で説明されているprint_media
表を使用します
SELECT product_id FROM print_media@dbs2 WHERE foo@dbs2(ad_sourcetext, 'aa') > 0;
-- foo is a user-define function returning a NUMBER
DELETE FROM print_media@dbs2 WHERE DBMS_LOB.GETLENGTH@dbs2(ad_graphic) = 0;
5.3.1.1 リモートのユーザー定義型ファンクションの制限
-
SQLファンクションに適用される制限はここにも適用されます。
-
1つの
dblink
内のファンクションは、他のdblink内のLOBデータを操作できません。たとえば、次の文はサポートされていません。SELECT a.product_id FROM print_media@dbs1 a, print_media@dbs2 b WHERE CONTAINS@dbs1(b.ad_sourcetext, 'aa') > 0;
-
1つの問合せブロックに、異なる
dblink
の表およびファンクションを含めることはできません。たとえば、次の文はサポートされていません。SELECT a.product_id FROM print_media@dbs2 a, print_media@dbs3 b WHERE CONTAINS@dbs2(a.ad_sourcetext, 'aa') > 0 AND foo@dbs3(b.ad_sourcetext) > 0; -- foo is a user-defined function in dbs3
-
PL/SQLからのSQL文の発行以外、PL/SQL内からのリモートLOB操作の実行(
DBMS_LOB
)はサポートされていません。
5.3.1.2 PL/SQL、OCIおよびJDBC内のリモート・ファンクション
「リモートのユーザー定義型ファンクションの制限」にリストされているすべてのSQL文は、PL/SQL、OCI、JDBC内から実行された場合、同じように機能します。追加機能はありません。
5.3.2 PL/SQLでのリモート・ロケータの使用
LENGTH
、INSTR
、SUBSTR
、UPPER
などの組込みPL/SQLファンクションとして渡すことができます。次に例を示します。DECLARE
substr_data varchar2(4000);
remote_loc CLOB;
BEGIN
SELECT c2 into remote_loc
FROM lob_tab@db2 WHERE c1=1;
substr_data := substr(remote_loc, position, length)
END;
5.3.3 DBMS_LOB
でのリモート・ロケータの使用
BFILEを対象としたAPIを除くすべてのDBMS_LOB
APIは、リモートLOBロケータでの操作をサポートします。
次の例は、dbms_lob
操作の入力としてリモート・ロケータを渡す方法を示しています。
DECLARE
lob CLOB;
buf VARCHAR2(120) := 'TST';
amt NUMBER(2);
len NUMBER(2);
BEGIN
amt :=30;
select c2 into lob from lob_tab@db2 where c1=3 for update;
dbms_lob.write(lob, amt, 1, buf);
amt :=30;
dbms_lob.read(lob, amt, 1, buf);
len := dbms_lob.getlength(lob);
dbms_output.put_line(buf);
dbms_output.put_line(amt);
dbms_output.put_line('get length output = ' || len);
END;
/
内容は次のとおりです。
5.3.3.1 DBMS_LOB
でのリモート・ロケータの使用に関する制限
2つのLOBロケータを受け付けるすべてのAPIでは、両方のLOBを1つのデータベースで収集する必要があります。
関連項目:
-
DBMS_LOB
APIの完全なリストについては、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。
5.4 OCILOB
APIでのリモート・ロケータの使用
(BFILEを対象としたAPIを除く)すべてのOCILOB
APIは、リモートLOB
での操作をサポートします。
ノート:
2つのロケータを受け付けるすべてのAPIは、両方のLOBロケータを同じデータベース・リンクから取得する必要があります。次のOCILOB
ファンクションのリストには、リモートLOB
ロケータがそれらのファンクションに渡された場合にエラーが示されます。
-
OCILobAssign
-
OCILobLocatorAssign
-
OCILobArrayRead()
-
OCILobArrayWrite()
-
OCILobLoadFromFile2()
次の例は、リモート・ロケータをOCILOB
APIに渡す方法を示しています。
void select_read_remote_lob()
{
text *select_sql = (text *)"SELECT c2 lob_tab@dbs1 where c1=1";
ub4 amtp = 10;
ub4 nbytes = 0;
ub4 loblen=0;
OCILobLocator * one_lob;
text strbuf[40];
/* initialize single locator */
OCIDescriptorAlloc(envhp, (dvoid **) &one_lob,
(ub4) OCI_DTYPE_LOB,
(size_t) 0, (dvoid **) 0)
OCIStmtPrepare(stmthp, errhp, select_sql, (ub4)strlen((char*)select_sql),
(ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT);
OCIDefineByPos(stmthp, &defp, errhp, (ub4) 1,
(dvoid *) &one_lob,
(sb4) -1,
(ub2) SQLT_CLOB,
(dvoid *) 0, (ub2 *) 0,
(ub2 *) 0, (ub4) OCI_DEFAULT));
/* fetch the remote locator into the local variable one_lob */
OCIStmtExecute(svchp, stmthp, errhp, 1, 0, (OCISnapshot *)0,
(OCISnapshot *)0, OCI_DEFAULT);
/* Get the length of the remote LOB */
OCILobGetLength(svchp, errhp,
(OCILobLocator *) one_lob, (ub4 *)&loblen)
printf("LOB length = %d\n", loblen);
memset((void*)strbuf, (int)'\0', (size_t)40);
/ * Read the data from the remote LOB */
OCILobRead(svchp, errhp, one_lob, &amtp,
(ub4) 1, (dvoid *) strbuf, (ub4)& nbytes, (dvoid *)0,
(OCICallbackLobRead) 0,
(ub2) 0, (ub1) SQLCS_IMPLICIT));
printf("LOB content = %s\n", strbuf);
}
関連項目:
OCILOB
APIの完全なリストについては、『OCIプログラマーズ・ガイド』を参照してください。