解决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 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数据库所遇到的各种中文乱码问题了。
如果您遇到更多的问题,欢迎在社区提问。