You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:51:40