Oracle
 sql >> Database >  >> RDS >> Oracle

Semantica CHAR e ORA-01461

Questo probabilmente non è qualcosa che puoi aggirare a meno che tu non voglia usare un CLOB invece di un VARCHAR2.

In Oracle, quando si dichiara una colonna, l'impostazione predefinita prevede l'utilizzo della semantica della lunghezza dei byte. Quindi un VARCHAR2(100), ad esempio, alloca 100 byte di memoria. Se stai utilizzando un set di caratteri a byte singolo come ISO 8859-1, ogni carattere richiede 1 byte di memoria, quindi questo alloca anche spazio per 100 caratteri. Ma se stai usando un set di caratteri multibyte come UFT-8, ogni carattere può richiedere da 1 a 4 byte di memoria. A seconda dei dati, quindi, un VARCHAR2(100) potrebbe essere in grado di memorizzare solo 25 caratteri di dati (i caratteri inglesi generalmente richiedono 1 byte, i caratteri europei generalmente richiedono 2 byte e i caratteri asiatici generalmente richiedono 3 byte).

Puoi dire a Oracle di utilizzare la semantica della lunghezza dei caratteri che è normalmente ciò che consiglierei quando si passa da un database ISO-8859-1 a un database UTF-8. Se dichiari una colonna VARCHAR2(100 CHAR), Oracle allocherà spazio per 100 caratteri indipendentemente dal fatto che finisca per essere 100 byte o 400 byte. Puoi anche impostare il parametro NLS_LENGTH_SEMANTICS su CHAR per modificare l'impostazione predefinita (per il nuovo DDL) in modo che un VARCHAR2(100) allochi 100 caratteri di memoria anziché 100 byte.

Sfortunatamente per te, tuttavia, il limite alla dimensione di un Oracle VARCHAR2 (nel contesto del motore SQL anziché del motore PL/SQL) è di 4000 byte. Quindi, anche se dichiari una colonna VARCHAR2(4000 CHAR), sarai comunque limitato all'inserimento effettivo di 4000 byte di dati che possono contenere fino a 1000 caratteri. Ad esempio, in un database che utilizza il set di caratteri AL32UTF8, posso dichiarare una colonna VARCHAR2(4000 CHAR) ma l'inserimento di un carattere che richiede 2 byte di memoria mostra che non posso davvero inserire 4000 caratteri di dati

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

Se devi archiviare 4000 caratteri di dati UTF-8, avresti bisogno di un tipo di dati in grado di gestire 16000 byte, il che richiederebbe il passaggio a un CLOB.