使用 oracle jdbc 连接时如何获取数据库模式名称?

Posted

技术标签:

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

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

【问题讨论】:

【参考方案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 或其他类型的数据库上它可能会返回其他类型的对象(我在阅读 ***.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());

【讨论】:

以上是关于使用 oracle jdbc 连接时如何获取数据库模式名称?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过JDBC连接Oracle数据库获取表名列表

使用JDBC获取Oracle连接时报错

oracle jdbc中getConnection中的参数如何配置才能获得连接,

JDBC连接ORACLE

如何使用JDBC连接oracle数据库

AWS Glue:如何使用 JDBC 连接 oracle db