我正在用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>
答案 0 :(得分:5)
我找到的解决方案似乎有效:
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);
}
我必须将IF NOT EXISTS
放在我的SQL语句中的正确位置。
答案 1 :(得分:3)
来自Java docs的ResultSet
定义:
ResultSet对象维护一个指向其当前行的光标 数据。最初,光标位于第一行之前。该 next方法将光标移动到下一行,因为它返回 当ResultSet对象中没有更多行时,它可以是false 在while循环中用于迭代结果集。
因此,您必须始终调用next()
方法,否则getRow()
将始终返回零,因为光标位于第一行之前。
答案 2 :(得分:1)
为您所寻求的内容构建了mysql功能:http://dev.mysql.com/doc/refman/5.0/en/create-table.html
简而言之:只需在表创建查询的末尾添加IF NOT EXISTS
。
编辑:
没有一般的方法可以做到这一点。大多数数据库都有一个information_scheme表,但确定信息的查询可能如下所示:
SELECT count(*)
FROM information_schema.system_tables
WHERE table_schem = 'public' AND table_name = 'user';
这适用于sqlite,mysql,msql,mariadb和postgres +可能很多其他人。
答案 3 :(得分:-2)
我不知道这是否一定会对你的目标有所帮助,但是当我使用Python和MySQL遇到这个问题时,我只是在每个“Create Table”语句之前添加了一个“Drop Table”语句,这样才会运行该脚本会自动删除现有表,然后重建每个表。这可能不适合您的需求,但这是我为类似问题找到成功的解决方案。