Исправлена ​​максимальная длина, разрешенная для символа в символе Oracle 4000 - PullRequest
0 голосов
/ 27 августа 2018

В настоящее время я использую Oracle 11g. Согласно моему требованию, мне нужно сохранить первые 4000 (максимальный лимит) символов в моей переменной (используется в триггерах).

Для этого я использую функцию VarName = SUBSTR (VarName, 1, 4000), но похоже, что она ничего не хранит (я передаю '111 ...' (4096 символов для хранения), из которых я хочу хранить ('111 ...') только первые 4000 символов).

Он работал для 4 символов, но не работал для максимальных ограничений. Я пробовал с длиной 3999, 3000, но у меня ничего не получалось.

Пожалуйста, посмотрите на это и предложите мне какое-нибудь решение для этого.

(* Примечание: я не могу изменить тип переменной с varchar на clob, так как в этом столбце уже есть миллионы устаревших данных.)

* Модификация: Я пробовал с длиной Substr 2048 , она работает , но как только я предоставляю 2049 символов для substr, она снова становится нулевой . Но в значение поля типа данных определяется как VARCHAR2 (4000 CHAR) .

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

Если я прав, вам лучше перейти на оракул 12. Позвольте мне объяснить:

Oracle (до версии 11 включительно) имеет предел HARD 4000 BYTES для столбцов char / varchar, и этот предел не может быть преодолен путем простого объявления столбца как "varchar2 (4000) CHAR) ".

если в вашей базе данных используется многобайтовый набор символов, этот предел все еще остается в силе, поэтому вы сможете хранить 4000 символов только при соблюдении этих двух условий:

  1. в вашей кодировке есть символы, которые занимают только один байт
  2. строка, которую вы хотите сохранить, состоит только из символов, закодированных в один байт

    Например: если ваш набор символов в базе данных - UTF8, символ «А» занимает один байт, но символу «а» требуется два байта:

                |  Bytes required       |Bytes required       |   Bytes required  
      string    |  if database charset  |if database charset  |  if database charset       
                |  is  ASCII            |is  UTF8             |   is  UTF16
      --------- |-------------------------------------------------------------------
       "A"      |  1 byte               |   1 bytes           |   2 bytes 
       "à"      |  1 byte               |   2 bytes           |   2 bytes 
       "àA"     |  2 byte               |   3 bytes           |   4 bytes       
    

поэтому в столбце VARCHAR2 (4000 CHAR) в базе данных UTF8 вы сможете хранить строку, состоящую из 4000 символов «A», но если вы используете 4000 символов «à», она будет ограничена 2000 символами : в UTF8 любой символ, чей код unicode number> = 128 (то есть: это не ASCII-символ), занимает несколько байтов. в UTF16 любой символ съедает как минимум 2 байта.

Глядя на описываемые вами симптомы (и на ваше имя), я думаю, что вы не используете однобайтовый набор символов ... и я также думаю, что большинству используемых символов требуется как минимум два байта, так вот причина фактического ограничения в 2000 символов: вы сталкиваетесь с жестким ограничением в 4000 байтов.

Я думаю, что единственное «простое» решение для вас - это обновить базу данных до оракула 12, где этот жесткий предел может быть увеличен до 32000 байт (AFAIK, он не делает это «из коробки»: вам нужно соответственно настроить его при создании базы данных).

если вы создадите базу данных oracle 12 с повышенным пределом, ваши столбцы varchar2 (4000 CHAR) больше не будут соответствовать жесткому пределу.

Помните также, что когда вы обычно объявляете столбец как VARCHAR2 (4000), oracle по умолчанию интерпретирует его как VARCHAR2 (4000 BYTE). это значение по умолчанию можно изменить, выполнив в течение сеанса следующее:

 alter session set NLS_LENGTH_SEMANTICS='CHAR'

его TEORICALLY можно установить на уровне экземпляра для всей базы данных и всего сеанса, , но оракул предупреждает вас НЕ делать этого, потому что система будет некорректно работать , поэтому придерживайтесь его использования на уровне сеанса.

Надеюсь, это поможет.


P.S. Может быть, вы найдете полезную подсказку:

В моей базе данных я написал триггер "после входа в систему", который выполняется автоматически, который изменяет сеанс только для пользователя (ей) моего приложения

CREATE OR REPLACE TRIGGER TRG_MYAPP_AFTER_LOGON
AFTER LOGON on database
declare
    function IsMyAppUser return boolean is
    cnt number;
    begin
       -- if the user is the owner of the schema, all its commands are expected
       -- to use the "char" length semantics 
       if user = 'MYAPP' then
          return true;
       end if;
       --- this is specific to my app: I have a table that lists the login names
       --- of the users who have been created only with the purpose of using the app
       select count(*) into cnt  
       from my_app_users u 
       where u.usr_login=user 
         and ROWNUM=1;
       return cnt>0;
    end;
BEGIN
   if IsMyAppUser then
       execute immediate 'alter session set nls_length_semantics = ''CHAR''';
   end if;
END TRG_QBF_AFTER_LOGON;
0 голосов
/ 28 августа 2018

RPAD или LPAD:

Я мог бы получить ячейку 4000 символов, как это:

select rpad('x',3999, '-'),  v.* 
  from v$version v 
 where rownum=1

Придает

|x------[3999 times] | Oracle Database 11g Release 11.2.0.4.0 - 64bit dev|
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...