SQL Server 2000转Oracle 12c重音字符显示问号求助
解决SQL Server TEXT到Oracle CLOB的重音字符乱码问题
咱们一步步来排查和修复这个问题,从数据读取、传输到写入Oracle的全流程梳理:
1. 确保SQL Server端读取的字符编码准确
jtds驱动读取SQL Server的TEXT列时,直接用getString可能会因为驱动默认的编码转换丢失信息,加上你用的Latin1_General_CI_AS其实是基于Windows-1252(而非单纯的ISO-8859-1),建议调整连接串和读取方式:
- 修改jtds连接串,指定
charset=CP1252(对应Latin1_General_CI_AS的实际编码):jdbc:jtds:sqlserver://host:port/dbname;charset=CP1252 - 改用
getClob读取大文本列,避免字符串截断或编码转换问题:Statement st = conn1.createStatement(); ResultSet rs = st.executeQuery("select * from table1 where id = 63"); while(rs.next()){ // 用Clob读取TEXT列 Clob sqlServerClob = rs.getClob("TESTO"); String testo = sqlServerClob.getSubString(1, (int) sqlServerClob.length()); // 后续写入Oracle的代码... }
2. 修正Oracle连接的字符集配置
Oracle的字符集是WE8ISO8859P15,需要确保JDBC连接时的字符集和数据库一致,避免转换丢失:
- 在Oracle JDBC连接串中添加字符集参数:
jdbc:oracle:thin:@//host:port/service?characterEncoding=ISO-8859-15&useUnicode=false - 同时设置JVM的
NLS_LANG环境变量(可以在启动脚本中添加):
注意:export NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P15-Dfile.encoding参数不影响JDBC和数据库的字符交互,不用再设置。
3. 正确写入Oracle CLOB列
直接用setString写入CLOB可能会触发隐式的字符编码转换,建议用字符流或Clob对象写入:
PreparedStatement ps = conn2.prepareStatement("insert into table2(id, testo) values(?,?)"); ps.setString(1, rs.getString("ID")); // 方式1:用StringReader写入字符流 ps.setClob(2, new StringReader(testo)); // 方式2:创建Oracle Clob对象写入 // Clob oracleClob = conn2.createClob(); // oracleClob.setString(1, testo); // ps.setClob(2, oracleClob); ps.executeUpdate(); // 注意:插入用executeUpdate,不是executeQuery! ps.close();
这里要注意:你原来的代码用了ps.executeQuery(),插入操作应该用executeUpdate(),虽然可能不影响字符,但这是规范问题。
4. 验证Oracle端数据是否正确
SQL Developer显示问号大概率是工具自身的编码配置问题,而非数据库数据错误:
- 用Oracle的
dump函数查看字节值,确认重音字符的存储是否正确:
如果结果中select dump(testo, 1016) from table2 where id=63;è对应的十六进制是E8(符合WE8ISO8859P15编码),说明数据存储没问题,只是SQL Developer的编码设置不对。你可以在SQL Developer中调整工具→首选项→环境→编码为ISO-8859-15试试。
5. 正确读取Oracle CLOB列
读取Oracle CLOB时,同样要避免直接用getString,改用Clob的字符流或getSubString:
Statement stOracle = conn2.createStatement(); ResultSet rsOracle = stOracle.executeQuery("select testo from table2 where id=63"); if(rsOracle.next()){ Clob oracleClob = rsOracle.getClob("testo"); // 方式1:用getSubString读取 String content = oracleClob.getSubString(1, (int) oracleClob.length()); // 方式2:用字符流读取(适合大文本) BufferedReader reader = new BufferedReader(oracleClob.getCharacterStream()); StringBuilder sb = new StringBuilder(); String line; while((line = reader.readLine()) != null){ sb.append(line); } String content = sb.toString(); System.out.println(content); }
另外,确保ojdbc8.jar(匹配Oracle12c)和orai18n.jar都在你的classpath中,后者负责Oracle的国际化字符处理。
内容的提问来源于stack exchange,提问作者uizz
相关产品推荐
相关产品推荐

