Я использую следующий оператор, подготовленный и связанный в 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;
-- ok
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