Вставка данных 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 ответа:
Ваша проблема не исходит из 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 определяет длину столбца
Есть два общих подхода к решению этой проблемы. Первый-утроить размер выделяемых столбцов (обычно требуется один символ в наборе символов AL32UTF8 не более трех байт, хотя в некоторых исключительных случаях требуется четыре байта). Вместо указания длины в 4 байта, вы бы указали длину в 12 байт (VARCHAR2
(или столбцаNVARCHAR2
) в байтах, не персонажи. Если у вас есть данные, которые находятся за пределами набора символов US7ASCII, набор символов AL32UTF8 требует более 1 байта памяти. Похоже, что данные, которые вы пытаетесь вставить в столбецSYMBOL
, требуют 7 байт памяти, хотя они могут содержать только 4 символа.CODE
станет 9 байт, аNAME
станет 192 байта). Второй-изменитьNLS_LENGTH_SEMANTICS
так, чтобы столбецVARCHAR2
выделял размер в символах, а не в байтахALTER SYSTEM SET nls_length_semantics = CHAR scope= BOTH
Как только вы это сделаете (вам нужно будет войти в систему как SYS, чтобы иметь возможность изменять параметры инициализации), все сценарии, созданные вашей платформой, будут использовать символ семантика по умолчанию.