この章では、LONG
データ型を使用する表からLOBデータ型へと移行する手法について説明します。この章の内容は次のとおりです。
関連項目: 各種のプログラミング環境におけるLOBデータ型のサポートの詳細は、次の各章を参照してください。 |
表列をLONG
データ型からLOBデータ型に移行すると、次のようなメリットがあります。
注意: この章で説明する手法を使用すると、次のいずれの変換も可能になります。
特に明記しないかぎり、この章のLONGからLOBへの変換に関する説明は、これら2つのデータ型変換に適用されます。 |
様々なアプリケーション開発の使用例におけるLONG
データ型とLOBデータ型のセマンティクスには、次のような違いがあります。
LONG
型の列の数には制限があります。特定の表に含めることができるLONG
型の列は1つのみです。表に含めるLOB型の列の数には制限がありません。
LOB用のデータ・インタフェースを使用すると、LONG
またはLONG
RAW
列を含む表をレプリケートできます。LOB列ではレプリケートが許可されますが、LONG
列とLONG
RAW
列ではサポートされません。データベースでは、LONG
データ型とLONG
RAW
データ型を含む列はレプリケートされた表から省略されます。
表がレプリケートされている場合、または表にマテリアライズド・ビューがある場合にLONG
列をLOBに変更するときは、手動でレプリカを修正する必要があります。
注意:
|
この項では、LONG
列をLOB列に変換する前に満たす必要のある事前条件について説明します。
LONG
列のドメイン索引は、LONG
列をLOB列に変換する前に削除する必要があります。詳細は、「LONGデータ型からLOBデータ型に変換された列の索引」を参照してください。
LONG
列の変換処理中にREDO領域が生成されると、パフォーマンスが低下することがあります。変換処理中の表に対するREDOがログに記録されるのは、表にLOGGING
が指定されている場合のみです。
また、LONG
からLOBへ変換中の列に対するREDOがログに記録されるのは、LOB列の記憶特性がLOGGING
に指定されている場合のみです。LOB列のロギング設定(LOGGING
またはNOLOGGING
)は、LOBが作成された表領域から継承されます。
移行中のREDO領域の生成を回避するには、表を移行する前に次の手順に従います(構文はBNFです)。
次の文を実行します。ALTER TABLE Long_tab NOLOGGING;
次の文を実行します。ALTER TABLE Long_tab MODIFY (long_col CLOB [DEFAULT <
default_val
>]) LOB (long_col) STORE AS (NOCACHE NOLOGGING);
STORE AS
句にNOLOGGING
を指定する場合は、NOCACHE
も指定する必要があることに注意してください。
次の文を実行します。ALTER TABLE Long_tab MODIFY LOB (long_col) (CACHE);
次の文を実行します。ALTER TABLE Long_tab LOGGING;
表およびLOB列を含む表領域のバックアップを作成します。
rdbms/admin/utldtree.sql
ユーティリティを使用すると、表をLONG型からLOB型の列に移行する場合に、アプリケーションで変更が必要な部分を判断できます。このユーティリティを使用すると、指定のオブジェクトに依存するすべてのオブジェクトを再帰的に参照できます。たとえば、LONG
列を含む表に依存するオブジェクトをすべて参照できます。参照できるのは、権限があるオブジェクトのみです。
utldtree.sql
の使用方法は、utldtree.sqlファイル内に記載されています。また、utldtree.sql
が必要となるのはPL/SQLの場合のみです。SQLおよびOCIの場合は、アプリケーションを変更する必要はありません。
この項では、既存の表をLONG
データ型からLOBデータ型へ移行する方法を説明します。この項の内容は次のとおりです。
LONG列を含む表のオンライン再定義(高可用性が重要な場合)
Oracle Data Pumpを使用したデータベースの移行(このユーティリティを使用して変換が可能な場合)
SQLのALTER
TABLE
文を使用すると、LONG
列からLOB列に変換できます。そのためには、次の構文を使用します。
ALTER TABLE [<schema>.]<table_name> MODIFY ( <long_column_name> { CLOB | BLOB | NCLOB } [DEFAULT <default_value>]) [LOB_storage_clause];
たとえば、次のように作成された表があるとします。
CREATE TABLE Long_tab (id NUMBER, long_col LONG);
この例では、次のALTER
TABLE
文を使用して、Long_tab
表のlong_col
列をCLOB
データ型に変更できます。
ALTER TABLE Long_tab MODIFY ( long_col CLOB );
注意: ALTER TABLE 文は、表の内容を新しい領域にコピーし、操作の終了時に古い領域を解放します。このため、必要な領域が一時的に2倍になります。 |
ALTER
TABLE
文を使用してLONG
列をLOB列に変換する場合、次のオプションのみが許可されていることに注意してください。
DEFAULT
: LOB列のデフォルト値を指定できます。
LOB_storage_clause
: 変換する列のLOB記憶特性を指定できます。このオプションはMODIFY
句に指定できます。
LONG
列をLOB型の列に変換する場合、ALTER
TABLE
文の他のオプションは使用できません。
移行については、次の一般的な問題があります。
以前のLONG
列に対するすべての制約は、新しいLOB列においても保持されます。LONG
列で有効な制約は、NULL
およびNOT
NULL
のみです。これらの列に対する制約、またはこの表の他の列やプロパティを変更するには、移行後にALTER
TABLE
文を使用します。
デフォルト値を指定しない場合、LONG
列のデフォルト値がLOB列のデフォルト値となります。
表に対するほとんどの既存のトリガーは引き続き使用できますが、UPDATE OF
トリガーで問題が発生する可能性があります。詳細は、「LONGからLOBへのアプリケーションの移行」を参照してください。
前述のようにALTER
TABLE
を使用しない場合は、LONG
列に対してTO_LOB
演算子を使用し、LONG列をLOB列にコピーできます。CREATE
TABLE
AS
SELECT
文またはINSERT
AS
SELECT
文でTO_LOB
演算子を使用すると、LONG
列からCLOB
列またはNCLOB
列に、またはLONG
RAW
列からBLOB
列にデータをコピーできます。たとえば、LONG
列を含む表が次のように作成されているとします。
CREATE TABLE Long_tab (id NUMBER, long_col LONG);
次の文を使用すると、列をLOB列にコピーできます。
CREATE TABLE Lob_tab (id NUMBER, clob_col CLOB); INSERT INTO Lob_tab SELECT id, TO_LOB(long_col) FROM long_tab; COMMIT;
INSERT
がエラーを戻す場合は(UNDO用の領域がなかった場合)、WHERE
句を使用してLONG
データを少しずつLOB列に移行できます。データが正確にコピーされていることを確認した後、元の表を削除し、次のどちらかの手順を使用して新しい表のビューまたはシノニムを作成できます。
DROP TABLE Long_tab; CREATE VIEW Long_tab (id, long_col) AS SELECT * from Lob_tab;
または
DROP TABLE Long_tab; CREATE SYNONYM Long_tab FOR Lob_tab;
この一連の操作は、Long_tab
表のLong_col
列のデータ型をLONG
からCLOB
に変更する操作と同じです。この方法を使用する場合は、新しい表の制約、トリガー、権限付与および索引を再作成する必要があります。
TO_LOB
演算子の使用には、次のような制限事項があることに注意してください。
TO_LOB
を使用してデータをLOB列にコピーできますが、オブジェクト型のLOB属性にはコピーできません。
TO_LOB
はリモート表に使用できません。たとえば、次の文は機能しません。
INSERT INTO tb1@dblink (lob_col) SELECT TO_LOB(long_col) FROM tb2; INSERT INTO tb1 (lob_col) SELECT TO_LOB(long_col) FROM tb2@dblink; CREATE TABLE tb1 AS SELECT TO_LOB(long_col) FROM tb2@dblink;
索引構成表の作成時に、CREATE
TABLE
AS
SELECT
文でTO_LOB
演算子を使用して、LONG
またはLONG
RAW
列をLOB列に変換することはできません。
この制限事項を回避するには、索引構成表を作成してから、TO_LOB
演算子を使用してLONG
列またはLONG
RAW
列のINSERT
AS
SELECT
を実行します。
どのPL/SQLブロックの中でもTO_LOB
を使用できません。
LONG
列およびLONG
RAW
列を含む表は、表のオンライン再定義を使用して移行できます。この方法は、高可用性が重要なデータベース表のLONG列を移行する場合に適しています。
この方法を使用するには、次のように、再定義処理中にLONG
列をLOB型に変換する必要があります。
LONG
列をCLOB
列またはNCLOB
列に変換します。
LONG
RAW
列をBLOB
列に変換します。
この変換を実行するには、DBMS_REDEFINITION.START_REDEF_TABLE()
プロシージャの列マッピングにTO_LOB()
演算子を使用します。
注意: LONG 列またはLONG RAW 列を含む表のオンライン再定義を実行するには、この項で説明するように各列をLOB型に変換する必要があります。 |
次のリストに、オンライン再定義処理に関係する一般タスクを示します。LONG
列とLONG
RAW
列の変換に固有の問題については、該当する箇所で説明します。ここで説明しないオンライン再定義処理の詳細は、この項の最後に示す関連マニュアルを参照してください。
空の仮表を作成します。再定義処理が完了すると、この表には移行済のデータが保持されます。この仮表で次の操作を行います。
移行元の表にあるLONG
列ごとにCLOB
列またはNCLOB
列を定義します。
移行元の表にあるLONG
RAW
列ごとにBLOB
列を定義します。
再定義処理を開始します。そのためには、次のように、DBMS_REDEFINITION.START_REDEF_TABLE
をコールし、TO_LOB
演算子を使用して列マッピングを渡します。
DBMS_REDEFINITION.START_REDEF_TABLE( 'schema_name', 'original_table', 'interim_table', 'TO_LOB(long_col_name
)lob_col_name
', 'options_flag', 'orderby_cols');
long_col_name
は元の表で変換するLONG
列またはLONG
RAW
列の名前で、lob_col_name
は仮表のLOB列の名前です。このLOB列に変換後のデータが保持されます。
DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS
プロシージャをコールします。詳細は、関連マニュアルを参照してください。
DBMS_REDEFINITION.FINISH_REDEF_TABLE
プロシージャをコールします。詳細は、関連マニュアルを参照してください。
パラレル実行に十分なリソースがあるシステムでは、LONG
列のLOB列への再定義は、次の条件下でパラレルに実行できます。
挿入先の表がパーティション化されていない場合:
挿入先の表にLOB列を格納するために使用されるセグメントが、自動セグメント領域管理(ASSM)が使用可能になっている(現在のデフォルト)ローカル管理表領域に属している。
1つのLONG
列から1つのLOB列への単純なマッピングが存在し、挿入先の表には1つのLOB列のみがある。
挿入先の表がパーティション化されている場合、パーティション化に通常使用されるパラレル実行方法が適用されます。挿入先の表がパーティション化されている場合、オンライン再定義がパラレルに実行されます。
オンライン再定義の例
次の例に、LOB列を使用したオンライン再定義を示します。
REM Grant privileges required for online redefinition.
GRANT execute ON DBMS_REDEFINITION TO pm;
GRANT ALTER ANY TABLE TO pm;
GRANT DROP ANY TABLE TO pm;
GRANT LOCK ANY TABLE TO pm;
GRANT CREATE ANY TABLE TO pm;
GRANT SELECT ANY TABLE TO pm;
REM Privileges required to perform cloning of dependent objects.
GRANT CREATE ANY TRIGGER TO pm;
GRANT CREATE ANY INDEX TO pm;
connect pm/passwd
drop table cust;
create table cust(c_id number primary key,
c_zip number,
c_name varchar(30) default null,
c_long long
);
insert into cust values(1, 94065, 'hhh', 'ttt');
-- Creating Interim Table
-- There is no requirement to specify constraints because they are
-- copied over from the original table.
create table cust_int(c_id number not null,
c_zip number,
c_name varchar(30) default null,
c_long clob
);
declare
col_mapping varchar2(1000);
BEGIN
-- map all the columns in the interim table to the original table
col_mapping :=
'c_id c_id , '||
'c_zip c_zip , '||
'c_name c_name, '||
'to_lob(c_long) c_long';
dbms_redefinition.start_redef_table('pm', 'cust', 'cust_int', col_mapping);
END;
/
declare
error_count pls_integer := 0;
BEGIN
dbms_redefinition.copy_table_dependents('pm', 'cust', 'cust_int',
1, true, true, true, false,
error_count);
dbms_output.put_line('errors := ' || to_char(error_count));
END;
/
exec dbms_redefinition.finish_redef_table('pm', 'cust', 'cust_int');
-- Drop the interim table
drop table cust_int;
desc cust;
-- The following insert statement fails. This illustrates
-- that the primary key constraint on the c_id column is
-- preserved after migration.
insert into cust values(1, 94065, 'hhh', 'ttt');
select * from cust;
関連項目: この項で前述した再定義処理の詳細は、次の関連マニュアルを参照してください。
|
この項では、アプリケーションの移行計画に影響したり、アプリケーションの変更を必要とする、LONG
データ型とLOBデータ型の違いについて説明します。
PL/SQL環境とOCI環境でLONGデータ型に使用するほとんどのAPIは、LOBデータ型にも使用できるように拡張されています。これらのAPIをまとめて、永続LOB用のデータ・インタフェースまたは単にデータ・インタフェースと呼びます。データ・インタフェースには、特に次のようなメリットがあります。
LONG
データ型からLOBデータ型に変換された列を含む表を使用するPL/SQLおよびOCIアプリケーションでは、アプリケーションの変更が最小限ですみます。
LOBロケータを扱わずにアプリケーションでLOBデータ型を使用できます。
関連項目:
|
AFTER UPDATE
OF
トリガーのUPDATE
OF
リストには、LOB列を作成できません。LONG
列は、この種のトリガーに作成できます。たとえば、次のCREATE TRIGGER文は無効です。
CREATE TABLE t(lobcol CLOB); CREATE TRIGGER trig AFTER UPDATE OF lobcol ON t ...;
他のすべてのトリガーはLOB列で機能します。
移行する表の列の索引は、LONG
列をLOB列に変換した後に手動で再作成する必要があります。これには、ファンクション索引が含まれます。
LONG
列のファンクション索引は、変換処理中は使用できなくなり、変換後に再作成する必要があります。ファンクション索引を使用するアプリケーション・コードは、変換後もそのまま動作します。
LONG
列のドメイン索引は、LONG
列をLOB列に変換する前に削除する必要があることに注意してください。変換後にドメイン索引を再作成できます。
変換後に索引を再作成する手順は、次のとおりです。
次のように、元の表から索引を選択します。
SELECT index_name FROM user_indexes WHERE table_name='LONG_TAB';
注意: この問合せでは、表名を大文字で指定する必要があります。 |
選択した索引に対して次のコマンドを使用します。
ALTER INDEX <index> REBUILD
LOB列には、空のLOBを保持できます。空のLOBとは、完全に初期化済でデータが移入されていないLOBロケータです。LONG
データ型ではロケータが使用されないため、LONG
データ型には「空」という概念が適用されません。
LOB列値とLONG
列値はどちらも、初期値としてNULL
または空の文字列リテラルが挿入された場合は、NULL
値を持ちます。そのため、LONG
列にNULL
または長さ0(ゼロ)の値を使用するアプリケーション・コードは、列をLOB型に変換した後も同様に動作します。
対照的に、空として初期化されたLOBは、次の例に示すようにNULL
以外の値を持ちます。
CREATE TABLE long_tab(id NUMBER, long_col LONG); CREATE TABLE lob_tab(id NUMBER, lob_col CLOB); INSERT INTO long_tab values(1, NULL); REM A zero length string inserts a NULL into the LONG column: INSERT INTO long_tab values(1, ''); INSERT INTO lob_tab values(1, NULL); REM A zero length string inserts a NULL into the LOB column: INSERT INTO lob_tab values(1, ''); REM Inserting an empty LOB inserts a non-NULL value: INSERT INTO lob_tab values(1, empty_clob()); DROP TABLE long_tab; DROP TABLE lob_tab;
アンカー型を使用したアプリケーションでは、LOBへの変換中に、オーバーロードされた変数が別のターゲットに解決される場合があります。たとえば、p
プロシージャが指定1および2でオーバーロードされるとします。
procedure p(l long) is ...; -- (specification 1) procedure p(c clob) is ...; -- (specification 2)
また、次のプロシージャ・コールが使用されるとします。
declare var longtab.longcol%type; BEGIN ... p(var); ... END;
LONG
列からLOB列に移行する前に、このコールにより指定1に解決されます。longtab
がLOB列に移行すると、このコールは指定2に解決されます。これは、指定1のパラメータの型がCHAR
、VARCHAR2
、RAW
、LONG
RAW
の場合も同じであることに注意してください。
表をLONG
列からLOB列に移行した後、アプリケーションを手動で検査し、オーバーロードされたプロシージャの変更が必要かどうかを判断する必要があります。
移行前にLOB引数を取るオーバーロードされたプロシージャが含まれていたアプリケーションは、正常に動作しなくなる場合があります。これには、LONG
のアンカー型を使用しないアプリケーションも含まれます。たとえば、p
プロシージャに対する次の指定(1および2)とプロシージャ・コールを考えてみます。
procedure p(n number) is ...; -- (1) procedure p(c clob) is ...; -- (2) p('123'); -- procedure call
移行前には、CHAR
からNUMBER
への変換のみが可能であったため、指定1が選択されていました。移行後では、両方の変換が可能なため、コールの解釈が不明確になり、オーバーロード・エラーが発生します。
PL/SQLでは、NUMBER
、DATE
、ROW_ID
、BINARY_INTEGER
およびPLS_INTEGER
データ型からLONG
への暗黙的な変換が許可されますが、これらのデータ型からLOBへの暗黙的な変換は許可されません。
アプリケーションでこの種の暗黙的な変換を使用する場合、文字データにはTO_CHAR
演算子、バイナリ・データにはTO_RAW
演算子を使用して、これらの型を明示的に変換する必要があります。たとえば、アプリケーションに次のような割当て操作があるとします。
number_var := long_var; -- The RHS is a LOB variable after converting.
この場合は、コードを次のように変更する必要があります。
number_var := TO_CHAR(long_var); -- Assuming that long_var is of type CLOB after conversion
LOB型の場合、次の変換はサポートされません。
BLOB
からVARCHAR2
、CHAR
またはLONG
CLOB
からRAW
またはLONG
RAW
これは、暗黙的な変換が発生する操作すべてに適用されます。たとえば、アプリケーションに次のようなSELECT
文があるとします。
SELECT long_raw_column INTO my_varchar2 VARIABLE FROM my_table
この場合、表の変換後にlong_raw_column
がBLOB
になると、SELECT
文でエラーが生成されます。この変換を機能させるには、次のように、TO_RAW
演算子を使用してBLOB
をRAW
に明示的に変換する必要があります。
SELECT TO_RAW(long_raw_column) INTO my_varchar2 VARIABLE FROM my_table
CLOB
をRAW
変数に選択する場合、CLOB
をRAW
に割り当てる場合、およびBLOB
をVARCHAR2
に割り当てる場合も同様です。