1 に答える
これは、VARCHAR2 の代わりに CLOB を使用しない限り、おそらく回避できるものではありません。
Oracle では、列を宣言すると、デフォルトでバイト長セマンティクスが使用されます。たとえば、VARCHAR2(100) は 100 バイトのストレージを割り当てます。ISO 8859-1 のようなシングルバイト文字セットを使用している場合、すべての文字に 1 バイトのストレージが必要であるため、100 文字分のスペースも割り当てられます。ただし、UFT-8 などのマルチバイト文字セットを使用している場合、各文字には 1 ~ 4 バイトのストレージが必要になる場合があります。したがって、データによっては、VARCHAR2(100) は 25 文字のデータしか格納できない場合があります (通常、英語の文字には 1 バイト、ヨーロッパの文字には通常 2 バイト、アジアの文字には通常 3 バイトが必要です)。
ISO-8859-1 データベースから UTF-8 データベースに移行するときに通常私が提案する文字長セマンティクスを使用するように Oracle に指示できます。列 VARCHAR2(100 CHAR) を宣言すると、最終的に 100 バイトになるか 400 バイトになるかに関係なく、Oracle は 100 文字にスペースを割り当てます。また、NLS_LENGTH_SEMANTICS パラメータを CHAR に設定してデフォルトを変更し (新しい DDL の場合)、VARCHAR2(100) が 100 バイトではなく 100 文字のストレージを割り当てるようにすることもできます。
残念ながら、Oracle VARCHAR2 のサイズの制限 (PL/SQL エンジンではなく SQL エンジンのコンテキストで) は 4000 バイトです。したがって、列 VARCHAR2(4000 CHAR) を宣言したとしても、実際に挿入できるデータは 4000 バイトに制限されますが、これはわずか 1000 文字である可能性があります。たとえば、AL32UTF8 文字セットを使用するデータベースでは、列 VARCHAR2(4000 CHAR) を宣言できますが、2 バイトのストレージを必要とする文字を挿入すると、実際には 4000 文字のデータを挿入できないことがわかります。
SQL> create table foo (
2 col1 varchar2(4000 char)
3 );
Table created.
SQL> insert into foo values( rpad( 'abcde', 4000, unistr('\00f6') ) );
1 row created.
SQL> ed
Wrote file afiedt.buf
1* insert into foo values( rpad( 'abcde', 6000, unistr('\00f6') ) )
SQL> /
1 row created.
SQL> select length(col1), lengthb(col1)
2 from foo;
LENGTH(COL1) LENGTHB(COL1)
------------ -------------
2003 4000
2003 4000
4000 文字の UTF-8 データを格納する必要がある場合は、CLOB への移動が必要になる 16000 バイトを処理できるデータ型が必要です。