尝试在 H2 数据库中创建表时出现 Liquibase 错误

Posted

技术标签:

【中文标题】尝试在 H2 数据库中创建表时出现 Liquibase 错误【英文标题】:Getting Liquibase error when trying to create a table in a H2 database 【发布时间】:2015-10-24 17:50:35 【问题描述】:

如何使用 Liquibase 在 H2 内存数据库中创建表?我正在使用 Gradle 2.7、Liquibase 1.1.1 插件和 H2 1.4.190 插件。这是我的 Liquibase 创建表语句……

    <changeSet author="davea" id="add_my_prefix_sync_address">
            <createTable tableName="my_prefix_sync_address">
        <column defaultValue="" name="id" type="VARCHAR(32)">
            <constraints nullable="false" primaryKey="true"/>
        </column>
        <column defaultValue="" name="address" type="VARCHAR(500)">
            <constraints nullable="true"/>
        </column>
        <column defaultValue="" name="city" type="VARCHAR(100)">
            <constraints nullable="true"/>
        </column>
        <column defaultValue="" name="state" type="VARCHAR(10)">
            <constraints nullable="true"/>
        </column>
        <column defaultValue="" name="zip" type="VARCHAR(10)">
            <constraints nullable="true"/>
        </column>
        <column defaultValue="" name="lattitude" type="INT UNSIGNED">
            <constraints nullable="true"/>
        </column>
        <column defaultValue="" name="longitude" type="INT UNSIGNED">
            <constraints nullable="true"/>
        </column>
        <column defaultValue="" name="email" type="VARCHAR(200)">
            <constraints nullable="true"/>
        </column>
        <column defaultValue="" name="phone" type="VARCHAR(32)">
            <constraints nullable="true"/>
        </column>
        <column defaultValue="" name="phone_type" type="VARCHAR(10)">
            <constraints nullable="true"/>
        </column>
            </createTable>
    </changeSet>

但是在运行我的 Grade build 命令时,我收到了这个错误……

Execution failed for task ':update'.
> liquibase.exception.LiquibaseException: Unexpected error running Liquibase: org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement "CREATE TABLE PUBLIC.my_prefix_SYNC_ADDRESS (ID VARCHAR(32) DEFAULT '' NOT NULL, ADDRESS VARCHAR(500) DEFAULT '', CITY VARCHAR(100) DEFAULT '', STATE VARCHAR(10) DEFAULT '', ZIP VARCHAR(10) DEFAULT '', LATTITUDE INT UNSIGNED DEFAULT ,[*] LONGITUDE INT UNSIGNED DEFAULT , EMAIL VARCHAR(200) DEFAULT '', PHONE VARCHAR(32) DEFAULT '', PHONE_TYPE VARCHAR(10) DEFAULT '', CONSTRAINT PK_my_prefix_SYNC_ADDRESS PRIMARY KEY (ID)) "; expected "NOT, EXISTS, INTERSECTS, SELECT, FROM"; SQL statement:
  CREATE TABLE PUBLIC.my_prefix_sync_address (id VARCHAR(32) DEFAULT '' NOT NULL, address VARCHAR(500) DEFAULT '', city VARCHAR(100) DEFAULT '', state VARCHAR(10) DEFAULT '', zip VARCHAR(10) DEFAULT '', lattitude INT UNSIGNED DEFAULT , longitude INT UNSIGNED DEFAULT , email VARCHAR(200) DEFAULT '', phone VARCHAR(32) DEFAULT '', phone_type VARCHAR(10) DEFAULT '', CONSTRAINT PK_my_prefix_SYNC_ADDRESS PRIMARY KEY (id)) [42001-190]

如果重要的话,这些是我在 build.grade 脚本中设置的插件……

buildscript 
  repositories 
    mavenCentral()
  
  dependencies 
    classpath 'mysql:mysql-connector-java:5.1.36'
    classpath 'com.h2database:h2:1.4.190'
    classpath 'org.flywaydb:flyway-gradle-plugin:3.2.1'
  


…
plugins 
  id "org.liquibase.gradle" version "1.1.1"


…

flyway 
    url = 'jdbc:h2:mem:test'
    user = 'sa'


liquibase 
  activities 
    main 
      File propsFile = new File(liquibasePropertiesFile)
      Properties properties = new Properties()
      properties.load(new FileInputStream(propsFile))
      changeLogFile 'src/main/resources/db.changelog-master.xml'
      url properties['url']
      username properties['username']
      password properties['password']
    
    test 
      File propsFile = new File(liquibasePropertiesFile)
      Properties properties = new Properties()
      properties.load(new FileInputStream(propsFile))
      changeLogFile 'src/main/resources/db.changelog-master.xml'
        url 'jdbc:h2:mem:test'
        username 'sa'
    
    runList = 'main,test'
  

【问题讨论】:

【参考方案1】:

也许使用 varchar(32) 列作为主键是不合法的。

【讨论】:

你是在问我还是告诉我?文档中没有关于这种限制的任何内容。 我不知道H2的细节,所以这是一个建议。我会尝试运行在其他一些 SQL 工具中生成的 SQL,看看 H2 是怎么说的。 在 H2 中运行该 SQL 会产生相同的结果。我的问题是我需要对我的 Liquibase changeSet 或 Gradle/H2 生成中的配置进行哪些更改才能使 changeSet 正确处理。 如果你能提供正确的 SQL,那可能是错误报告的基础。 发生的事情是数字列 () 的 'defaultValue=""' 导致生成 SQL作为“DEFAULTVALUE”(对于字符串,它将是“DEFAULTVALUE ''”)。不确定这是否是 Liquibase 错误,但很容易在脚本中清理。

以上是关于尝试在 H2 数据库中创建表时出现 Liquibase 错误的主要内容,如果未能解决你的问题,请参考以下文章

在 sqlite 数据库中创建表时出现语法错误

为啥我不能在我的 H2 数据库中创建表?

防止用户在 H2 中创建表

无法使用 JPA 在 H2 中创建表和加载数据

尝试从 Oracle 导入到 H2 时出现 Temenos DBImport 错误

尝试使用 H2 数据库更新 JDBC ResultSet 时出现异常