【问题标题】:Liquibase createTable with autoIncrement column generates different SQL for Oracle 11g and 12c具有 autoIncrement 列的 Liquibase createTable 为 Oracle 11g 和 12c 生成不同的 SQL
【发布时间】:2017-12-15 17:48:56
【问题描述】:

这是我的第一个问题,所以请保持温和;-)。

我们有一个带有以下变更集的 liquibase 项目:

<changeSet author="Me" id="db.changelog-master-1">
  <preConditions onFail="MARK_RAN">
    <not>
      <tableExists tableName="table_x" />
    </not>
  </preConditions>
  <createTable remarks="Groep" tableName="table_x">
    <column autoIncrement="true" name="id" type="${serial}">
      <constraints primaryKey="true" primaryKeyName="table_x_pk" />
    </column>
    <column name="indsync" type="varchar(5)">
      <constraints nullable="false" />
    </column>
    <column name="code" type="varchar(10)" />
    <column defaultValue="2" name="code_n" type="char(1)">
      <constraints nullable="false" />
    </column>
    <column name="description" type="varchar(80)" />
    <column defaultValue="2" name="description_n" type="char(1)">
      <constraints nullable="false" />
    </column>
  </createTable>

启动我们使用 Oracle 11g 的应用程序时,创建的表如下所示:

  CREATE TABLE "SOMETHING"."TABLE_X" 
   (  "ID" NUMBER(*,0) NOT NULL ENABLE, 
   "INDSYNC" VARCHAR2(5 CHAR) NOT NULL ENABLE, 
   "CODE" VARCHAR2(10 CHAR), 
   "CODE_N" CHAR(1 CHAR) DEFAULT '2' NOT NULL ENABLE, 
   "DESCRIPTION" VARCHAR2(80 CHAR), 
   "DESCRIPTION_N" CHAR(1 CHAR) DEFAULT '2' NOT NULL ENABLE, 
    CONSTRAINT "TABLE_X_PK" PRIMARY KEY ("ID")
  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT)
  TABLESPACE "SOMETHING"  ENABLE
   ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
 NOCOMPRESS LOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT)
  TABLESPACE "SOMETHING" ;

   COMMENT ON TABLE "SOMETHING"."TABLE_X"  IS 'Groep';

  CREATE OR REPLACE TRIGGER "SOMETHING"."TABLE_X_BI" before insert on table_x for each row  WHEN (new.id is null) begin select table_x_seq.nextval into :new.id from dual; end;
/
ALTER TRIGGER "SOMETHING"."TABLE_X_BI" ENABLE;

这按预期工作,并且将 sequence.nextval 插入到 id 列中。 但是在启动我们使用 Oracle 12c 的应用程序时,创建的表如下所示:

 CREATE TABLE "SOMETHING"."TABLE_X" 
   (  "ID" NUMBER(*,0) GENERATED BY DEFAULT AS IDENTITY MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER  NOCYCLE  NOT NULL ENABLE, 
   "INDSYNC" VARCHAR2(5 CHAR) NOT NULL ENABLE, 
   "CODE" VARCHAR2(10 CHAR), 
   "CODE_N" CHAR(1 CHAR) DEFAULT '2' NOT NULL ENABLE, 
   "DESCRIPTION" VARCHAR2(80 CHAR), 
   "DESCRIPTION_N" CHAR(1 CHAR) DEFAULT '2' NOT NULL ENABLE, 
    CONSTRAINT "TABLE_X_PK" PRIMARY KEY ("ID")
  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "SOMETHING"  ENABLE
   ) SEGMENT CREATION IMMEDIATE 
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
 NOCOMPRESS LOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "SOMETHING" ;

   COMMENT ON TABLE "SOMETHING"."TABLE_X"  IS 'Groep';

  CREATE OR REPLACE EDITIONABLE TRIGGER "SOMETHING"."TABLE_X_BI" before insert on table_x for each row  WHEN (new.id is null) begin select table_x_seq.nextval into :new.id from dual; end;
/
ALTER TRIGGER "SOMETHING"."TABLE_X_BI" ENABLE;

12c 创建的表的问题在于,序列的值永远不会用于列 ID,因为它不会为空,因为“GENERATED BY DEFAULT AS IDENTITY MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE NOT NULL ENABLE"

id 字段在每次插入时递增,但不使用序列。

我的问题是,经过一段时间和几次 changeSet 之后,我们擦除 table_x 的内容,删除序列并重新创建它以重新开始。 这在使用 oracle 11g 时非常有效,但在 12c 中却不行。 12c 中的 id 字段一直在递增并且不会被重置,这会在启动我们的应用程序时导致问题。

我需要做什么才能在 oracle 12c 上拥有与 11g 上相同的 createTable 定义?

格兹,

莱克斯

编辑1:我们使用的liquibase版本是3.4.2(maven依赖org.liquibase:liquibase-core)

编辑 2:根据@SteveDonie 的要求, ${serial} 定义如下:

<property name="serial" value="numeric(*,0)" dbms="oracle"/>
<property name="serial" value="serial" dbms="postgresql"/>
<property name="serial" value="int(10) UNSIGNED" dbms="mysql"/>

对于 Oracle,只有一个定义用于两个版本。

【问题讨论】:

  • 您的变更集提到了一个参数 ${serial} - 这两个平台的设置是否不同?
  • 嗨@SteveDonie,我用请求的信息修改了问题。
  • 我在 [here][1] 中读到了 12c 中关于标识列的更改,但它也指出旧式基于触发器的解决方案仍然有效,但执行较少。 [1]:oracle-base.com/articles/12c/identity-columns-in-oracle-12cr1

标签: oracle11g java-8 liquibase oracle12c


【解决方案1】:

您是否尝试过 ID 字段的defaultValueComputed 标签?

<changeSet id="table_x_seq_create" author="takacsl">
    <createSequence cacheSize="2000" cycle="false" incrementBy="1" sequenceName="SEQ_TABLE_X" startValue="1"/>
</changeSet>
<changeSet id="table_x_create" author="takacsl">
  <createTable remarks="Groep" tableName="table_x">
    <column name="id" type="integer" defaultValueComputed="nextval('SEQ_TABLE_X')>
      <constraints primaryKey="true"  />
    </column>
    <column name="indsync" type="varchar(5)">
      <constraints nullable="false" />
    </column>
    <column name="code" type="varchar(10)" />
    <column defaultValue="2" name="code_n" type="char(1)">
      <constraints nullable="false" />
    </column>
    <column name="description" type="varchar(80)" />
    <column defaultValue="2" name="description_n" type="char(1)">
      <constraints nullable="false" />
    </column>
  </createTable>
</changeSet>

另一个更复杂的解决方法是使用自定义构建器类覆盖 sql 代码生成。

【讨论】:

    猜你喜欢
    • 2016-04-09
    • 2020-06-10
    • 2014-10-03
    • 2017-01-27
    • 1970-01-01
    • 2020-08-02
    • 1970-01-01
    • 2016-05-20
    • 2020-10-23
    相关资源
    最近更新 更多