Почему Oracle требует TO_NCHAR при связывании текста SQL_C_WCHAR через ODBC - PullRequest
1 голос
/ 03 декабря 2008

Я использую следующее утверждение, подготовленное и связанное в ODBC:

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

Выполняется при подключении ODBC 3.0 к базе данных Oracle 10g в кодировке AL32UTF8, даже после привязки к строке wchar_t с использованием SQLBindParameter(SQL_C_WCHAR) все равно выдает ошибку ORA-12704: несоответствие набора символов.

Почему? Я обязываю как wchar. Разве wchar не должен считаться NCHAR?

Если я изменяю параметр, чтобы обернуть его с помощью TO_NCHAR(), тогда запрос работает без ошибок. Однако, поскольку эти запросы используются для нескольких баз данных, я не хочу добавлять TO_NCHAR только для текстовых привязок Oracle. Есть что-то, чего мне не хватает? Еще один способ решить эту проблему без молотка 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;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 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

Ответы [ 2 ]

0 голосов
/ 03 декабря 2008

Спасибо, Джастин.

Не могу сказать, что точно понимаю, как выбирать между VARCHAR2 и NVARCHAR2. Я пытался использовать VARCHAR2 для моего свидания (которое включает в себя много разных языков, как европейских, так и азиатских), и в то время это не сработало.

Мне снова пришлось немного поиграть, и я обнаружил, что использование предложения Джастина работает в этой комбинации:

  • AL32UTF8 кодировка базы данных
  • Типы столбцов VARCHAR2
  • установить NLS_LANG = .UTF8 перед запуском sqlplus.exe
  • файлы данных с использованием UTF-8 (то есть файлы со всеми операторами INSERT)
  • вставка и извлечение строк из базы данных с использованием SQL_C_WCHAR

Я до сих пор не нахожу Oracle, с которым интересно играть, как, например, с PostgreSQL ...: -)

0 голосов
/ 03 декабря 2008

Если набор символов базы данных Oracle - AL32UTF8, почему столбцы определены как NVARCHAR2? Это означает, что вы хотите, чтобы эти столбцы были закодированы с использованием национального набора символов (обычно AL16UTF16, но это может отличаться в вашей базе данных). Если вы в основном не храните данные на азиатском языке (или другие данные, которые требуют 3 байта для хранения в AL32UTF8), довольно редко можно создавать столбцы NVARCHAR2 в базе данных Oracle, когда набор символов базы данных поддерживает Unicode.

В общем, вам лучше справляться с набором символов базы данных (столбцы CHAR и VARCHAR2), а не пытаться работать с национальным набором символов (столбцы NCHAR и NVARCHAR2), потому что требуется гораздо меньше переходов, по которым нужно переходить на стороне разработки / конфигурации вещей. Поскольку вы не увеличиваете набор символов, которые вы можете кодировать, выбирая типы данных NVARCHAR2, держу пари, что вы будете счастливее с типами данных VARCHAR2.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...