【问题标题】:H2: how to tell if table exists?H2:如何判断表是否存在?
【发布时间】:2013-10-31 08:19:19
【问题描述】:

我正在尝试编写检查 H2 表是否存在的 Java 代码:如果它不存在,它首先执行一个 CREATE TABLE 查询,该查询在继续进行之前创建该表。

我遵循了this Google Groups question 中的建议,但它根本不起作用。

如果我运行以下查询:

SELECT COUNT(*) AS count FROM information_schema.tables WHERE table_name = 'word_types'

我返回了一个带有 COUNT 字段的单行,其值为 0;这表明word_types 表不存在。但是当我运行时:

SELECT * FROM word_types

我得到了 0 个结果集,但我使用的 SQL 前端/GUI 向我显示了 word_types 表中存在的所有字段/列。此外,当我深入了解数据库的可用表列表(使用相同的 GUI)时,我看到 word_types 存在。

那么,在尝试确定 H2 表是否存在时,正确的查询是什么? 使用 v1.3.173。提前致谢!

【问题讨论】:

  • 查询系统表时可能是大写/小写问题。用lower函数再试一次。
  • 为什么不使用CREATE TABLE IF NOT EXIST myTable?你的逻辑是什么,你每次在查询前检查还是在应用程序启动时检查一次?
  • 你的方法对我来说运行良好 - 如果第一个查询返回 0,那么第二个查询会给出错误代码 Table doesn't exist
  • 谢谢@DanBracuk (+1) - 我应该在哪里应用较低的功能?你能提供一个代码示例吗?再次感谢!
  • 谢谢@Admit (+1) - 不错的建议,如果这里所有其他方法都失败了,我可能会接受。我的逻辑是在应用启动时检查一次。

标签: java sql jdbc h2


【解决方案1】:
    Connection con = getConnection();
    Boolean tableExist = false;
    PreparedStatement preparedStatement = con.prepareStatement("SHOW TABLES FROM INFORMATION_SCHEMA");
        Boolean rq = preparedStatement.execute();
        if(rq) {
                ResultSet rs = preparedStatement.getResultSet();
                while (rs.next()) {
                    if(rs.getString(rs.getRow()).equals("WORD_TYPES")) {
                        isExist = true;
                        break;
                }
            }
        }

【讨论】:

    【解决方案2】:

    还有一个 JDBC API,您可以使用它来查询一个或多个表的存在。 这(理论上)比使用information_schema 的直接查询更便携。

    (实际上,由于不同的 DBMS 定义和使用概念架构和目录略有不同这一事实,可移植性仍然受到一定限制)。

    这就是它的工作原理:

    boolean tableExists = false;
    
    Connection conn = getConnection(); // get a DB connection from somewhere
    ResultSet rset = conn.getMetaData().getTables(null, null, "WORD_TYPES", null);
    if (rset.next())
    {
      tableExists = true;
    }
    

    除了"WORD_TYPES",您还可以使用 SQL 风格的通配符,例如"WORD_%".

    请注意,H2 有一个配置设置 DATABASE_TO_UPPER,默认情况下设置为 true。因此,任何表名都会转换为大写,这就是为什么您需要以大写形式查询表(或将DATABASE_TO_UPPER 设置为false)。

    另外,使用其他参数(我在这里设置为null),您可以进一步将搜索范围限制为特定的场景或表类型。

    如果您需要,结果集还包含有关表的元信息,例如架构或表注释。

    有关选项和可用元数据的完整列表,请参阅JavaDoc

    【讨论】:

    • ResultSet rset = conn.getMetaData().getTables(null, null, "WORD_TYPES", null)) 总是为我返回 null ......
    【解决方案3】:

    首先:检查您输入表格名称的大小写。这很重要。 word_typesWORD_TYPES 是两个不同的表。
    第二个:如果要检查表是否存在,如果不存在则创建一个,我建议您使用以下示例:

    CREATE TABLE IF NOT EXISTS TEST(ID INT PRIMARY KEY, NAME VARCHAR(255));
    

    【讨论】:

    • 你成功了@qiGuar (+1) - 这是一个外壳问题。创建表时,我将表名指定为word_types。当我运行SELECT * FROM word_types 时,我看到该表存在但没有行返回(这是正确的,我还没有在其中插入任何内容)。但是我必须在检查information_schema.tables 表是否存在我的word_types 表的查询中将表名指定为WORD_TYPES。很奇怪。
    • 这是因为information_schema.tables中的表名以大写形式存储,命令区分大小写。但我不能告诉你为什么名称会以这种方式存储。
    • 未加引号的表名通常不区分大小写,但它们在大多数数据库中始终以相同的大小写存储(通常为大写,有时为小写)。
    • 看我的回答。有一个配置设置 DATABASE_TO_UPPER 负责此行为,因为它默认设置为 TRUE
    【解决方案4】:

    您的上述查询将返回您的表不存在的记录数,因为您必须触发以下查询。此查询将返回您数据库的所有表,然后您可以从那里检查您的“word_types”是否存在。

    使用您的数据库名称 走 选择 * FROM 系统表 去吧

    如果它有效或无效也回复我

    【讨论】:

    • 请使用编辑器上的代码示例按钮来标记sql语句、代码示例等。您可以使用按钮编辑您的答案,它有助于编写更具可读性的答案。
    • 感谢@Rohit Goyla (+1) - 但是当我尝试您的 SQL 时出现以下错误:Error: Syntax error in SQL statement "USE[*] MYAPP_DB GO SELECT * FROM SYS.TABLES GO "; expected "UPDATE, {"; SQL statement: USE myapp_db GO SELECT * FROM sys.Tables GO [42001-173] SQLState: 42001 ErrorCode: 42001
    • 据我所知,USE YOURDBNAME 语句适用于 Microsoft SQL Server。不过,问题是针对H2 database
    【解决方案5】:

    如果第二个查询没有抛出异常或返回任何行,则表示该表存在但为空。

    【讨论】:

      猜你喜欢
      • 2023-03-19
      • 2013-05-12
      • 2021-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-05
      • 2010-12-30
      相关资源
      最近更新 更多