Това вероятно не е нещо, което можете да заобиколите, освен ако не искате да използвате CLOB вместо VARCHAR2.
В Oracle, когато декларирате колона, по подразбиране се използва семантика с дължина на байта. Така VARCHAR2(100), например, разпределя 100 байта за съхранение. Ако използвате еднобайтов набор от знаци като ISO 8859-1, всеки знак изисква 1 байт място за съхранение, така че това също отделя място за 100 знака. Но ако използвате многобайтов набор от знаци като UFT-8, всеки знак може да изисква между 1 и 4 байта място за съхранение. Следователно в зависимост от данните VARCHAR2(100) може да съхрани само 25 знака данни (английските знаци обикновено изискват 1 байт, европейските знаци обикновено изискват 2 байта, а азиатските знаци обикновено изискват 3 байта).
Можете да кажете на Oracle да използва семантика на дължината на знаците, което обикновено е това, което бих предложил при преминаване от база данни ISO-8859-1 към база данни UTF-8. Ако декларирате колона VARCHAR2(100 CHAR), Oracle ще разпредели място за 100 знака, независимо дали това ще бъде 100 байта или 400 байта. Можете също да зададете параметъра NLS_LENGTH_SEMANTICS на CHAR, за да промените стойността по подразбиране (за нов DDL), така че VARCHAR2(100) да разпределя 100 знака за съхранение вместо 100 байта.
За ваше съжаление обаче ограничението за размера на Oracle VARCHAR2 (в контекста на SQL машината, а не на PL/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 данни, ще ви трябва тип данни, който може да обработва 16000 байта, което ще наложи преместване в CLOB.