Вставка данных unicode в базу данных Oracle с помощью Doctrine2 и Symfony2


Я пишу приложение, используя Symfony2 и Doctrine2, где мне нужно использовать Oracle в качестве моей базы данных (с которой я незнаком, я почти всегда использую MySQL). Я установил Oracle XE на свой dev box и создал пользователя.

Мои параметры подключения выглядят следующим образом в конфигурации Symfony2:

database_driver: oci8
database_host: localhost
database_name: xe
database_user: myusername
database_password: mypassword
database_port: 1521
database_charset: AL32UTF8

При запуске php app/console doctrine:schema:create на CLI схема создается успешно, но при попытке загрузить мои начальные светильники с php app/console doctrine:fixtures:load, я получаю следующую ошибку:

[DoctrineDBALDBALException]
An exception occurred while executing 'INSERT INTO my_currency 
(id, code, name, symbol) VALUES (?, ?, ?, ?)' with params 
{"1":3,"2":"RUB","3":"Russian Ruble","4":"u0440u0443u0431."}:

ORA-12899: value too large for column "MYUSERNAME"."MY_CURRENCY"."SYMBOL" 
(actual: 7, maximum: 4)

Мой скрипт fixtures содержит следующие данные для вставки этой строки:

array('RUB', 'Russian Ruble', 'руб.'),

Сущность определяется как:

FooMyBundleEntityCurrency:
  type: entity
  table: my_currency
  id:
    id:
      type: integer
      generator: { strategy: AUTO }
  fields:
    code:
      type: string
      length: 3
    name:
      type: string
      length: 64
    symbol:
      type: string
      length: 4

Насколько я понимаю, Oracle XE имеет набор символов по умолчанию UTF-8, поэтому типы полей не должны быть установлены в NVARCHAR2 (они установлены в VARCHAR2, автоматически по Доктрине).

Есть ли у кого-нибудь идеи относительно того, где я ошибаюсь?
2 2

2 ответа:

Ваша проблема не исходит из PHP: ваш столбец "MY_CURRENCY"."SYMBOL", вероятно, определяется как VARCHAR2(4 byte) вместо VARCHAR2(4 CHAR).

Поскольку символ Юникода может занимать более одного байта, вы должны использовать CHAR при определении переменных таблици . Вот почему вы получаете ошибку Оракула.

Вы должны иметь возможность изменять свою таблицу:

ALTER TABLE MY_CURRENCY MODIFY (SYMBOL VARCHAR2(4 CHAR));

И затем вставьте любые 4 символа в этот столбец.

Во-первых, какую версию Oracle XE вы используете и какой набор символов вы используете? Если вы используете 10G версию Oracle XE, была возможность загрузить версию, которая использовала западноевропейский набор символов в дополнение к версии, которая использовала набор символов Unicode. Что возвращают эти запросы?

SELECT *
  FROM v$version

SELECT *
  FROM v$nls_parameters
 WHERE parameter LIKE '%CHARACTERSET';

Предполагая, что база данных использует набор символов Unicode, по умолчанию Oracle определяет длину столбца VARCHAR2 (или столбца NVARCHAR2) в байтах, не персонажи. Если у вас есть данные, которые находятся за пределами набора символов US7ASCII, набор символов AL32UTF8 требует более 1 байта памяти. Похоже, что данные, которые вы пытаетесь вставить в столбец SYMBOL, требуют 7 байт памяти, хотя они могут содержать только 4 символа.

Есть два общих подхода к решению этой проблемы. Первый-утроить размер выделяемых столбцов (обычно требуется один символ в наборе символов AL32UTF8 не более трех байт, хотя в некоторых исключительных случаях требуется четыре байта). Вместо указания длины в 4 байта, вы бы указали длину в 12 байт (CODE станет 9 байт, а NAME станет 192 байта). Второй-изменить NLS_LENGTH_SEMANTICS так, чтобы столбец VARCHAR2 выделял размер в символах, а не в байтах
ALTER SYSTEM SET nls_length_semantics = CHAR scope= BOTH

Как только вы это сделаете (вам нужно будет войти в систему как SYS, чтобы иметь возможность изменять параметры инициализации), все сценарии, созданные вашей платформой, будут использовать символ семантика по умолчанию.