10.3 リモート・ロケータの操作
永続LOBロケータをリモート表からローカル変数に選択できます。これは、PL/SQL、JDBCまたは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;
- リモート表での問合せとDMLを使用したバインドとしてのローカル・ロケータおよびリモート・ロケータの使用
この項では、問合せおよびDML文のバインド値について説明します。 - リモート・ロケータの使用
この項では、PL/SQLおよびOCILOB APIでのリモート・ロケータの使用例を示します。 - OCILOB APIでのリモート・ロケータの使用
ほとんどのOCILOB
APIでは、リモートLOB
ロケータでの操作がサポートされます。次のOCILOB
関数のリストは、リモートLOB
ロケータが渡されるとエラーを返します。 - リモートLOBロケータ使用時の制限
リモートLOBロケータには、次の制限事項があります。
関連項目:
親トピック: 分散LOB
10.3.1 リモート表での問合せとDMLを使用したバインドとしてのローカル・ロケータおよびリモート・ロケータの使用
この項では、問合せおよびDML文のバインド値について説明します。
バインド値でクエリおよびDML (INSERT
、UPDATE
、DELETE
)を使用する場合は、次の4つのケースが考えられます。最初のケースにはローカルの表およびロケータが含まれ、標準の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);
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;
ノート:
returning
句を含むDMLは、スカラーおよびLOB両方の列についてリモート表でサポートされません。
親トピック: リモート・ロケータの操作
10.3.2 リモート・ロケータの使用
この項では、PL/SQLおよびOCILOB APIでのリモート・ロケータの使用例を示します。
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;
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;
/
ほとんどのOCILOB
APIでは、リモートLOB
ロケータに対する操作がサポートされています。次のOCILOB
関数のリストは、リモートLOB
ロケータが渡されるとエラーを返します。
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プログラマーズ・ガイド』を参照してください。
親トピック: リモート・ロケータの操作
10.3.3 OCILOB APIでのリモート・ロケータの使用
ほとんどのOCILOB
APIでは、リモートLOB
ロケータに対する操作がサポートされています。次のOCILOB
関数のリストは、リモートLOB
ロケータが渡されるとエラーを返します。
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プログラマーズ・ガイド』を参照してください。
親トピック: リモート・ロケータの操作
10.3.4 リモート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など)のロケータと別のデータベース(DB2など)のロケータをバインド変数として使用することはできません。 -
収集した表またはロケータでは同じデータベース・リンクが使用されます。同じデータベースをポイントする2つの異なるDBリンクを使用できます。次の例では、
dblink1
とdblink2
の両方が同じリモート・データベースを指していますが、認証方法が異なります。Oracle Databaseはこのような操作をサポートしません。INSERT into tab1@dblink1 SELECT * from tab2@dblink2;
- 2つのロケータを受け入れる
DBMS_LOB
またはOCILob
APIでは、同じデータベース・リンクを介して両方のLOBロケータを取得する必要があります。次の例で指定されている操作はサポートされません。SELECT ad_sourcetext INTO clob1 FROM print_media@db1 WHERE product_id = 10011; SELECT ad_sourcetext INTO clob2 FROM print_media@db2 WHERE product_id = 10011; DBMS_LOB.COPY(clob1, clob2, length(clob2));
-
バインド値は列のLOB型と同じLOB型であることが必要です。たとえば、
NCLOB
ロケータをNCLOB
列にバインドし、CLOB
ロケータをCLOB
列にバインドする必要があります。NCLOB
型とCLOB
型間の暗黙の変換はリモートLOBではサポートされません。 -
配列バインドを使用するDML文は、バインド操作にリモート・ロケータが含まれる場合、または関連する表がリモート表の場合はサポートされません。
-
ローカル変数にリモート表からの
BFILE
列は選択できません。
親トピック: リモート・ロケータの操作