在 Liquibase 中,如何将新的 column/field 添加到现有的复合主键
In Liquibase, how to add a new column/field to an existing composite primary key
我们有一个 现有 table,其中有 2 个现有列用作复合主键。它们的设置与此非常相似:
<!-- WE CAN NO LONGER MODIFY THIS CHANGESET -->
<changeSet author="an_awesome_author" id="EXAMPLE-01">
<createTable tableName="our_awesome_table">
<column name="source" type="varchar(32)">
<constraints
primaryKey="true"
nullable="false"
primaryKeyName="CPK_OUR_AWESOME_TABLE"/>
</column>
<column
name="external_id"
type="varchar(255)">
<constraints
primaryKey="true"
nullable="false"
primaryKeyName="CPK_OUR_AWESOME_TABLE"/>
</column>
</createTable>
</changeSet>
随后我们注意到可以有多个记录具有相同的 source
& external_id
()。提交数据的小组定期提交,他们向我们保证他们绝不会在同一批数据中使用 source
和 external_id
的相同组合。
因此(出于超出此问题的原因)我们决定添加一个 created_at
字段,该字段不可为空,默认为每条记录添加到 table.这并不难,例如我们可以 运行 这对 changeSet
s
<!-- WE ARE TRYING TO FINALIZE THESE CHANGESETS -->
<changeSet author="yours_truly"
id="EXAMPLE-02-01">
<addColumn tableName="our_awesome_table">
<column name="CREATED_AT"
type="datetime"
valueDate="current_datetime"
defaultValueDate="current_datetime" />
<!-- the above:
adds the new field
sets the type
adds the current timestamp to existing records
will default to the current timestamp for new records
-->
</addColumn>
</changeSet>
<changeSet author="yours_truly"
id="EXAMPLE-02-02">
<addNotNullConstraint tableName="our_awesome_table"
columnName="CREATED_AT"/>
<!-- the above:
now that every record has a value in the newly created field,
we can add a constrant preventing null entries into the column
-->
</changeSet>
但是,我们还需要添加 created_at
到我们现有的复合主键!
如果我在创建字段时尝试将主键作为约束包括在内,它会抱怨 table 只能有一个主键 —尽管事实上它已经是一个复合键,我只是想将它添加到已经存在的复合键中。 但它也抱怨 created_at
时间戳为空。所以,我不确定哪个是真正的问题♂️,但它在这里肯定行不通。
例如
<changeSet author="yours_truly"
id="EXAMPLE-02-01">
<addColumn tableName="our_awesome_table">
<column name="CREATED_AT"
type="datetime"
valueDate="current_datetime"
defaultValueDate="current_datetime">
<constraints primaryKey="true"
primaryKeyName="PK_OUR_AWESOME_TABLE"/>
<!-- this constraints causes multiple problems -->
</column>
</addColumn>
</changeSet>
结果类似于:
[ERROR] Reason: liquibase.exception.DatabaseException: ORA-02260: table can have only one primary key
[ERROR] [Failed SQL: ALTER TABLE OUR_AWESOME_TABLE.OUR_AWESOME_TABLE ADD CREATED_AT TIMESTAMP DEFAULT SYSTIMESTAMP PRIMARY KEY NOT NULL]
如果我尝试将主键作为 <constraint>
包含在我们添加不可为空约束的 changeSet 中,那么我基本上被告知我不能在那里使用 <constraints>
并且相反需要 <addXxxConstraint>
列表之一,列表中有一个 <addPrimaryKey>
— 这听起来像是正确的约束。
因此,如果我将第二个 changeSet 更改为这样的内容,我希望它能正常工作:
<changeSet author="yours_truly"
id="EXAMPLE-02-02">
<addNotNullConstraint tableName="our_awesome_table"
columnName="CREATED_AT"/>
<addPrimaryKey tableName="our_awesome_table"
columnNames="CREATED_AT"
primaryKeyName="CPK_OUR_AWESOME_TABLE"/>
</changeSet>
但是 — 正如您可能猜到的那样 — 它不起作用。相反,它告诉我,cvc-complex-type.3.2.2: Attribute 'primaryKeyName' is not allowed to appear in element 'addPrimaryKey'.
那么,如何向现有的复合主键添加一个新的不可空字段?
addPrimaryKey-Type 没有 primaryKeyName 属性 - 可以通过 constraintName
.
设置约束的名称
但这行不通,因为您不能在 oracle 中更改主键。相反,您必须 drop the primary key (很可能是相应的索引),然后重新创建它,包括 columnNames
:
中您想要的列
<changeSet author="yours_truly"
id="EXAMPLE-02-02">
<addNotNullConstraint tableName="our_awesome_table"
columnName="CREATED_AT"/>
<dropPrimaryKey tableName="our_awesome_table"
dropIndex="true"
constraintName="CPK_OUR_AWESOME_TABLE"/>
<addPrimaryKey tableName="our_awesome_table"
columnNames="external_id, created_at"
constraintName="CPK_OUR_AWESOME_TABLE"/>
</changeSet>
我们有一个 现有 table,其中有 2 个现有列用作复合主键。它们的设置与此非常相似:
<!-- WE CAN NO LONGER MODIFY THIS CHANGESET -->
<changeSet author="an_awesome_author" id="EXAMPLE-01">
<createTable tableName="our_awesome_table">
<column name="source" type="varchar(32)">
<constraints
primaryKey="true"
nullable="false"
primaryKeyName="CPK_OUR_AWESOME_TABLE"/>
</column>
<column
name="external_id"
type="varchar(255)">
<constraints
primaryKey="true"
nullable="false"
primaryKeyName="CPK_OUR_AWESOME_TABLE"/>
</column>
</createTable>
</changeSet>
随后我们注意到可以有多个记录具有相同的 source
& external_id
(source
和 external_id
的相同组合。
因此(出于超出此问题的原因)我们决定添加一个 created_at
字段,该字段不可为空,默认为每条记录添加到 table.这并不难,例如我们可以 运行 这对 changeSet
s
<!-- WE ARE TRYING TO FINALIZE THESE CHANGESETS -->
<changeSet author="yours_truly"
id="EXAMPLE-02-01">
<addColumn tableName="our_awesome_table">
<column name="CREATED_AT"
type="datetime"
valueDate="current_datetime"
defaultValueDate="current_datetime" />
<!-- the above:
adds the new field
sets the type
adds the current timestamp to existing records
will default to the current timestamp for new records
-->
</addColumn>
</changeSet>
<changeSet author="yours_truly"
id="EXAMPLE-02-02">
<addNotNullConstraint tableName="our_awesome_table"
columnName="CREATED_AT"/>
<!-- the above:
now that every record has a value in the newly created field,
we can add a constrant preventing null entries into the column
-->
</changeSet>
但是,我们还需要添加 created_at
到我们现有的复合主键!
如果我在创建字段时尝试将主键作为约束包括在内,它会抱怨 table 只能有一个主键 —尽管事实上它已经是一个复合键,我只是想将它添加到已经存在的复合键中。 但它也抱怨 created_at
时间戳为空。所以,我不确定哪个是真正的问题♂️,但它在这里肯定行不通。
例如
<changeSet author="yours_truly"
id="EXAMPLE-02-01">
<addColumn tableName="our_awesome_table">
<column name="CREATED_AT"
type="datetime"
valueDate="current_datetime"
defaultValueDate="current_datetime">
<constraints primaryKey="true"
primaryKeyName="PK_OUR_AWESOME_TABLE"/>
<!-- this constraints causes multiple problems -->
</column>
</addColumn>
</changeSet>
结果类似于:
[ERROR] Reason: liquibase.exception.DatabaseException: ORA-02260: table can have only one primary key
[ERROR] [Failed SQL: ALTER TABLE OUR_AWESOME_TABLE.OUR_AWESOME_TABLE ADD CREATED_AT TIMESTAMP DEFAULT SYSTIMESTAMP PRIMARY KEY NOT NULL]
如果我尝试将主键作为 <constraint>
包含在我们添加不可为空约束的 changeSet 中,那么我基本上被告知我不能在那里使用 <constraints>
并且相反需要 <addXxxConstraint>
列表之一,列表中有一个 <addPrimaryKey>
— 这听起来像是正确的约束。
因此,如果我将第二个 changeSet 更改为这样的内容,我希望它能正常工作:
<changeSet author="yours_truly"
id="EXAMPLE-02-02">
<addNotNullConstraint tableName="our_awesome_table"
columnName="CREATED_AT"/>
<addPrimaryKey tableName="our_awesome_table"
columnNames="CREATED_AT"
primaryKeyName="CPK_OUR_AWESOME_TABLE"/>
</changeSet>
但是 — 正如您可能猜到的那样 — 它不起作用。相反,它告诉我,cvc-complex-type.3.2.2: Attribute 'primaryKeyName' is not allowed to appear in element 'addPrimaryKey'.
那么,如何向现有的复合主键添加一个新的不可空字段?
addPrimaryKey-Type 没有 primaryKeyName 属性 - 可以通过 constraintName
.
但这行不通,因为您不能在 oracle 中更改主键。相反,您必须 drop the primary key (很可能是相应的索引),然后重新创建它,包括 columnNames
:
<changeSet author="yours_truly"
id="EXAMPLE-02-02">
<addNotNullConstraint tableName="our_awesome_table"
columnName="CREATED_AT"/>
<dropPrimaryKey tableName="our_awesome_table"
dropIndex="true"
constraintName="CPK_OUR_AWESOME_TABLE"/>
<addPrimaryKey tableName="our_awesome_table"
columnNames="external_id, created_at"
constraintName="CPK_OUR_AWESOME_TABLE"/>
</changeSet>