简体   繁体   English

使用Doctrine2和Symfony2将unicode数据插入Oracle数据库

[英]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). 我正在使用Symfony2和Doctrine2编写一个应用程序,其中我需要使用Oracle作为数据库(我不熟悉它们,我几乎总是使用MySQL)。 I have installed Oracle XE on my dev box and created a user. 我已经在我的开发箱上安装了Oracle XE并创建了一个用户。

My connection parameters look like this in my Symfony2 config: 我的连接参数在我的Symfony2配置中如下所示:

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: 在CLI上运行php app/console doctrine:schema:create时,架构已成功创建,但是当尝试使用php app/console doctrine:fixtures:load加载初始固定装置时,出现以下错误:

[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). 据我了解,Oracle XE具有默认字符集UTF-8,因此字段类型不必设置为NVARCHAR2(Doctrine自动将其设置为VARCHAR2)。

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) . 您的问题不是来自PHP:您的"MY_CURRENCY"."SYMBOL"列可能定义为VARCHAR2(4 byte)而不是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. 由于Unicode字符可能占用多个字节,因此在定义表变量时必须使用CHAR This is why you are getting an Oracle error. 这就是为什么您会收到Oracle错误。

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. 然后将任何4个字符插入此列。

First off, what version of Oracle XE are you using and what character set are you using? 首先,您正在使用哪个版本的Oracle XE和您使用什么字符集? 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. 如果您使用的是Oracle XE的10g版本,除了使用Unicode字符集的版本外,还可以选择下载使用西欧字符集的版本。 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. 假定默认情况下数据库使用的是Unicode字符集,则Oracle以字节而不是字符的形式指定VARCHAR2列(或NVARCHAR2列)的长度。 If you have data that is outside of the US7ASCII character set, the AL32UTF8 character set requires more than 1 byte of storage. 如果您的数据不在US7ASCII字符集中,则AL32UTF8字符集需要1个以上的字节存储空间。 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. 您试图插入到SYMBOL列中的数据似乎需要7个字节的存储空间,尽管它可能仅包含4个字符。

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). 第一种是将分配的列的大小增加三倍(AL32UTF8字符集中的单个字符通常不超过三个字节,尽管在某些特殊情况下需要四个字节)。 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). 而不是指定4个字节的长度,而是指定12个字节的长度( CODE将变为9个字节,而NAME将变为192个字节)。 The second is to change the NLS_LENGTH_SEMANTICS so that a VARCHAR2 column allocates a size in characters rather than bytes 第二个是更改NLS_LENGTH_SEMANTICS以便VARCHAR2列以字符而不是字节分配大小

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. 完成此操作后(您将需要以SYS身份登录才能更改初始化参数),默认情况下,框架生成的所有脚本都将使用字符语义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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