从 jdbc/postgresql 获取新创建表的列元数据

Posted

技术标签:

【中文标题】从 jdbc/postgresql 获取新创建表的列元数据【英文标题】:Getting column metadata from jdbc/postgresql for newly created table 【发布时间】:2014-03-05 07:49:06 【问题描述】:

我正在尝试从新创建的表中获取列列表(它是在 java 代码中创建的)。 问题是我没有得到这些列。 该代码适用于已经在数据库中的表,但是如果我创建一个新表并尝试立即获取列信息,它不会找到任何...

更新: 这是我用于测试的完整代码:

@Test
public void testtest() throws Exception 
    try (Connection conn = dataSource.getConnection()) 
        String tableName = "Table_" + UUID.randomUUID().toString().replace("-", "");
        try (Statement statement = conn.createStatement()) 
            statement.executeUpdate(String.format("create table %s (id int primary key,name varchar(30));", tableName));
        
        DatabaseMetaData metaData = conn.getMetaData();
        try (ResultSet rs = metaData.getColumns(null, null, tableName, null)) 
            int colsFound = 0;
            while (rs.next()) 
                colsFound++;
            
            System.out.println(String.format("Found %s cols.", colsFound));
        
        System.out.println(String.format("Autocommit is set to %s.", conn.getAutoCommit()));
    

和输出:

Found 0 cols.
Autocommit is set to true.

【问题讨论】:

创建新表后是否关闭连接? 是的,我关闭了两个:语句和连接。虽然我使用 DriverManagerDataSource 来获取连接所以它可能是它没有关闭...... 【参考方案1】:

问题在于您的表名的大小写:

String tableName = "Table_" 

因为这是一个不带引号的标识符(一件好事),所以当 Postgres 将其名称存储在系统目录中时,该名称将转换为小写。

DatabaseMetaData API 调用区分大小写 ("Table_" != "table_"),因此您需要传递小写的表名:

ResultSet rs = metaData.getColumns(null, null, tableName.toLowerCase(), null))

有关如何使用标识符的更多详细信息在手册中:http://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS

【讨论】:

就是这样。感谢您的回复。【参考方案2】:

我做了简单的测试,它似乎工作。我可以使用 PostgreSQL JDBC 创建新表并显示其列(我使用 Jython):

conn = db.createStatement()
conn.execute("CREATE TABLE new_table (id SERIAL, txt VARCHAR(200))")
db_meta_data = db.getMetaData()
for tbl_name in ('date_test', 'new_table'):
    print('\n-- %s --' % (tbl_name))
    rs = db_meta_data.getColumns(None, None, tbl_name, None)
    while (rs.next()):
        print('%s:%s' % (rs.getString(3), rs.getString(4)))
conn.close()

此代码显示已存在的表的列:date_test 和刚刚创建的 new_table。我还在CREATE TABLE 之后添加了一些代码来关闭连接,但我的结果始终相同且正确。

可能是您的 JDBC 驱动程序有问题。我使用来自postgresql-9.3-1100.jdbc41.jar 的驱动程序。

也可能是用户权限的问题。您是否使用同一个用户来创建表和获取元数据? psqlpgAdmin 或其他工具中是否可以看到新表?

其他原因是 PostgreSQL 也使用事务来更改模式。因此,如果您禁用默认自动提交和关闭连接,您的架构更改将丢失。你用db.setAutoCommit(false)吗?

您也可以直接查询 PostgreSQL 架构:

SELECT DISTINCT table_name, column_name
FROM information_schema.columns
WHERE table_schema='public'
AND table_name = 'new_table'
ORDER BY 1, 2 

【讨论】:

您好,感谢您的回复。我已将 jdbc 驱动程序更新为您提到的驱动程序,但没有帮助。我使用相同的凭据来创建表和获取 te 列信息。 所以唯一的想法是在未提交的事务中创建表。 你在psql看到这张表吗? 我用 PostgreSQL 模式查询更新了我的答案。您可以将其添加到您的测试代码中,而不是查询元数据并向我们展示结果吗?【参考方案3】:

奇怪地将小写的表名传递给 getColumns 方法确实有效...感谢 Michał Niklas 的查询,它让我走上了正轨。

【讨论】:

哦,我曾经也遇到过这个问题 :-) 现在我只关心在表名或列名中使用小写字母。

以上是关于从 jdbc/postgresql 获取新创建表的列元数据的主要内容,如果未能解决你的问题,请参考以下文章

创建并写入数据库 JDBC PySpark

创建一个新表,其中第一行作为旧表的列名

从其他表的数据创建新表

片段中的Android ListView - 获取新数据后刷新表的问题

spring整合Mybatis | Postgresql为例

Jdbc Postgresql 没有执行查询