Oracle
 sql >> Base de données >  >> RDS >> Oracle

Sémantique CHAR et ORA-01461

Ce n'est probablement pas quelque chose que vous pouvez contourner à moins que vous ne vouliez utiliser un CLOB au lieu d'un VARCHAR2.

Dans Oracle, lorsque vous déclarez une colonne, la valeur par défaut consiste à utiliser une sémantique de longueur en octets. Ainsi, un VARCHAR2(100), par exemple, alloue 100 octets de stockage. Si vous utilisez un jeu de caractères à un octet comme ISO 8859-1, chaque caractère nécessite 1 octet de stockage, ce qui alloue également de l'espace pour 100 caractères. Mais si vous utilisez un jeu de caractères multi-octets comme UFT-8, chaque caractère peut nécessiter entre 1 et 4 octets de stockage. Selon les données, par conséquent, un VARCHAR2(100) peut ne pouvoir stocker que 25 caractères de données (les caractères anglais nécessitent généralement 1 octet, les caractères européens nécessitent généralement 2 octets et les caractères asiatiques nécessitent généralement 3 octets).

Vous pouvez dire à Oracle d'utiliser la sémantique de longueur de caractère, ce que je suggérerais normalement lors du passage d'une base de données ISO-8859-1 à une base de données UTF-8. Si vous déclarez une colonne VARCHAR2(100 CHAR), Oracle allouera de l'espace pour 100 caractères, que ce soit 100 octets ou 400 octets. Vous pouvez également définir le paramètre NLS_LENGTH_SEMANTICS sur CHAR pour modifier la valeur par défaut (pour le nouveau DDL) afin qu'un VARCHAR2(100) alloue 100 caractères de stockage au lieu de 100 octets.

Malheureusement pour vous, la limite de taille d'un Oracle VARCHAR2 (dans le contexte du moteur SQL plutôt que du moteur PL/SQL) est de 4 000 octets. Ainsi, même si vous déclarez une colonne VARCHAR2(4000 CHAR), vous serez toujours limité à l'insertion de 4000 octets de données qui peuvent être aussi peu que 1000 caractères. Par exemple, dans une base de données utilisant le jeu de caractères AL32UTF8, je peux déclarer une colonne VARCHAR2(4000 CHAR) mais l'insertion d'un caractère qui nécessite 2 octets de stockage montre que je ne peux pas vraiment insérer 4000 caractères de données

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

Si vous avez besoin de stocker 4 000 caractères de données UTF-8, vous aurez besoin d'un type de données pouvant gérer 16 000 octets, ce qui nécessiterait de passer à un CLOB.