2

我正在使用 Symfony2 和 Doctrine2 编写一个应用程序,我需要使用 Oracle 作为我的数据库(我不熟悉,我几乎总是使用 MySQL)。我已经在我的开发盒上安装了 Oracle XE 并创建了一个用户。

我的 Symfony2 配置中的连接参数如下所示:

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

在 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)

我的夹具脚本中包含以下数据,用于插入此行:

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

实体定义为:

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

据我了解,Oracle XE 有一个默认的 UTF-8 字符集,因此字段类型不需要设置为 NVARCHAR2(它们被设置为 VARCHAR2,由 Doctrine 自动设置)。

有人对我哪里出错有任何想法吗?

4

2 回答 2

3

您的问题不是来自 PHP:您的"MY_CURRENCY"."SYMBOL"列可能被定义为VARCHAR2(4 byte)而不是VARCHAR2(4 CHAR).

由于 unicode 字符可能占用超过一个字节,因此您必须CHAR在定义表变量时使用。这就是您收到 Oracle 错误的原因。

您应该能够修改您的表格:

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

然后在此列中插入任意 4 个字符。

于 2012-11-13T11:18:50.377 回答
2

首先,您使用的是什么版本的 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 身份登录才能更改初始化参数),你的框架生成的任何脚本都将默认使用字符语义。

于 2012-11-13T11:22:16.170 回答