Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Semântica CHAR e ORA-01461


Isso provavelmente não é algo que você possa contornar, a menos que queira usar um CLOB em vez de um VARCHAR2.

No Oracle, quando você declara uma coluna, o padrão é usar a semântica de comprimento de byte. Assim, um VARCHAR2(100), por exemplo, aloca 100 bytes de armazenamento. Se você estiver usando um conjunto de caracteres de byte único como ISO 8859-1, cada caractere requer 1 byte de armazenamento, portanto, isso também aloca espaço para 100 caracteres. Mas se você estiver usando um conjunto de caracteres de vários bytes como o UFT-8, cada caractere pode exigir entre 1 e 4 bytes de armazenamento. Dependendo dos dados, portanto, um VARCHAR2(100) pode armazenar apenas 25 caracteres de dados (caracteres ingleses geralmente requerem 1 byte, caracteres europeus geralmente requerem 2 bytes e caracteres asiáticos geralmente requerem 3 bytes).

Você pode dizer ao Oracle para usar semântica de comprimento de caractere, que normalmente é o que eu sugiro ao passar de um banco de dados ISO-8859-1 para um banco de dados UTF-8. Se você declarar uma coluna VARCHAR2(100 CHAR), o Oracle alocará espaço para 100 caracteres, independentemente de ser 100 bytes ou 400 bytes. Você também pode definir o parâmetro NLS_LENGTH_SEMANTICS como CHAR para alterar o padrão (para o novo DDL) para que um VARCHAR2(100) aloque 100 caracteres de armazenamento em vez de 100 bytes.

Infelizmente para você, porém, o limite de tamanho de um Oracle VARCHAR2 (no contexto do mecanismo SQL em vez do mecanismo PL/SQL) é de 4.000 bytes. Portanto, mesmo que você declare uma coluna VARCHAR2(4000 CHAR), você ainda estará limitado a inserir 4.000 bytes de dados, que podem ter apenas 1.000 caracteres. Por exemplo, em um banco de dados usando o conjunto de caracteres AL32UTF8, posso declarar uma coluna VARCHAR2(4000 CHAR), mas inserir um caractere que requer 2 bytes de armazenamento mostra que não consigo inserir 4000 caracteres de dados
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 você precisar armazenar 4.000 caracteres de dados UTF-8, precisará de um tipo de dados que possa lidar com 16.000 bytes, o que exigiria a mudança para um CLOB.