【发布时间】:2012-08-10 21:11:52
【问题描述】:
我正在用 Java 编写一个数据库程序,如果它不存在,我想创建一个表。我从How can I detect a SQL table's existence in Java? 了解到DatabaseMetaData.getTables(),我正在尝试使用它:
private boolean tableExists() throws SQLException {
System.out.println("tableExists()");
DatabaseMetaData dbmd = conn.getMetaData();
ResultSet rs = dbmd.getTables(null, null, this.getTableName(), null);
System.out.println("TABLE_NAME: " + rs.getString("TABLE_NAME"));
return rs.getRow() == 1;
}
问题是rs.getRow() 总是返回0,即使在表创建之后也是如此。使用rs.getString("TABLE_NAME") 会引发异常,指出结果集为空。
我想到的一个可能的解决方案是执行CREATE TABLE 语句并捕获任何抛出的异常。但是,我不喜欢在程序的控制流中使用异常的想法。
FWIW,我正在使用 HSQLDB。但是,我想编写独立于 RDMS 引擎的 Java 代码。还有其他方法可以使用DatabaseMetaData.getTables() 来做我想做的事吗?还是有其他解决方案来编写我的tableExists() 方法?
添加:
使用此处给出的建议,我找到了一个似乎适用于我的生产代码的解决方案:
private void createTable() throws SQLException {
String sqlCreate = "CREATE TABLE IF NOT EXISTS " + this.getTableName()
+ " (brand VARCHAR(10),"
+ " year INTEGER,"
+ " number INTEGER,"
+ " value INTEGER,"
+ " card_count INTEGER,"
+ " player_name VARCHAR(50),"
+ " player_position VARCHAR(20))";
Statement stmt = conn.createStatement();
stmt.execute(sqlCreate);
}
现在我也在编写一个 JUnit 测试来断言该表确实已创建:
public void testConstructor() throws Exception {
try (BaseballCardJDBCIO bcdb = new BaseballCardJDBCIO(this.url)) {
String query = "SELECT count(*) FROM information_schema.system_tables WHERE table_name = '" + bcdb.getTableName() + "'";
Connection conn = DriverManager.getConnection(this.url);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query);
Assert.assertTrue(rs.next());
Assert.assertEquals(1, rs.getInt(1));
Assert.assertFalse(rs.next());
}
}
此测试在 assertEquals() 上失败,并显示以下消息:
FAILED: expected: <1> but was: <0>
【问题讨论】:
-
嗨,为什么不直接使用 SQL CREATE TABLE name IF NOT EXISTS (...) 呢?它更容易,如果表已经存在,则将其保留在
-
@bali182 感谢您的建议。正确的语法是
CREATE TABLE IF NOT EXISTS <name> (<columns>)。现在我也在写一个 JUnit 测试。如果你有时间,一些帮助会很棒! -
我打赌你没有
information_schema架构的读取权限(或者它不存在) -
@AlonsoDominguez 明天我有更多时间时会研究一下。