最近做项目时,由于其他同事修改了数据类型(nvarchar改为varchar),导致程序出错,错误提示为:ORA-12704: character set mismatch。本篇将重现此错误,并给出解决方案,具体如下:
一 错误描述
1 演示数据库版本
SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE 11.2.0.4.0 Production
TNS for Linux: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production
2 创建测试表T_Test1 & T_Test2
SQL> create table t_test1(id number, name varchar2(100));
Table created.
SQL> create table t_test2(id number ,name nvarchar2(100));
Table created.
3 初始化后的数据
SQL> select * from t_test1;
ID NAME
---------- --------------------
1 中国农业银行
2 中国建设银行
3
4 HSBC
SQL> select * from t_test2;
ID NAME
---------- --------------------
3 平安银行
4 执行查询,出现错误
SQL> SELECT t1.id,
CASE
WHEN t1.name IS NULL THEN
t2.name
ELSE
t1.name
END NAME
FROM t_test1 t1
LEFT JOIN t_test2 t2
ON t1.id = t2.id;
t1.name
*
ERROR at line 6:
ORA-12704: character set mismatch
出现此问题的原因是两个列字符类型不匹配,即字符集不匹配。
二 解决办法
解决思路:使用转换函数将两列的类型改为一致。
1 使用to_char函数做字符转换,将nvarchar2转为varchar2
SQL> SELECT t1.id,
CASE
WHEN t1.name IS NULL THEN
to_char(t2.name)
ELSE
t1.name
END NAME
FROM t_test1 t1
LEFT JOIN t_test2 t2
ON t1.id = t2.id;
ID NAME
---------- --------------------
3 平安银行
4 HSBC
1 中国农业银行
2 中国建设银行
2 使用to_nchar做字符转换,将varchar2转为nvarchar2
SQL> SELECT t1.id,
CASE
WHEN to_nchar(t1.name) IS NULL THEN
t2.name
ELSE
to_nchar(t1.name)
END NAME
FROM t_test1 t1
LEFT JOIN t_test2 t2
ON t1.id = t2.id;
ID NAME
---------- --------------------
3 平安银行
4 HSBC
1 中国农业银行
2 中国建设银行
3 使用cast函数做字符转换,将varchar2转为nvarchar2
SQL> SELECT t1.id,
CASE
WHEN cast(t1.name as nvarchar2(100)) IS NULL THEN
t2.name
ELSE
cast(t1.name as nvarchar2(100))
END NAME
FROM t_test1 t1
LEFT JOIN t_test2 t2
ON t1.id = t2.id;
ID NAME
---------- --------------------
3 平安银行
4 HSBC
1 中国农业银行
2 中国建设银行
4 使用 translate...using函数将varchar2转为nvarchar2
SQL> SELECT t1.id,
CASE
WHEN translate(t1.name USING nchar_cs) IS NULL THEN
t2.name
ELSE
translate(t1.name USING nchar_cs)
END NAME
FROM t_test1 t1
LEFT JOIN t_test2 t2
ON t1.id = t2.id;
ID NAME
---------- --------------------
3 平安银行
4 HSBC
1 中国农业银行
2 中国建设银行
5 使用 translate...using函数将nvarchar2转为varchar2
SQL> SELECT t1.id,
CASE
WHEN t1.name IS NULL THEN
translate(t2.name USING char_cs)
ELSE
t1.name
END NAME
FROM t_test1 t1
LEFT JOIN t_test2 t2
ON t1.id = t2.id;
ID NAME
---------- --------------------
3 平安银行
4 HSBC
1 中国农业银行
2 中国建设银行