sql >> Databasteknik >  >> RDS >> Oracle

CHAR semantik och ORA-01461

Detta är förmodligen inget du kan komma runt om du inte vill använda en CLOB istället för en VARCHAR2.

I Oracle, när du deklarerar en kolumn, är standard att använda byte-längds semantik. Så en VARCHAR2(100), till exempel, allokerar 100 byte lagring. Om du använder en enkelbyte-teckenuppsättning som ISO 8859-1, kräver varje tecken 1 byte lagringsutrymme, så detta allokerar också utrymme för 100 tecken. Men om du använder en multi-byte teckenuppsättning som UFT-8, kan varje tecken kräva mellan 1 och 4 byte lagring. Beroende på data kan därför en VARCHAR2(100) endast lagra 25 tecken med data (engelska tecken kräver vanligtvis 1 byte, europeiska tecken kräver vanligtvis 2 byte och asiatiska tecken kräver vanligtvis 3 byte).

Du kan säga till Oracle att använda teckenlängdssemantik, vilket vanligtvis är vad jag skulle föreslå när du flyttar från en ISO-8859-1-databas till en UTF-8-databas. Om du deklarerar en kolumn VARCHAR2(100 CHAR) kommer Oracle att allokera utrymme för 100 tecken oavsett om det blir 100 byte eller 400 byte. Du kan också ställa in parametern NLS_LENGTH_SEMANTICS till CHAR för att ändra standardinställningen (för ny DDL) så att en VARCHAR2(100) allokerar 100 tecken lagring istället för 100 byte.

Tyvärr för dig är gränsen för storleken på en Oracle VARCHAR2 (i sammanhanget av SQL-motorn snarare än PL/SQL-motorn) 4000 byte. Så även om du deklarerar en kolumn VARCHAR2(4000 CHAR), kommer du fortfarande att vara begränsad till att faktiskt infoga 4000 byte med data som kan vara så få som 1000 tecken. Till exempel, i en databas som använder teckenuppsättningen AL32UTF8, kan jag deklarera en kolumn VARCHAR2(4000 CHAR), men att infoga ett tecken som kräver 2 byte lagring visar att jag inte riktigt kan infoga 4000 tecken med data

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

Om du behöver lagra 4 000 tecken UTF-8-data, skulle du behöva en datatyp som kan hantera 16 000 byte, vilket skulle göra det nödvändigt att flytta till en CLOB.




  1. MAMP Pro mysql kan inte starta

  2. Skillnader mellan INDEX, PRIMÄR, UNIK, FULLTEXT i MySQL?

  3. MySQL - Hitta rader som matchar alla rader från den sammanfogade tabellen

  4. Möjligt sätt att infoga lastInsertId från en tabell till en annan samtidigt eller samtidigt