0

我正在尝试将加密的 unicode 文本存储在 OracleRAW字段中。AL32UTF8在加密之前,为了提高效率,我将字符串转换为原始字节数组。(NLS_NCHAR_CHARACTERSETAL16UTF16)。

从UTL_I18N 包中抛出LOSSY_CHARACTERSET_CONVERSION( ORA-12713) 异常。

我故意设置NCharConversionException = true让它抛出异常,而不是让有损转换“希腊化”输出。

我究竟做错了什么?

为了方便起见,这里是一个使用 Dapper 的示例。没有调用 string_to_raw 的 NVarchar2 参数绑定可以正常工作。

    /// <summary>
    /// using Dapper;
    /// using Oracle.ManagedDataAccess.Client
    /// 
    /// </summary>
    [Test, Explicit]
    public void Dapper_Sql_NLS_StringToRaw_ReturnValue_RefCursor_SmokeTest()
    {

        var parms = new OracleDynamicParameters();
        var cn = ApiThreadContext.Current.Connection.DbConnection as OracleConnection;

        OracleGlobalization og = cn.GetSessionInfo();
        og.NCharConversionException = true; //throws LOSSY_CHARACTERSET_CONVERSION
        cn.SetSessionInfo(og);

        var expected = "Шон";

        parms.Add(":in_plain", expected, OracleDbType.NVarchar2, ParameterDirection.Input);
        parms.Add(":rc", dbType: OracleDbType.RefCursor, direction: ParameterDirection.ReturnValue);

        //'Шон'
        var result = cn.Query<dynamic>(
            "select utl_i18n.string_to_raw(:in_plain, 'AL32UTF8') from dual",
            //"select :in_plain from dual",
            parms,
            commandType: CommandType.Text
        );

    }  

客户端

Windows 7 Professional x64 SP1 .Net 4.6 Full Oracle.ManagedDataAccess.dll4.12.1.2400(最新)。

Oracle全球化设置:

{Oracle.ManagedDataAccess.Client.OracleGlobalization}
Calendar: "GREGORIAN"
Comparison: "BINARY"
Currency: "£"
DateFormat: "DD-MON-YYYY HH24:MI:SS"
DateLanguage: "ENGLISH"
DualCurrency: "€"
ISOCurrency: "UNITED KINGDOM"
Language: "ENGLISH"
LengthSemantics: "BYTE"
NCharConversionException: true
NumericCharacters: ".,"
Sort: "BINARY"
Territory: "UNITED KINGDOM"
TimeStampFormat: "DD-MON-RR HH24.MI.SSXFF"
TimeStampTZFormat: "DD-MON-RR HH24.MI.SSXFF TZR"
TimeZone: "Europe/London"

我没有NLS_LANG在客户端上设置环境变量,因为上面应该涵盖。(无论如何,我都没有检查它是否对托管提供者有任何影响)。

服务器

NLS_DATABASE_PARAMETERS

NLS_NCHAR_CHARACTERSET  AL16UTF16
NLS_LANGUAGE                ENGLISH
NLS_TERRITORY           UNITED KINGDOM
NLS_CURRENCY            £
NLS_ISO_CURRENCY            UNITED KINGDOM
NLS_NUMERIC_CHARACTERS  .,
NLS_CHARACTERSET            WE8MSWIN1252
NLS_CALENDAR                GREGORIAN
NLS_DATE_FORMAT         DD-MON-RR
NLS_DATE_LANGUAGE       ENGLISH
NLS_SORT                    BINARY
NLS_TIME_FORMAT         HH24.MI.SSXFF
NLS_TIMESTAMP_FORMAT        DD-MON-RR HH24.MI.SSXFF
NLS_TIME_TZ_FORMAT      HH24.MI.SSXFF TZR
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH24.MI.SSXFF TZR
NLS_DUAL_CURRENCY       €
NLS_COMP                    BINARY
NLS_LENGTH_SEMANTICS    BYTE
NLS_NCHAR_CONV_EXCP     FALSE
NLS_RDBMS_VERSION       10.2.0.5.0

V$版本

Oracle Database 10g Release 10.2.0.5.0 - 64bit Production
PL/SQL Release 10.2.0.5.0 - Production
CORE    10.2.0.5.0  Production
TNS for 64-bit Windows: Version 10.2.0.5.0 - Production
NLSRTL Version 10.2.0.5.0 - Production

客户端错误堆栈:

Test 'UddFixture.Dapper_Sql_NLS_StringToRaw_SmokeTest' failed:
    Oracle.ManagedDataAccess.Client.OracleException : ORA-12713: Character data loss in NCHAR/CHAR conversion
ORA-06512: at "SYS.UTL_I18N", line 321
ORA-06512: at line 1
    at OracleInternal.ServiceObjects.OracleCommandImpl.VerifyExecution(OracleConnectionImpl connectionImpl, Int32& cursorId, Boolean bThrowArrayBindRelatedErrors, OracleException& exceptionForArrayBindDML, Boolean& hasMoreRowsInDB, Boolean bFirstIterationDone)
    at OracleInternal.ServiceObjects.OracleCommandImpl.ExecuteReader(String commandText, OracleParameterCollection paramColl, CommandType commandType, OracleConnectionImpl connectionImpl, OracleDataReaderImpl& rdrImpl, Int32 longFetchSize, Int64 clientInitialLOBFS, OracleDependencyImpl orclDependencyImpl, Int64[] scnForExecution, Int64[]& scnFromExecution, OracleParameterCollection& bindByPositionParamColl, Boolean& bBindParamPresent, Int64& internalInitialLOBFS, OracleException& exceptionForArrayBindDML, Boolean isDescribeOnly, Boolean isFromEF)
    at Oracle.ManagedDataAccess.Client.OracleCommand.ExecuteReader(Boolean requery, Boolean fillRequest, CommandBehavior behavior)
    at Oracle.ManagedDataAccess.Client.OracleCommand.ExecuteDbDataReader(CommandBehavior behavior)
    Core\Connectivity\Dapper\SqlMapper.cs(1631,0): at Dapper.SqlMapper.<QueryImpl>d__61`1.MoveNext()
    at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
    at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
    Core\Connectivity\Dapper\SqlMapper.cs(1506,0): at Dapper.SqlMapper.Query[T](IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Boolean buffered, Nullable`1 commandTimeout, Nullable`1 commandType)
    UddFixture.cs(330,0): at UddFixture.Dapper_Sql_NLS_StringToRaw_SmokeTest()
4

1 回答 1

1

早些时候我也使用过OracleGlobalization对象,但是我遇到了几个错误。我明确建议不要使用它!

也许代替UTL_I18N.STRING_TO_RAW, function ASCIISTR, resp。UNISTR可能是您的问题的一个选项:

SELECT ASCIISTR('Шон') FROM dual;

\0428\043E\043D

SELECT UNISTR('\0428\043E\043D') FROM dual;

Шон
于 2015-10-16T07:39:38.133 回答