Про роботу з українськими літерами в InterBase

Не лякайтеся обсягу цього тексту! Насправді тут перераховані абсолютно всі теми, що стосуються "русифікації" Borland InterBase та Firebird. Вам можуть знадобитися деякі, але спочатку прочитайте весь документ, а потім використовуйте потрібне.

Версія IB 5 і 6 хоч і вільна від цієї помилки, в деяких випадках при операції відновлення бази даних спостерігається помилка "text subtype52 не located" (або схожа).

Далі практично все, що буде викладено, можна прочитати як у IB32.HLP, так і в документації Borland InterBase Language Reference, розділ Character sets and collation orders (і не тільки там).

Створення бази даних

Тепер, коли ви перевстановили Borland InterBase, настав час створення бази даних. Отримати можливість роботи з українськими літерами у базі даних можна двома способами: звичайним та не використовуючи кодування.

Звичайний спосіб: Працюючи на будь-якій платформі, ви повинні при створенні БД вказати додатковий параметр DEFAULT CHARACTER SET WIN1251. Якщо ви створюєте БД в WISQL, то цю фразу вписуєте в memo-поле Database Options, а якщо те саме робите в командному рядку ISQL - використовуйте повний синтаксис CREATE DATABASE "C:/MYDIR/MYDATABASE.GDB" USER "SYSDBA" PASSWORD "masterkey" DEFAULT CHARACTER SET WIN1251; Для BDE слід використовувати налаштування, зазначені в розділі "Робота через BDE", який можна прочитати нижче.

Примітка: еквівалентом character set WIN1251 є кодування CYRL, однак використовувати його не рекомендується, т.к. вона не підтримує UPPER.

Не використовуючи кодування: створюючи БД НЕ вказувати DEFAULT CHARATER SET для бази даних ні для символьних полів. У цьому випадку в BDE повинен бути вказаний параметрLANGDRIVER: на сторінці SYSTEM - ascii ansi, DRIVERS - пусто, ALIAS - пусто. В цьому випадку в БД можна записувати символи в будь-якому кодуванні.

Спосіб з відмовою від кодувань більш простий, дозволяє працювати з різними наборами символів в одному коннекті (наприклад, для web), але не може забезпечувати правильне сортування різних наборів символів - перед використанням такого підходу потрібно все ретельно перевірити. Наприклад, не буде працювати функція UPPER та collation orders - натомість доведеться використовувати функції з модуля CASEUDF.

Вся решта цього документа стосується лише офіційного способу роботи з українськими літерами в IB

! Не варто намагатися називати таблиці, поля чи будь-які інші об'єкти БД українськими літерами. Це не відповідає стандарту, так само як і при іменуванні типів або змінних в мовах програмування Pascal або C. Загалом це стосується і Interbase 6/Firebird, де в діалекті 3 можна вказувати імена об'єктів, укладені в подвійних лапках.

Якщо ви створили таблицю, і хочете додати туди кілька записів прямо з WISQL, варто від'єднатися від БД і приєднатися знову попередньо встановивши в "WISQL/Session/Advanced Settings/Character set on" цей WIN1251.

Робота через BDE

! У списку кодувань Borland InterBase є ще одне українськомовне – CYRL (866). Проте вже давно Borland не випускає жодних засобів роботи з IB з DOS, тому працюючи в Windows використовувати кодування 866 ​​було б дивно.

Робота через інші компоненти та API

Тут неважливо, який саме набір компонентів використовується - IBObjects, FreeIBComponents, FIBPlus або IBX. Потрібно у параметрах компонента, що відповідає за з'єднання (XXDatabase), вписати рядок

Якщо ж йдеться про інструментидля роботи з IB, що працюють без BDE, вони повинні підтримувати вказівку потрібного кодування ДО коннекта до бази даних. Наприклад, IBConsole придбала таку можливість починаючи з 319 версії.

Скрипти та ISQL

Власне, все те саме. Тобто. кодування символів потрібно вказати перед коннектом або створенням бази даних. Буквально – на початку скрипту написати:

Ця команда видається інтерактивно перед коннектом до БД через утиліту командного рядка ISQL.

Uppercase українських букв

CREATE TABLE TESTCHAR( ID INTEGER NOT NULL PRIMARY KEY, NAME1 CHAR(30), NAME2 CHAR(30) COLLATE PXW_CYRL )

І занесемо до цієї таблиці (хоча б за допомогою SQL Explorer) такі дані:

1АА
2ББ
3УУ
4аа
5бб
6вв
Тепер, виконайте три запити, і подивіться в якому порядку повертатимуться записи

1) SELECT * FROM TESTCHAR ORDER BY NAME1 2) SELECT * FROM TESTCHAR ORDER BY NAME2 3) SELECT * FROM TESTCHAR ORDER BY NAME1 COLLATE PXW_CYRL

Зверніть увагу, що другий та третій запити призвели до однакового порядку записів у результаті. Справді, в будь-якому місці та в будь-якій ситуації можна додати специфікатор COLLATE PXW_CYRL, якщо при створенні таблиці рядкового поля цей специфікатор не вказано.

Наприклад, якщо потрібно зробити пошук за uppercase-значенням, навіть коли поле було створено без collate - SELECT * FROM TESTCHAR WHERE UPPER(NAME1 COLLATE PXW_CYRL) = 'А'

Природно, що для поля NAME2 така конструкція не знадобиться, і нормально відпрацює запит SELECT *FROM TESTCHAR WHERE UPPER(NAME2) = 'А'

Примітка: якщо у вас є індекс NAME2, то використання будь-якої функції (UPPER, або підключених UDF) призведе до того, що оптимізатор не зможе використовувати індекс для прискорення запиту. У цьому випадку запит SELECT * FROM TESTCHAR WHERE NAME2 = 'А' буде оптимізований (пошук за індексом), а запит SELECT * FROM TESTCHAR WHERE UPPER (NAME2) = 'А' призведе до перебору всіх записів таблиці. Якщо у вас багато записів у подібній таблиці, і лише одна умова WHERE, що містить UPPER, то ви можете додати до таблиці додаткове поле з DEFAULT UPPER(SOURCEFIELD). В цьому випадку нові значення додаються тільки в SOURCEFIELD, а пошук ведеться по полю, що містить готовий UPPER.

Примітка : вказівка ​​COLLATE PXW_CYRL призводить до того, що IB вважає такі поля, що зберігають символи в 3-байтовому кодуванні, і не дозволяє створити індекс такого поля якщо його довжина перевищує 84 (252/3=84) символу. У такому випадку краще відмовитися від стандартного UPPER і використовувати власні UDF для перекладу регістру літер. Приклад функцій UpCase та LoCase з вихідним текстом на Delphi та готовою DLL можна взяти тут – caseudf.zip (10K). Загалом вказувати COLLATE PXW_CYRL чи ні, ви повинні вирішити для себе самостійно. В основному вибір визначається необхідністю специфічного сортування великих та малих українських літер, яке забезпечує COLLATE PXW_CYRL (див. вище запити з order by).

Як змінити COLLATE на працюючій базі даних

Примітка: ви повинні пам'ятати, що у найпростішому випадку таке завдання вирішується написанням SELECT * FROM MYTABLE WHERE UPPER(MYFIELD COLLATE PXW_CYRL) = 'ВАСЯ'

Це ж стосується і ORDER BY COLLATE PXW_CYRL. Таким чином, все викладене нижче варто використовувати тільки ву крайньому випадку, коли жодні інші стандартні методи не працюють.

Для цього вам потрібно буде відредагувати системну таблицю RDB $ RELATION_FIELDS. Перші два шпальти цієї таблиці - RDB$FIELD_NAME і RDB$RELATTION_NAME, тобто. ім'я поля та ім'я таблиці відповідно. Знайдіть запис, у якого ці поля мають потрібне вам значення - наприклад MYFIELD та MYTABLE.

Останній стовпець таблиці RDB$RELATION_FIELDS називається RDB$COLLATION_ID. У ньому записано 0, якщо поле має лише CHARACTER SET WIN1251, і 1 - якщо поле було створено з CHARACTER SET WIN1251 COLLATE PXW_CYRL.

Тому просто поміняйте 0 на 1, але там, де RDB$COLLATION_ID не має значення "порожньо".

Тепер щоб існуючі в таблиці записи отримали новий COLLATE, потрібно зробити

UPDATE MYTABLE SET MYFIELD=MYFIELD

інакше UPPER буде працювати тільки для нових записів, але не для старих - це викликано тим, що InterBase зберігає інформацію про типи полів в blob таблиці RDB $ FORMATS, що дозволяє змінювати тип поля, довжину, і наприклад COLLATE прямо "на ходу".

Ну і щоб перевірити, чи правильно працює UPPER, можна видати запит

SELECT UPPER(MYFIELD) FROM MYTABLE

Якщо ви хочете змінити "одним махом" COLLATE у всіх полів вашої БД, то можете виконати запит

UPDATE RDB$RELATION_FIELDS SET RDB$COLLATION_ > WHERE (RDB$FIELD_NAME NOT CONTAINING '$') AND (RDB$SYSTEM_FLAG = 0) AND (RDB$COLLATION_ >

Потім, природно, update доведеться виконати для кожної таблиці, де ви хочете для рядкових полів працювати з UPPER. Якщо по зміненим рядковим полям є індекси, потрібно ці індекси видалити і перестворити, т.к. order by використовуватиме сортування значення ключа, а чи не значення поля у таблиці.

Примітка: зміна системних таблиць є нормальною операцією, якщо ви точно знаєте, що хочете зробити, і ознайомилися з розділом System Tables у книзі InterBase Language Reference. InterBase може змінювати структуру таблиць, типів полів тощо. операції, однак для них немає відповідних команд SQL - вони просто не визначені у стандарті.

ODBC-драйвер

Робота з українськими літерами через ODBC-драйвер із версій IB 4.2, 5.0 та 5.1.1 буде проблемною. Цей драйвер НЕ дозволяє встановити кодування символів, що приймаються та передаються. Якщо на читання ODBC-драйвер працює (і автономно і через BDE) нормально, то на запис - доводиться формувати запит вручну і додавати специфічну вказівку набору символів, що використовується. Наприклад, для тієї ж таблиці TESTCHAR, вставку записів доведеться писати за допомогою UpdateSQL: INSERT INTO TESTCHAR VALUES (:ID, _win1251 :NAME1, _win1251 :NAME2)

Нагадаю, що драйвер версії 3.0, що постачається з IB 5.5/5.6, коректно працює з українськими літерами та кодуванням БД WIN1251.

українські літери в процедурах, що зберігаються, тригерах і exceptions

Через помилку в GBAK (аж до IB 6.0 включно) не рекомендується використовувати як список допустимих значень для рядкових полів українські літери при описі структури таблиці (default value list). Краще перенести цю частину тригер, якщо така перевірка дійсно необхідна на сервері. Якщо все-таки це сталося, відновити базу даних вдасться тільки при встановленому параметрі GBAK Do not restore validity conditions (або БД не відновиться, див Verbose Output).

У Firebird версії 0.9.5.156 і вище цей баг усунений, проте, щоб він не виникав, потрібно створення бази даних саме в цій версії.Backup/Restore для виправлення бага недостатньо.

Ще один варіант вирішення проблеми з українськими default – це створення їх у наступній формі:

create table bug_bugbase ( s varchar(20) character set win1251 collate win1251 default _win1251 'XXXX' not null);

Це дасть вказівку однозначно ідентифікувати character set для символів, що вказуються у default.