воскресенье, 5 декабря 2010 г.

Customizing Locale Data NLS_SORT=UKRUMIX

    Недавно получилась забавная ситуация: во время сортировки буква Э оказалась между К и М вместо того чтобы быть на своем месте: перед Ю и Я. Оказалось ничего удивительного, на клиентских машинах локализация Windows установлена как UKRAINIAN и при инсталляции Oracle Client для программ которые работают с базой данных Oracle устанавливается украинская локализация(в реестре прописывается ключ NLS_LANG = UKRAINIAN_UKRAINE.CL8MSWIN1251), в которой буквы Э не существует, вот она и всплывает не на своем месте. Пока что данные в базе на русском и поэтому надо будет букву Э поставить на свое место в украинской локализации.

    Разработчики разными способами выходят из этой ситуации и самый первый способ к которому они прибегают - это решить проблему при помощи SQL. Но в Oracle существует более элегантный способ - настроить локализацию на сервере баз данных при помощи утилиты : Locale Builder.

    Назовем нашу локализацию UKRUMIX - добавим в украинский букву Э, а также мне не понравилась наша буква Ґ, американцы кажется не ту букву приняли за используемую у нас в Украине.

  1. Запуск утилиты Locale Builder:
    Start > Programs > Oracle-OraHome10 > Configuration and Migration Tools > Locale Builder
    или
    $oracle_home/nls/lbuilder/lbuilder.bat
  2. Переходим на Creating a New Linguistic Sort with the Oracle Locale Builder
    Нам новой сортировки не надо, мы скопируем существующую Linguistic Sort=UKRAINIAN,
    добавим в нужную позицию необходимые нам буквы, сохраним в новый файл в директорию D:\Temp, имя файла предложит утилита сама

    File->Open...->By Object Name...


    Выбираем Linguistic Sort(ID): UKRAINIAN(46)


    Откроется закладка General


    Заменим Collation Name: UKRAINIAN -> UKRUMIX
    Так как мы редактируем Monolingual Linguistic Sort, то возьмем ID из диапазона 1001
    (The valid range for Collation ID (sort ID) for a user-defined sort is 1000 to 2000 for monolingual collation and 10000 to 11000 for multilingual collation.)


    Переходим на закладку Major/Minor, сортируем по полю Major Sort,
    становимся на запись с Major Sort = 147, Unicode Value = 0x0403


    • Нажимаем New и указываем следующий значения:
      • Unicode Value = 0x0490
      • Major Sort = 147
      • Minor Sort = 3


    • Add
    • Нажимаем New и указываем следующий значения:
      • Unicode Value = 0x0491
      • Major Sort = 147
      • Minor Sort = 4


    • Add
    • Нажимаем New и указываем следующий значения:
      • Unicode Value = 0x042d
      • Major Sort = 227
      • Minor Sort = 1
    • Add
    • Нажимаем New и указываем следующий значения:
      • Unicode Value = 0x044d
      • Major Sort = 227
      • Minor Sort = 2
    • Add
    • Сохраним NLT файл в D:\temp Сохранять под именем, предложенным самой утилитой(под другим именем не даст сохранить) File -> Save As...
  3. Generating and Installing NLB Files
    1. As the user who owns the files (typically user oracle), back up the NLS installation boot file (lx0boot.nlb) and the NLS system boot file (lx1boot.nlb) in the ORA_NLS10 directory. On a UNIX platform, enter commands similar to the following example:
      % setenv ORA_NLS10 $ORACLE_HOME/nls/data
      % cd $ORA_NLS10
      % cp -p lx0boot.nlb lx0boot.nlb.orig
      % cp -p lx1boot.nlb lx1boot.nlb.orig
      
      
      Note that the -p option preserves the timestamp of the original file.
    2. In Oracle Locale Builder, choose Tools > Generate NLB or click the Generate NLB icon in the left side bar.
    3. Click Browse to find the directory where the NLT file is located
    4. Click OK to generate the NLB files.
    5. Copy the lx1boot.nlb file into the path:
      copy D:\temp\lx1boot.nlb $ORACLE_HOME/nls/data
      
    6. Copy the new NLB files into the $ORACLE_HOME/nls/data directory.
      copy D:\temp\lx303e9.nlb $ORACLE_HOME\nls\data
      
    7. Restart the database to use the newly created locale data.
      cmd> lsnrctl stop
      
      cmd> sqlplus / as sysdba
      sql> shutdown immediate
      sql> startup
      sql> exit
      
      
      
  4. Тестируем:
    select * from (
      select 'Э'/*unistr('\042d')*/ name from dual
      union all
      select 'э'/*unistr('\044d')*/ name from dual
      union all
      select 'ґ'/*unistr('\0491')*/ name from dual
      union all
      select 'Ґ'/*unistr('\0490')*/ name from dual
      union all
      select 'Ю'/*unistr('\xxxx')*/ name from dual
      union all
      select 'Я'/*unistr('\xxxx')*/ name from dual
      union all
      select 'В'/*unistr('\xxxx')*/ name from dual
      union all
      select 'Д'/*unistr('\xxxx')*/ name from dual
    )
    order by NLSSORT(name, 'NLS_SORT = UKRUMIX');
    /
    
    NA
    -- 
    В
    Ґ
    ґ
    Д
    Э
    э
    Ю
    Я
    
    8 rows selected.