【问题标题】:How to get database schema name when using oracle jdbc connection?使用 oracle jdbc 连接时如何获取数据库模式名称?
【发布时间】:2012-11-12 09:37:39
【问题描述】:

我正在尝试使用 DatabaseMetaData.getTables() 方法获取所有数据库表。但是这种方法需要数据库模式名称模式。是否可以获取当前数据库连接的架构名称?

【问题讨论】:

    标签: java oracle jdbc


    【解决方案1】:

    当前连接的标准架构是您用于登录的用户名。因此,如果您的用户是SCOTT,则必须使用SCOTT 来表示DatabaseMetaData.getTables()

    您可以通过DatabaseMetaData.getUserName()获取用户名。

    但请记住,在 JDBC 驱动程序中比较模式/用户名是区分大小写的,并且通常用户名是大写的。

    我不能 100% 确定 DatabaseMetaData.getUserName() 是否会在所有情况下以正确的大小写返回名称。可以肯定的是,您可能希望在使用该值之前执行一个 upperCase()。

    【讨论】:

    • 你是对的。我正在寻找的带有模式 id 名称的字符串是大写的用户名字符串。
    • 既然schema/username是区分大小写的,为什么Oracle把用户名存储为大写??
    • @CKLee:因为 SQL 标准要求标识符被折叠成大写,这就是为什么非引号标识符在 Oracle 中以大写形式存储。在这种情况下,区分大小写的原因是后台的 JDBC 驱动程序执行类似where owner = ? 的操作,并且 that 比较区分大小写(与所有其他字符串比较一样)。作为 标识符 一部分的用户名不区分大小写。 select * from SCOTT.foobarselect * from scott.FOObar 相同
    • 我现在正在为不同的数据库开发 DDL 层。 Oracle 的行为使我无法概括我的实现。无论如何要强制 Oracle 将用户名与原始案例一起存储?
    • @CKLee:没有单一的解决方案:一些 DBMS 以大写形式存储它,一些以小写形式存储,一些以混合大小写形式存储。比较字符串时,有些区分大小写,有些不区分,有些有时区分。有些总是独立于操作系统和安装选项工作,因为有些这种行为取决于配置或操作系统。
    【解决方案2】:

    尝试使用 getCatalogs()。这是一个速写

      public List<String> getDatabases(DBEnv dbEnv) {
    
            Connection conn = getConnection(dbEnv);
            List<String> resultSet = new ArrayList<String>();
    
            try {
                DatabaseMetaData metaData = conn.getMetaData();
                ResultSet res = metaData.getCatalogs();
    
                while (res.next()) {
                    resultSet.add(res.getString("TABLE_CAT"));
                }
    
            } catch (SQLException e) {
                logger.error(e.toString());
            }
    
            return resultSet;
    
        }
    

    【讨论】:

    • 不知道为什么但是结果集是空的。
    • @ThaiTran 你知道为什么该方法被称为 getCatalogs 而不是 getSchemas 吗?
    • @johnny-b-goode - 如果您同时发现原因:) - 是数据库以不同的方式解释该方法吗?我的意思是,它适用于 MySql,但在 Oracle 或其他类型的数据库上它可能会返回其他类型的对象(我在阅读 stackoverflow.com/questions/7942520/… 时遇到了这个提示)
    【解决方案3】:

    从 Java 7 开始,Connection 有一个 getSchema 方法:https://docs.oracle.com/javase/8/docs/api/java/sql/Connection.html#getSchema--

    【讨论】:

    • 很好的调用但是...至少在 MySQL (v5.7.x) [Connection].getSchema() 上返回 null - 即使模式是在连接字符串上定义的。 MySQL 将其解释为数据库实例 ID 的方式略有不同,并且显然没有将其转换为 JDBC 的适当数据模型(目录/模式/{object})。
    • OP 问题与 Oracle 特别相关,但考虑到 JDBC 应该是抽象的……人们会认为“getSchema()”会返回模式,而“getUserName()”等会返回与用户、数据库实例 ID 和模式的通用模型相关联的预期数据,但是……唉,这显然与 Oracle 和 MySQL 不一致。
    【解决方案4】:

    不幸的是,答案是没有一致的解决方案。如果 John 有权访问 Sally.Table ... 查询将起作用,但 getUserName() 将返回 John 而不是 Sally 模式。对于 Oracle,用户拥有他们的架构,而其他人可能有权访问,该用户 ID 是该连接上的 默认 架构。

    此外,getSchemaName() 和 getCatalog() 都不会返回架构名称。

    @horse_with_no_name 对 Oracle 有最接近的答案,因为给定的用户名是(默认)模式名称,除非在对象引用中被覆盖,如图所示。

    对于其他数据库,相同的规则并不一致。

    【讨论】:

      【解决方案5】:

      您可以使用

      获取架构名称
      Connection conn = 
      DriverManager.getConnection("jdbc:oracle:thin:@server:port:SID",prop);    
      DatabaseMetaData databaseMetaData = conn.getMetaData();
      System.out.println("schema name >>>> "+databaseMetaData.getUserName());
      

      【讨论】:

        猜你喜欢
        • 2011-08-06
        • 1970-01-01
        • 2014-11-11
        • 2014-12-13
        • 2015-03-16
        • 2016-10-01
        • 2019-08-21
        • 1970-01-01
        相关资源
        最近更新 更多