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

php app/console doctrine:schema:createCLI で実行すると、スキーマは正常に作成されますが、最初のフィクスチャを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に設定する必要はありません(Doctrineによって自動的にVARCHAR2に設定されます)。

私がどこで間違っているのか、誰かが何か考えを持っていますか?

4

2 に答える 2

3

問題は PHP に起因するものではありません。列はおそらくではなく"MY_CURRENCY"."SYMBOL"として定義されています。VARCHAR2(4 byte)VARCHAR2(4 CHAR)

Unicode 文字は 1 バイト以上かかる場合があるため、テーブル変数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列 (または列) の長さを指定します。NVARCHAR2US7ASCII 文字セット外のデータがある場合、AL32UTF8 文字セットには 1 バイトを超えるストレージが必要です。列に挿入しようとしているデータには、SYMBOL4 文字しかない場合でも 7 バイトのストレージが必要なようです。

これに対処するには、2 つの一般的なアプローチがあります。1 つ目は、割り当てる列のサイズを 3 倍にすることです (AL32UTF8 文字セットの 1 文字は、通常 3 バイト以下で済みますが、一部の例外的なケースでは 4 バイトが必要です)。4 バイトの長さを指定するのではなく、12 バイトの長さを指定します ( CODE9 バイトにNAMEなり、192 バイトになります)。2 つ目は、列がバイト数ではなく文字数でサイズを割り当てるように を変更するNLS_LENGTH_SEMANTICSことです。VARCHAR2

ALTER SYSTEM SET nls_length_semantics = CHAR scope= BOTH

これを行うと (初期化パラメーターを変更するには、SYS としてログインする必要があります)、フレームワークによって生成されたスクリプトは、デフォルトで文字セマンティクスを使用します。

于 2012-11-13T11:22:16.170 に答える