简体   繁体   中英

Inserting unicode data into Oracle Database with Doctrine2 and Symfony2

I'm writing an application using Symfony2 and Doctrine2 where I need to use Oracle as my database (of which I am unfamiliar with, I almost always use MySQL). I have installed Oracle XE on my dev box and created a user.

My connection parameters look like this in my Symfony2 config:

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

When running php app/console doctrine:schema:create on the CLI, the schema is created successfully, but when trying to load my initial fixtures with php app/console doctrine:fixtures:load , I'm getting the following error:

[Doctrine\DBAL\DBALException]
An exception occurred while executing 'INSERT INTO my_currency 
(id, code, name, symbol) VALUES (?, ?, ?, ?)' with params 
{"1":3,"2":"RUB","3":"Russian Ruble","4":"\u0440\u0443\u0431."}:

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

My fixtures script has the following data in it for inserting this row:

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

The entity is defined as:

Foo\MyBundle\Entity\Currency:
  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

From what I understand, Oracle XE has a default character set of UTF-8, so the field types shouldn't need to be set to NVARCHAR2 (they're set to VARCHAR2, automatically by Doctrine).

Does anyone have any ideas as to where I'm going wrong?

Your problem doesn't come from PHP: your "MY_CURRENCY"."SYMBOL" column is probably defined as VARCHAR2(4 byte) instead of VARCHAR2(4 CHAR) .

Since an unicode character may take more than one byte, you have to use CHAR when you define your tables and variables. This is why you are getting an Oracle error.

You should be able to modify your table:

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

And then insert any 4 characters into this column.

First off, what version of Oracle XE are you using and what character set are you using? If you are using the 10g version of Oracle XE, there was an option to download a version that used a Western European character set in addition to a version that used a Unicode character set. What do these queries return?

SELECT *
  FROM v$version

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

Assuming that the database is using a Unicode character set, by default, Oracle specifies the length of a VARCHAR2 column (or a NVARCHAR2 column) in terms of bytes, not characters. If you have data that is outside of the US7ASCII character set, the AL32UTF8 character set requires more than 1 byte of storage. It appears that the data that you are trying to insert into the SYMBOL column requires 7 bytes of storage though it may comprise only 4 characters.

There are two general approaches to dealing with this. The first is to triple the size of the columns that you allocate (a single character in the AL32UTF8 character set normally requires no more than three bytes though some exceptional cases require four bytes). Rather than specifying a length of 4 bytes, you would specify a length of 12 bytes ( CODE would become 9 bytes and NAME becomes 192 bytes). The second is to change the NLS_LENGTH_SEMANTICS so that a VARCHAR2 column allocates a size in characters rather than bytes

ALTER SYSTEM SET nls_length_semantics = CHAR scope= BOTH

Once you do that (you'll need to log in as SYS to be able to change initialization parameters), any scripts generated by your framework will use character semantics by default.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM