PLS-00561 при загрузке NCLOB

Finder
Дата: 03.12.2009 11:24:14
Юникодное приложение на VC++ 2005
Клиент: OCCI 11 (Instant Client)

Загружаю юникодный текст через ХП в NCLOB поле таблицы (параметр "TEXTVAL" в ХП тоже NCLOB), внутри ХП - INSERT

m_pEnv = oracle::occi::Environment::createEnvironment("OCCIUTF16","OCCIUTF16", oracle::occi::Environment::OBJECT);
... // Вызываем ХП, вставляющую запись в таблицу
m_pOCCIStmt = m_pOCCIConn->createStatement((utext*) (LPCTSTR) sProcName);
.. // Пишем NCLOB
oracle::occi::Clob* pClob = OCCIGetTempClob();
pClob->open(oracle::occi::OCCI_LOB_READWRITE);
pClob->setCharSetIdUString((utext*) L"OCCIUTF16");
int iReaded = _tcslen(strVal); 
pClob->writeChunk(iReaded, (utext*) strVal, iReaded*2, 1);            
pClob->close(); 
m_pOCCIStmt->setClob(m_iOCCIParamIndex, *pClob);
m_pOCCIStmt->executeUpdate();

С моим сервером "FINDER" все работает прекрасно, с сервером ORACLE-TEST на executeUpdate() возникает ошибка:

PLS-00561: character set mismatch on value for parameter 'TEXTVAL'

Перечитал уже кучу статей, но совсем запутался. Со стороны клиента я явно передаю юникод, поле в БД - юникодное NCLOB, на каком этапе Оракл пытается что-то там преобразовать???

Вот краткая инфа о чарсетах (NLS_CHARACTERSET разный, но он же не должен влиять?!):

--select * from nls_database_parameters;

-- сервер ORACLE-TEST (9i)
NLS_NCHAR_CHARACTERSET AL16UTF16
NLS_CHARACTERSET       AL32UTF8

--сервер FINDER (10g)
NLS_NCHAR_CHARACTERSET AL16UTF16
NLS_CHARACTERSET       CL8MSWIN1251

Прошу помочь разобраться, перелопатил уже кучу инфы и все равно никак не пойму... :-(
Finder
Дата: 03.12.2009 13:30:04
В эту же ХП передается юникодная строка nvarchar2 - и все записывается/читается нормально
m_pOCCIStmt->setDatabaseNCHARParam(m_iOCCIParamIndex, true);
m_pOCCIStmt->setUString(m_iOCCIParamIndex, (utext*) strVal);

Попробовал добавлять NCLOB параметр аналогичным кодом:
m_pOCCIStmt->setDatabaseNCHARParam(m_iOCCIParamIndex, true);
oracle::occi::Clob* pClob = OCCIGetTempClob();
pClob->open(oracle::occi::OCCI_LOB_READWRITE);
int iReaded = _tcslen(strVal); // 
pClob->writeChunk(iReaded, (utext*) strVal, iReaded*2, 1);            
pClob->close(); 
m_pOCCIStmt->setClob(m_iOCCIParamIndex, *pClob);
в этом варианте исключения не возникает, но в БД записывается текст в нечитабельном виде.
Finder
Дата: 03.12.2009 14:16:06
С передачей юникодной строки в NCLOB параметр заработал вариант с установкой setDatabaseNCHARParam() и почему-то текущей кодировки БД для NCLOB - "AL16UTF16":
m_pOCCIStmt->setDatabaseNCHARParam(m_iOCCIParamIndex, true);
oracle::occi::Clob* pClob = OCCIGetTempClob();
pClob->open(oracle::occi::OCCI_LOB_READWRITE);
CString OldCharSetId = (LPCTSTR) pClob->getCharSetIdUString().c_str(); // AL32UTF8=NLS_CHARACTERSET
pClob->setCharSetIdUString((utext*) L"AL16UTF16"); // =NLS_NCHAR_CHARACTERSET
//pClob->setCharSetIdUString((utext*) L"OCCIUTF16");				
int iReaded = _tcslen(strVal); // 
pClob->writeChunk(iReaded, (utext*) strVal, iReaded*2, 1);            
pClob->close(); 
m_pOCCIStmt->setClob(m_iOCCIParamIndex, *pClob);

То что заработало, конечно хорошо. Но почему надо устанавливать "AL16UTF16" - чем OCCI не устраивает стандартный параметр юникодной кодировки "OCCIUTF16" - который прекрасно работает с сервером "FINDER"?

Надо ли всегда при работе с NCLOB устанавливать "AL16UTF16" или надо при коннекте запрашивать значение NLS_NCHAR_CHARACTERSET и потом всегда подставлять его?
Finder
Дата: 03.12.2009 14:28:34
и как оказалось, последний вариант нормально работает с сервером "ORACLE-TEST", но портит кодировку на сервере "FINDER". Имеем два взаимоисключающих варианта.
Finder
Дата: 03.12.2009 14:31:11
Есть одно подозрение - сервера разных версий, "ORACLE-TEST" - 9ка, а "FINDER" - 10ка...
Finder
Дата: 04.12.2009 09:48:42
http://download.oracle.com/docs/cd/B12037_01/appdev.101/b10778/globalization.htm
Нашел казалось бы четкую инструкцию по работе с OCCI NCLOB:
CLOB and NCLOB Datatypes
Oracle provides the CLOB and NCLOB datatypes for storing and processing large amounts of character data. 
CLOBs represent data in the database characterset and NCLOBs represent data in the database national 
characterset. CLOBs and NCLOBs can be used as column types in relational tables and as attributes in 
object types.
The OCCI Clob class is used to work with both CLOB and NCLOB datatypes. If the database type is NCLOB, 
then the Clob setCharSetForm() method should be called with OCCI_SQLCS_NCHAR before reading/writing from 
the LOB.
The OCCI Clob class has support for multibyte and UTF16 charactersets. By default, the Clob interfaces 
assume the data is encoded in the client-side characterset (for both CLOBs and NCLOBs). To specify a 
different characterset or to specify the client-side national characterset for a NCLOB, call the 
setCharSetId() or setCharSetIdUString() methods with the appropriate characterset. The OCCI specific 
string 'OCCIUTF16' can be passed to indicate UTF16 as the characterset.

Example 7-5 Using CLOB and NCLOB Datatypes

//client characterset - ZHT16BIG5, national characterset - UTF16
Environment *env = Environment::createEnvironment("ZHT16BIG5","OCCIUTF16");...
Clob nclobvar;
//for NCLOBs, need to call setCharSetForm method. 
nclobvar.setCharSetForm(OCCI_SQLCS_NCHAR);...
//if reading/writing data in UTF16 for this NCLOB, still need to 
//explicitly call setCharSetId
nclobvar.setCharSetId("OCCIUTF16")

Не тут-то было... если добавить при записи NCLOB параметра в ХП вызов setCharSetForm(OCCI_SQLCS_NCHAR); - то получаем "ORA-24806 LOB form mismatch" - стабильно на обоих серверах.
При чтении из CLob из рекордсета я всегда использую оба эти вызова, они срабатывают нормально, но не на запись... В примере чарсет клиента указан неюникодный, но т.к. у меня юникодное приложение, использую
createEnvironment("OCCIUTF16","OCCIUTF16")

Судя по количеству советов в этом топике, что - неужели никто не работает через OCCI с юникодным NCLOB???
:-(