【问题标题】:Liquibase - insert rows with uuidLiquibase - 使用 uuid 插入行
【发布时间】:2017-07-10 17:21:33
【问题描述】:

我有两个表声明如下:

<changeSet author="istvan" id="country-table-changelog">
    <createTable tableName="country">
        <column name="id" type="uuid">
            <constraints nullable="false" unique="true" />
        </column>
        <column name="name" type="varchar">
            <constraints nullable="false" unique="true" />
        </column>
    </createTable>
</changeSet>

<changeSet author="istvan" id="region-table-changelog">
    <createTable tableName="region">
        <column name="id" type="uuid" >
            <constraints nullable="false" unique="true" />
        </column>
        <column name="country_id" type="uuid">
            <constraints nullable="false" />
        </column>
        <column name="name" type="varchar">
            <constraints nullable="false" unique="true" />
        </column>
    </createTable>
</changeSet>

<changeSet author="istvan" id="region-country-foreign-key-constraint">
    <addForeignKeyConstraint 
        baseTableName="region"
        baseColumnNames="country_id"
        referencedTableName="country"
        referencedColumnNames="id"
        constraintName="fk_region_country"
        onDelete="CASCADE" 
        onUpdate="RESTRICT"/>
</changeSet>

我想从 liquibase 更改日志文件中填写两个表,其中包含以下值:

INSERT INTO country VALUES('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'HUNGARY');
INSERT INTO region VALUES('bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'Baranya');

在示例中,我使用 aaaa's 和 bbbb's 只是因为简单。我想通过 DBMS 生成这些 UUID。

最好的方法是什么?我必须在我的变更日志文件中使用 SQL,还是可以使用 XML?我更喜欢 XML 或 JSON 等独立于 DBMS 的解决方案。

我的第二个问题是如何声明一个带有 UUID 的列,该列在插入时创建 UUID。比如:

<column name="id" type="uuid" value="??? GENERATE UUID ???">
    <constraints nullable="false" unique="true" />
</column>

感谢您的宝贵时间!

【问题讨论】:

    标签: sql liquibase


    【解决方案1】:

    您可以使用根据当前 DBMS 定义的属性来执行此操作。

    <property name="uuid_type" value="uuid" dbms="postgresql"/>
    <property name="uuid_type" value="uniqueidentifier" dbms="mssql"/>
    <property name="uuid_type" value="RAW(16)" dbms="oracle"/>
    
    <property name="uuid_function" value="uid.uuid_generate_v4()" dbms="postgresql"/>
    <property name="uuid_function" value="NEWID()" dbms="mssql"/>
    <property name="uuid_function" value="sys_guid()" dbms="oracle"/>
    

    然后在定义表格时使用这些属性:

    <column name="id" type="${uuid_type}" defaultValueComputed="${uuid_function}">
        <constraints nullable="false" unique="true" />
    </column>
    

    注意需要使用defaultValueComputed不是value

    如果该列是用默认值定义的,只需将其留在插入语句中,然后数据库将在插入时生成 UUID。

    【讨论】:

    • 第一部分有效。它使用919d39e4-2387-4926-91d5-595ebe0eea07 id 插入匈牙利。但是,对于第二次插入,它给出了以下异常:ERROR: insert or update on table "region" violates foreign key constraint "fk_region_country" Key (country_id)=(34e4e0d8-91d8-4d52-99ae-ec42d6b0e66e) is not present in table "country"。外键的用法很清楚,但我不知道如何在 liquibase 中使用它。这是我使用的代码:&lt;column name="country_id" type="${uuid_type}" defaultValueComputed="${uuid_function}"&gt; &lt;constraints nullable="false" /&gt; &lt;/column&gt;Thx
    • @FarkasIstván - 我收到了同样的错误。希望我能尽快找到答案,但与此同时,如果你知道了,请告诉我。
    • 对于 Oracle,不应该是 RAW(16) 而不是 RAW(32) 吗? (是的,Oracle 曾经在其在线文档中存在这方面的错误,但已得到纠正)。见docs.oracle.com/database/121/SQLRF/functions202.htm#SQLRF06120
    【解决方案2】:

    对于 MySQL,将您的属性放在 changeSet 标记之前:

        <property name="u_id" value="uuid()" dbms="mysql"/>
    

    然后

        <column name="ID" type="varchar(255)" valueComputed="${u_id}"/>
    

    注意:这里使用的是valueComputed,而不是defaultValueComputed

    【讨论】:

      【解决方案3】:

      部分数据库支持 UUID 列:Generate UUID values by default for each row on column of UUID type in H2 Database Engine

      我认为 Liquibase 没有嵌入 UUID 生成器,请查看列 (http://www.liquibase.org/documentation/column.html) 的 defaultValueComputed/valueComputed 属性 + 生成 UUID 的 DB 函数

      【讨论】:

        【解决方案4】:

        就像 Rammgarot 指出的那样,由于我们正在处理需要具有唯一值的列,因此我们应该使用 valueComputed 而不是 defaultValueComputed

        【讨论】:

          【解决方案5】:

          任何提供的答案都对我没有帮助如果是 MySQL,但我能够使用另一种方法 - 使用触发器来解决它。

          <changeSet author="nberezovski" id="1">
                  <createTable tableName="test">
                      <column name="id" type="varchar(255)">
                          <constraints primaryKey="true" nullable="false"/>
                      </column>
                      <column name="description" type="varchar(255)">
                      ...
                  </createTable>
          </changeSet>
          
          <changeSet author="nberezovski" id="2">
                  <sql splitStatements="false">
                      CREATE TRIGGER insert_test
                      BEFORE INSERT ON test
                      FOR EACH ROW
                      BEGIN
                      IF (NEW.id IS NULL) THEN
                      SET NEW.id = UUID();
                      END IF;
                      END;
                  </sql>
          </changeSet>
          

          之后,每次手动插入 description 的值时,MySQL 都会自动为我生成一个 id。例如:

          insert into test(description) values('some description');
          

          这种方法也有助于使用 loadData 加载数据

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2022-01-10
            • 1970-01-01
            • 2019-03-08
            • 2019-11-12
            • 2015-07-27
            • 1970-01-01
            • 2012-02-23
            • 1970-01-01
            相关资源
            最近更新 更多