我的 SQL Server 数据库中有以下索引
CREATE NONCLUSTERED INDEX XCR_ACTIVE ON dbo.CS_PA_VEH_BASE ( ETL_ACTIVE_FL )
WHERE ETL_ACTIVE_FL = 'N' ON "default";
其中 liquibase
给出以下内容:
<createIndex indexName="XCR_ACTIVE" tableName="CS_PA_VEH_DELTA">
<column computed="true" name="([ETL_ACTIVE_FL]='N')"/>
</createIndex>
但是当我想执行它时(也在 MS SQL Server 中)我得到以下内容
> **Error:** (14.2) 05-24-19 11:43:05 (E) (13004:15088) RUN-050304: |Session JOB_ODS_Liquibase Function call <raise_exception ( Liquibase
> update error: 1: Unexpected error running Liquibase: Incorrect syntax
> near '('. [Failed SQL: CREATE NONCLUSTERED INDEX XCR_ACTIVE ON
> [dbo].[CS_PA_VEH_DELTA](([ETL_ACTIVE_FL]='N'))] ) > failed, due to
> error <50316>: <Liquibase update error:-1: Unexpected error running
> Liquibase: Incorrect syntax near '('. [Failed SQL: CREATE NONCLUSTERED
> INDEX XCR_ACTIVE ON [dbo].[CS_PA_VEH_DELTA](([ETL_ACTIVE_FL]='N'))]>.
我希望这不是第一次发生在某人身上。
最佳答案
正如您在 answer 中提到的,Liquibase 中不支持部分/条件/过滤索引。
您尝试做的是使用compated
属性来设置过滤器的条件。 Documentation对于计算状态:
The attribute to set to true if the value in name isn't actually a column name but a function. Boolean.
因此,仅当您想以编程方式命名要索引的列时才使用它。因此,您必须使用纯 SQL
或 modifySql
。
修改Sql
使用modifySql
,您可以在生成的语句之前或之后附加 SQL,或者替换其中的部分内容。如果我们尝试使用追加,它将如下所示:
<changeSet id="create-an-index-modifySql" author="potato">
<createIndex tableName="CS_PA_VEH_BASE"
indexName="XCR_ACTIVE"
clustered="false">
<column name=ETL_ACTIVE_FL>
</createIndex>
<modifySql>
<append value="WHERE ETL_ACTIVE_FL = 'N'">
</modifySql>
</changeSet>
这将产生以下sql语句:
CREATE NONCLUSTERED INDEX XCR_ACTIVE ON CS_PA_VEH_BASE ( ETL_ACTIVE_FL )
WHERE ETL_ACTIVE_FL = 'N';
这种方法的问题是使用tablespace
属性时; WHERE
将附加在 ON tablespace
之后。示例:
<changeSet id="create-an-index-modifySql" author="potato">
<createIndex tableName="CS_PA_VEH_BASE"
indexName="XCR_ACTIVE"
tablespace="default"
clustered="false">
<column name=ETL_ACTIVE_FL>
</createIndex>
<modifySql>
<append value="WHERE ETL_ACTIVE_FL = 'N'">
</modifySql>
</changeSet>
CREATE NONCLUSTERED INDEX XCR_ACTIVE ON CS_PA_VEH_BASE ( ETL_ACTIVE_FL )
ON default WHERE ETL_ACTIVE_FL = 'N';
语法错误。
解决方案是将 modifySql
与 replace
和 with
属性一起使用:
<changeSet id="create-an-index-modifySql" author="potato">
<createIndex tableName="CS_PA_VEH_BASE"
indexName="XCR_ACTIVE"
tablespace="default"
clustered="false">
<column name=ETL_ACTIVE_FL>
</createIndex>
<modifySql>
<append replace="ON default" with="WHERE ETL_ACTIVE_FL = 'N' ON default">
</modifySql>
</changeSet>
CREATE NONCLUSTERED INDEX XCR_ACTIVE ON CS_PA_VEH_BASE ( ETL_ACTIVE_FL )
WHERE ETL_ACTIVE_FL = 'N' ON default;
虽然正确,但我认为它太繁琐并且容易出错。
纯 SQL
最安全的选择是使用 sql
标记创建一个 changeSet
,如下所示:
<changeSet id="create-an-index-pure-sql" author="potato">
<sql>
CREATE NONCLUSTERED INDEX XCR_ACTIVE
ON dbo.CS_PA_VEH_BASE (ETL_ACTIVE_FL)
WHERE ETL_ACTIVE_FL = 'N' ON "default";
</sql>
</changeSet>
虽然它不符合 Liquibase 的精神,但我认为它对于过滤索引来说是足够好的解决方案。
关于sql-server - 为条件索引生成的 Liquibase 代码在 MS SQL Server 中给出错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56323977/