【问题标题】:Oracle 19c jdbc driver doesn't support schema names bigger than 30 bytesOracle 19c jdbc 驱动程序不支持大于 30 字节的模式名称
【发布时间】:2021-09-05 23:39:08
【问题描述】:

根据甲骨文的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 驱动程序 实现中的错误。有替代方案的想法吗?

【问题讨论】:

  • 就在您的链接上:标识符名称的最大长度取决于 COMPATIBLE 初始化参数的值。: .... · 如果 COMPATIBLE 设置为低于 12.2 的值,则名称的长度必须为 1 到 30 个字节,但有这些例外
  • 这也可能取决于你database character set,因为:Oracle 数据库使用数据库字符集:...标识符,如表名、列名和 PL/SQL 变量。将 SQL 语句传递给数据库后,它不再是编程语言语义,因此文本是 DB 字符集
  • 兼容已经是 19.0
  • 您必须等待(或提高 SR)新的驱动程序版本。顺便说一句,DriverVersion 21.1.0.0.0 (ojdbc8.jar) 似乎触发了同样的异常Caught: java.sql.SQLException: Invalid argument(s) in call ...
  • @MarmiteBomber - 不。绝不。在 IT 领域 40 多年的时间里,我从来没有需要(或想要)一个这么长的对象名称。将其归结为理智、深思熟虑、记录在案、严格应用的命名标准。

标签: java database oracle jdbc ojdbc


【解决方案1】:

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 测试

DriverVersion 19.3.0.0.0 和 21.1.0.0.0

【讨论】:

    【解决方案2】:

    来自您的documentation link

    除非另有说明,否则以下规则列表适用于带引号和不带引号的标识符:

    1. 标识符名称的最大长度取决于COMPATIBLE初始化参数的值。

      • 如果 COMPATIBLE 设置为 12.2 或更高的值,则名称的长度必须为 1 到 128 个字节,但以下情况除外:

        • 数据库名称限制为 8 个字节。
        • 磁盘组、可插拔数据库 (PDB)、回滚段、表空间和表空间集的名称限制为 30 个字节。
      • 如果 COMPATIBLE 设置为低于 12.2 的值,则名称的长度必须为 1 到 30 个字节,但以下情况除外:

        • 数据库名称限制为 8 个字节。
        • 数据库链接的名称可以长达 128 个字节。

    您需要检查COMPATIBLE 初始化参数,如果它设置在12.2 以下,则限制为30 个字节。

    【讨论】:

    • 我没有包含这些细节,因为我认为它们是多余的,但我只是用这些信息更新了问题,兼容版本已经是 19.0.这里仍然没有成功。
    猜你喜欢
    • 1970-01-01
    • 2011-05-16
    • 2021-11-19
    • 2012-11-26
    • 1970-01-01
    • 2020-10-15
    • 2021-08-30
    • 2019-05-18
    • 2012-04-04
    相关资源
    最近更新 更多