问题:在Oracle数据库中有两个表其中一个表名与另外一个表名只相差了一个下划线,在使用jdbc连接Oracle查询有下划线的表的表结构的时候就会将另外一个表的字段名带出来,因此创建两个表A_B_D和表A_BCD。
CREATE TABLE A_B_D(A1 NUMBER,A2 NUMBER,A3 CHAR);
CREATE TABLE A_BCD(A11 NUMBER,A12 CHAR,A13 FLOAT);
通过查看Oracle jdbc源码发现
通过使用like查询发现问题复现。
SELECT * FROM all_tab_columns WHERE table_name LIKE 'A_B_D' ORDER BY table_name,COLUMN_id
分析: rs = oracle.getMetaData().getColumns(null, table.getTableSchema(), table.getTableName(), null);
while (rs.next()) {
col = new Column(rs);
columns.add(col);
}
-
getColumns
ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException
Oracle getColumns查询表时用的是like,模糊查询,传入的表名是一个模板的样式,在Oracle中下划线(_)和百分号(%)都是代表的任意的一个字符,因此此时传入的表名为A_B_D,就会将表A_BCD的字段和表A_B_D的字段全部查出来。
解决方法:通过转义将下划线转义为特殊字符
sql语句中通过使用escape在下划线等通配符前自定义一个转义字符(通常使用:\,当然可以自定义其他字符),这样通配符就会解释为普通的字符。
SELECT * FROM all_tab_columns WHERE table_name LIKE 'A_B\_D' ESCAPE'\' ORDER BY table_name,COLUMN_id
在jdbc获取字段名中则将"_"用"\_"代替就可以
String tablename = table.getTableName();
tablename = tablename.replace("_","\_");
rs = oracle.getMetaData().getColumns(null, table.getTableSchema(), tablename, null);
这样就将下划线转义为了特殊字符,查A_B_D时就会只将这个表的字段查出来,问题解决。
对比PG,PG将下划线转义为特殊字符为"//_"