Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Semantyka CHAR i ORA-01461

To prawdopodobnie nie jest coś, co można obejść, chyba że chcesz użyć CLOB zamiast VARCHAR2.

W Oracle, kiedy deklarujesz kolumnę, domyślnie używana jest semantyka długości bajtów. Na przykład VARCHAR2(100) przydziela 100 bajtów pamięci. Jeśli używasz zestawu znaków jednobajtowych, takiego jak ISO 8859-1, każdy znak wymaga 1 bajtu pamięci, więc przydzielane jest również miejsce na 100 znaków. Ale jeśli używasz wielobajtowego zestawu znaków, takiego jak UFT-8, każdy znak może wymagać od 1 do 4 bajtów pamięci. Dlatego w zależności od danych VARCHAR2(100) może przechowywać tylko 25 znaków danych (znaki angielskie zazwyczaj wymagają 1 bajtu, znaki europejskie zazwyczaj wymagają 2 bajtów, a znaki azjatyckie zazwyczaj wymagają 3 bajtów).

Możesz powiedzieć Oracle, aby używało semantyki długości znaków, co zwykle sugerowałbym przy przechodzeniu z bazy danych ISO-8859-1 do bazy danych UTF-8. Jeśli zadeklarujesz kolumnę VARCHAR2 (100 CHAR), Oracle przydzieli miejsce na 100 znaków, niezależnie od tego, czy ostatecznie będzie to 100 bajtów, czy 400 bajtów. Możesz również ustawić parametr NLS_LENGTH_SEMANTICS na CHAR, aby zmienić wartość domyślną (dla nowego DDL), tak aby VARCHAR2(100) przydzielał 100 znaków pamięci zamiast 100 bajtów.

Niestety dla Ciebie limit rozmiaru Oracle VARCHAR2 (w kontekście silnika SQL, a nie silnika PL/SQL) wynosi 4000 bajtów. Więc nawet jeśli zadeklarujesz kolumnę VARCHAR2 (4000 CHAR), nadal będziesz ograniczony do faktycznego wstawiania 4000 bajtów danych, które mogą mieć tylko 1000 znaków. Na przykład w bazie danych używającej zestawu znaków AL32UTF8 mogę zadeklarować kolumnę VARCHAR2 (4000 CHAR), ale wstawienie znaku, który wymaga 2 bajtów pamięci, pokazuje, że tak naprawdę nie mogę wstawić 4000 znaków danych

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

Jeśli potrzebujesz przechowywać 4000 znaków danych UTF-8, potrzebujesz typu danych, który mógłby obsłużyć 16000 bajtów, co wymagałoby przeniesienia do CLOB.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Dopasowanie Oracle SQL Regexp_replace

  2. Policz liczbę elementów w ciągu oddzielonym przecinkami w Oracle

  3. Expdp ze środowiska Oracle RAC

  4. plsql pobierz tabelę w wyzwalaczu „przed zmianą”

  5. SQL nie wyświetla wartości null w zapytaniu nie równa się?