如何解决Oracle 19c jdbc 驱动程序不支持大于 30 字节的模式名称
根据 Oracle 的 19c documentation:
架构名可以是128个字节,表名可以是128个字节,列名可以是128个字节。
但是,每当我尝试使用大于 30 字节的架构名称时,我都会面临这个问题:
Caused by: java.sql.sqlException: Invalid argument(s) in call
at oracle.jdbc.driver.PhysicalConnection.setSchema(PhysicalConnection.java:9462)
at com.zaxxer.hikari.pool.ProxyConnection.setSchema(ProxyConnection.java:460)
at com.zaxxer.hikari.pool.HikariProxyConnection.setSchema(HikariProxyConnection.java)
使用的驱动程序是:
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>19.7.0.0</version>
</dependency>
看起来驱动程序不支持根据 12c 版本引入的更长的对象名称,是否可以以某种方式配置任何线索?是否也可能是一些 AWS RDS 特定问题?
在使用相同 jdbc url 的 sql Developer 上:
SELECT name,value FROM v$parameter WHERE name = 'compatible';
NAME | VALUE
-------------------
compatible | 19.0.0
ALTER SESSION SET CURRENT_SCHEMA = VERY_VERY_VERY_LONG_SCHEMA_NAME;
Session altered.
更新: 反编译驱动程序代码后,这是我看到的:
public void setSchema(String schema) throws sqlException {
try {
String quoted = "\"[^\u0000\"]{0,28}\"";
String unquoted = "(\\p{javaLowerCase}|\\p{javaUpperCase})(\\p{javaLowerCase}|\\p{javaUpperCase}|\\d|_|\\$|#){0,29}";
String idPat = "(" + quoted + ")|(" + unquoted + ")";
sqlException var10000;
sqlException var9;
if (schema == null) {
var10000 = var9 = (sqlException)((sqlException)DatabaseError.createsqlException(this.getConnectionDuringExceptionHandling(),68).fillInStackTrace());
throw var10000;
} else if (!schema.matches(idPat)) {
var10000 = var9 = (sqlException)((sqlException)DatabaseError.createsqlException(this.getConnectionDuringExceptionHandling(),68).fillInStackTrace());
throw var10000;
} else {
String sql = "alter session set current_schema = " + schema;
Statement stmt = null;
try {
stmt = this.createStatement();
stmt.execute(sql);
...
}
意味着驱动程序被硬编码为仅接受 30 个字符。所以这似乎是 Oracle JDBC 驱动程序中的一个错误实现。有什么替代方案吗?
解决方法
在长标识符更改中,setSchema
似乎被遗忘(而且您似乎必须使用 Oracle 打开 SR 才能使其工作)
相反,JDBC
中长标识符的基本用法(包括按名称绑定)似乎工作正常。
示例
def rs = stmt.executeQuery("select COL1,LAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGE_NAME from LAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGE_NAME.LAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGE_NAME")
while(rs.next())
{
println "col1= ${rs.getInt('COL1')} col2= ${rs.getInt('LAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGE_NAME')}"
}
使用数据库版本 19.3.0.0.0 测试
驱动程序版本 19.3.0.0.0 和 21.1.0.0.0
,来自您的documentation link:
除非另有说明,以下规则列表适用于带引号和不带引号的标识符:
-
标识符名称的最大长度取决于
1101
初始化参数的值。-
如果
COMPATIBLE
设置为 12.2 或更高的值,则名称的长度必须为 1 到 128 个字节,以下情况除外:- 数据库名称限制为 8 个字节。
- 磁盘组、可插拔数据库 (PDB)、回滚段、表空间和表空间集的名称限制为 30 个字节。
-
如果
COMPATIBLE
设置为小于 12.2 的值,则名称的长度必须为 1 到 30 个字节,以下情况除外:- 数据库名称限制为 8 个字节。
- 数据库链接的名称最长可达 128 个字节。
-
您需要检查 COMPATIBLE
初始化参数,如果它设置在 COMPATIBLE
以下,那么您被限制为 30 个字节。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。