5 分散LOB
5.1 リモートLOBの操作
リモート表の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>親トピック: リモートLOB列の操作
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;
親トピック: リモートLOB列の操作
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';
親トピック: リモートLOB列の操作
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;
親トピック: リモート表のLOBでのSQLセマンティクス
5.2.2 組込みSQLファンクションへのリモート・ロケータの受け渡し
LENGTH、INSTR、SUBSTR、UPPERなど)にリモート・ロケータを渡すことができます。たとえば、Var lob1 CLOB;
BEGIN
select c2 into lob1 from lob_tab@db2 where c1=1;
END;
/
select length(:lob1) from dual;親トピック: リモート表のLOBでのSQLセマンティクス
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;親トピック: PL/SQLでのリモートLOBの操作
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_LOBAPIの完全なリストについては、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。
親トピック: DBMS_LOBでのリモート・ロケータの使用
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プログラマーズ・ガイド』を参照してください。
親トピック: 分散LOB