1

ODBCで準備およびバインドされた次のステートメントを使用します。

SELECT (CASE profile WHEN ? THEN 1 ELSE 2 END) AS profile_order 
FROM engine_properties;

AL32UTF8文字セットのOracle10gデータベースへのODBC3.0接続で実行すると、を使用してwchar_t文字列にバインドした後でもSQLBindParameter(SQL_C_WCHAR)、エラーORA-12704:文字セットの不一致が発生します。

なんで?私はwcharとしてバインドしています。wcharはNCHARと見なされるべきではありませんか?

パラメータを変更してラップするとTO_NCHAR()、クエリはエラーなしで機能します。ただし、これらのクエリは複数のデータベースバックエンドに使用されるため、OracleテキストバインディングだけにTO_NCHARを追加したくありません。足りないものはありますか?TO_NCHARハンマーなしでこれを解決する別の方法は?

検索やマニュアルで関連するものを見つけることができませんでした。

詳細...

- エラー

SELECT (CASE profile WHEN          '_default'  THEN 1 ELSE 2 END) AS profile_order
FROM engine_properties;

- わかった

SELECT (CASE profile WHEN TO_NCHAR('_default') THEN 1 ELSE 2 END) AS profile_order
FROM engine_properties;
SQL> describe engine_properties;
 名前ヌル?タイプ
 -------------------------------------------------- ---------------------------
 EID NOT NULL NVARCHAR2(22)
 LID NOT NULL NUMBER(11)
 PROFILE NOT NULL NVARCHAR2(32)
 PKEY NOT NULL NVARCHAR2(50)
 VALUE NOT NULL NVARCHAR2(64)
 READONLY NOT NULL NUMBER(5)

TO_NCHARのないこのバージョンは、SQL ServerとPostgreSQL(ODBC経由)およびSQLite(直接)で正常に機能します。ただし、Oracleでは「ORA-12704:文字セットの不一致」が返されます。

SQLPrepare(SELECT (CASE profile WHEN ? THEN 1 ELSE 2 END) AS profile_order 
    FROM engine_properties;) = SQL_SUCCESS
SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_WCHAR, 
    SQL_VARCHAR, 32, 0, "_default", 18, 16) = SQL_SUCCESS
SQLExecute() = SQL_ERROR
SQLGetDiagRec(1) = SQL_SUCCESS
[SQLSTATE: HY000, NATIVE: 12704, MESSAGE: [Oracle][ODBC]
    [Ora]ORA-12704: character set mismatch]
SQLGetDiagRec(2) = SQL_NO_DATA

TO_NCHARを使用する場合は問題ありません(ただし、SQL Server、Postgres、SQLiteなどでは機能しません)。

SQLPrepare(SELECT (CASE profile WHEN TO_NCHAR(?) THEN 1 ELSE 2 END) AS profile_order
    FROM engine_properties;) = SQL_SUCCESS
SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_WCHAR, 
    SQL_VARCHAR, 32, 0, "_default", 18, 16) = SQL_SUCCESS
SQLExecute() = SQL_SUCCESS
SQLNumResultCols() = SQL_SUCCESS (count = 1)
SQLFetch() = SQL_SUCCESS
4

2 に答える 2

0

Oracle データベースの文字セットが AL32UTF8 の場合、列が NVARCHAR2 として定義されているのはなぜですか? つまり、各国の文字セット (通常は AL16UTF16 ですが、データベースによっては異なる場合があります) を使用してこれらの列をエンコードする必要があることを意味します。主にアジア言語のデータ (または AL32UTF8 で 3 バイトのストレージを必要とするその他のデータ) を格納する場合を除き、データベースの文字セットが Unicode をサポートしている場合、Oracle データベースに NVARCHAR2 列を作成することは比較的まれです。

一般に、国別文字セット (NCHAR および NVARCHAR2 列) を使用するよりも、データベースの文字セット (CHAR および VARCHAR2 列) に固執する方がはるかに優れています。開発/構成面。NVARCHAR2 データ型を選択してエンコードできる文字セットを増やすわけではないので、VARCHAR2 データ型の方が満足できると思います。

于 2008-12-03T16:37:41.177 に答える
0

ありがとうジャスティン。

VARCHAR2 と NVARCHAR2 のどちらを選択するかを正確に理解しているとは言えません。私は自分の日付に VARCHAR2 を使用しようとしましたが (これにはヨーロッパとアジアの両方のさまざまな言語が含まれています)、その時はうまくいきませんでした。

私はもう一度遊んでみましたが、ジャスティンの提案を使用すると、次の組み合わせで機能することがわかりました。

  • AL32UTF8 データベース文字セット
  • VARCHAR2 列タイプ
  • sqlplus.exe を開始する前に NLS_LANG=.UTF8 を設定します。
  • UTF-8 を使用するデータ ファイル (つまり、すべての INSERT ステートメントを含むファイル)
  • SQL_C_WCHAR を使用してデータベースに文字列を挿入および抽出する

私はまだOracleを(たとえば)PostgreSQLほど楽しく遊んでいるとは思いませんが... :-)

于 2008-12-03T20:33:14.853 に答える