文章
· 一月 24, 2021 阅读大约需 3 分钟

解决SQL适配器连接到字符集为US7ASCII的Oracle数据库的中文乱码问题

在使用xDBC连接到字符集为US7ASCII的Oracle数据库时,大家可能遇到过中文的乱码问题,尤其是使用Oracle自己的xDBC驱动的时候。

字符集为US7ASCII的Oracle数据库虽然可以保存中文数据,但给客户端带来了很多麻烦,需要对获取和提交的数据进行转码。

 

在Ensemble/Health Connect/InterSystems IRIS 中使用SQL适配器连接到这样的Oracle数据库时,可以使用$ZCVT函数进行转码。

1. $ZCVT函数

$ZCVT函数是广泛使用的字符串转换函数,可以做大小写转换、编码转换、URL 和 URI 转换等。我们用其编码转换能力来解决字符集转码问题。

 

2. 获取的SQL结果集数据有中文时

这时,Oracle的驱动返回的中文数据通常是GB码,而不是Unicode或UTF码。可以通过$ZCVT函数对GB码的数据进行转码,转换为Unicode:

Set tCorrectData = $ZCVT(tOriginalData,"I","GB18030")
其中$ZCVT函数的第一个参数tOriginalData是获取到到结果集字段值;第二个参数“I”说明tOriginalData是输入字符串;第三个参数“GB18030”是说明输入字符串的字符集编码是GB18030。

上面的代码会将tOriginalValue按GB18030编码转换为Unicode编码,并将转换结果赋给变量tCorrectData。

 

3. 发送中文数据或中文查询条件时

首先,需要将本地Unicode的中文数据转码为GB码。还是使用$ZCVT函数:

Set tSendingData = $ZCVT(tOriginalData,"O","GB18030")

其中$ZCVT函数的第一个参数tOriginalData是输出的含中文数据;第二个参数“O”说明要转换输出数据;第三个参数“GB18030”是说明输出时要转换为GB18030。

上面的代码会将tOriginalValue按Unicode编码转换为GB18030编码,并将转换结果赋给变量tSendingData。

 

做完这一步,Oracle驱动很可能依然不认识其中的GB码中文数据。这时,需要将GB码的中文数据转换成GB明码字符串,例如你要将查询条件 中文 传给Oracle,你需要传递 D6D0CEC4过去(中的GB码为D6D0,文的GB码为CEC4),然后再使用Oracle的函数UTL_RAW.CAST_TO_VARCHAR2,将GB明码字符串转为内部使用的中文数据。所以修改后代码如下:

    Set tSendingData = $ZCVT(tOriginalData,"O","GB18030")
    Set tTmpDataHex = ""
    //转换为GB明码   
    For i=1:1:$length(tSendingData) 
    {
          Set tTmpDataHex = tTmpDataHex_$zhex($ASCII(tSendingData,i))
    }   
   //使用Oracle的UTL_RAW.CAST_TO_VARCHAR2的函数
   Set tSQL = "update dept_dict set dept_name = UTL_RAW.CAST_TO_VARCHAR2('"_ tTmpDataHex_"') where dept_code = '1'"

这里用到了$ZHEX$ASCII函数,将数据转换为其编码,并转为16进制值,从而得到GB明码。关于更多的Ensemble/Health Connect/InterSystems IRIS函数,可以参考文档

 

自此,应该可以解决从Ensemble和Health Connect连接到字符集为US7ASCII的Oracle数据库所遇到的各种中文乱码问题了。

如果您遇到更多的问题,欢迎在社区提问。

讨论 (2)1
登录或注册以继续