sql >> Database >  >> RDS >> Oracle

CHAR-semantiek en ORA-01461

Dit is waarschijnlijk niet iets waar je omheen kunt, tenzij je een CLOB wilt gebruiken in plaats van een VARCHAR2.

Wanneer u in Oracle een kolom declareert, wordt standaard de bytelengte-semantiek gebruikt. Dus een VARCHAR2(100) wijst bijvoorbeeld 100 bytes aan opslagruimte toe. Als u een tekenset van één byte gebruikt, zoals ISO 8859-1, heeft elk teken 1 byte opslagruimte nodig, dus dit wijst ook ruimte toe voor 100 tekens. Maar als u een multi-byte tekenset zoals UFT-8 gebruikt, kan voor elk teken tussen de 1 en 4 bytes aan opslagruimte nodig zijn. Afhankelijk van de gegevens kan een VARCHAR2(100) daarom slechts 25 tekens aan gegevens opslaan (Engelse tekens vereisen over het algemeen 1 byte, Europese tekens vereisen over het algemeen 2 bytes en Aziatische tekens vereisen over het algemeen 3 bytes).

Je kunt Oracle vertellen om semantiek van tekenlengte te gebruiken, wat ik normaal gesproken zou aanraden bij het overstappen van een ISO-8859-1-database naar een UTF-8-database. Als u een kolom VARCHAR2(100 CHAR) declareert, wijst Oracle ruimte toe voor 100 tekens, ongeacht of dat 100 bytes of 400 bytes wordt. U kunt ook de parameter NLS_LENGTH_SEMANTICS instellen op CHAR om de standaardwaarde (voor nieuwe DDL) te wijzigen, zodat een VARCHAR2(100) 100 tekens aan opslagruimte toewijst in plaats van 100 bytes.

Helaas voor u is de limiet voor de grootte van een Oracle VARCHAR2 (in de context van de SQL-engine in plaats van de PL/SQL-engine) 4000 bytes. Dus zelfs als u een kolom VARCHAR2(4000 CHAR) declareert, bent u nog steeds beperkt tot het daadwerkelijk invoegen van 4000 bytes aan gegevens die slechts 1000 tekens lang kunnen zijn. In een database die de AL32UTF8-tekenset gebruikt, kan ik bijvoorbeeld een kolom VARCHAR2 (4000 CHAR) declareren, maar als ik een teken invoeg dat 2 bytes opslagruimte vereist, blijkt dat ik niet echt 4000 tekens aan gegevens kan invoegen

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

Als u 4000 tekens aan UTF-8-gegevens wilt opslaan, heeft u een gegevenstype nodig dat 16000 bytes aankan, waardoor u naar een CLOB moet verhuizen.




  1. MySQL-tijdzones

  2. Wat is MariaDB? Hoe werkt MariaDB?

  3. pg_dump met gebruiker dont superadmin en grote objecten

  4. Bewaar array in database of maak andere kolommen