我在SO上遇到了这个例子,它给出了一个通过忽略空值来创建唯一索引的解决方案.但是,我想扩展它,我无法达成解决方案.
我有一个表的3列的复合索引(表中还有其他10列).这些列不是PK的一部分.在这3列中,2将始终保留一些值,第3列可能为NULL.我有大量的测试数据,并且有许多插入,其中2列具有相同的值,第3列为NULL.这些所有插件都适用于PostgreSQL,但Oracle抱怨道.为了让我的测试用例工作,我认为我认为最简单的解决方案是尝试一个独特的Oracle索引,它可以在PostgreSQL中运行.
确切地说:我想要一种以下类型的结构,不确定如何结合 col1 + col2 + col3
create unique index tbl_idx on tbl (nvl2(col3, col1 + col2, col1 + col2 + col3))
我正在使用liquibase.索引以下列方式创建 -
<changeSet dbms="postgresql,oracle" author="abc" id="222">
    <createIndex indexName="Index_7" schemaName="ss" tableName="Users" unique="true">
        <column name="idOrganization"/>
        <column name="strUsername"/>
        <column name="strNotDeleted"/>
    </createIndex>
</changeSet>
我使用liquibase来创建我的测试数据,这里有两个插入语句
<insert schemaName="ss" tableName="Users">
    <column name="strUsername" value="user1" />
    <column name="idUser" valueNumeric="20741" />
    <column name="idOrganization" valueNumeric="4" />
    <column name="strFirstName" value="user" />
    <column name="strLastName" value="one" />
    <column name="strEmail" value="email@foo.com" />
    <column name="strNotDeleted" />
</insert>
<insert schemaName="ss" tableName="Users">
    <column name="strUsername" value="user1" />
    <column name="idUser" valueNumeric="20771" />
    <column name="idOrganization" valueNumeric="4" />
    <column name="strFirstName" value="user" />
    <column name="strLastName" value="one" />
    <column name="strEmail" value="email@foo.com" />
    <column name="strNotDeleted" />
</insert>
这两个插件适用于PostgreSQL,但是Oracle失败并出现"Index_7约束违规"错误.
Jus*_*ave 10
如果目标只是为了防止重复strNotDeleted设置为非NULL值,那么你想要一个像这样的基于函数的索引
SQL> create table users(
  2    idOrganization number,
  3    strUsername    varchar2(100),
  4    strNotDeleted  varchar2(3)
  5  );
Table created.
SQL> create unique index idx_users
  2      on users( (case when strNotDeleted is not null
  3                      then idOrganization
  4                      else null
  5                  end),
  6                (case when strNotDeleted is not null
  7                      then strUsername
  8                      else null
  9                 end) );
Index created.
这允许插入您在问题中提到的两行
SQL> insert into users values( 4, 'user', null );
1 row created.
SQL> insert into users values( 4, 'user', null );
1 row created.
您可以在strNotNull列设置为非NULL值的位置插入一行
SQL> insert into users values( 4, 'user', 'Yes' );
1 row created.
但是你不能插入第二行
SQL> insert into users values( 4, 'user', 'Yes' );
insert into users values( 4, 'user', 'Yes' )
*
ERROR at line 1:
ORA-00001: unique constraint (SCOTT.IDX_USERS) violated
在幕后,Oracle b*-tree索引不会完全索引NULL条目.这两个CASE语句确保索引只有条目idOrganization,strUsername如果strNotDeleted不是NULL.如果strNotDeleted是NULL,则两个CASE语句都会求值,NULL并且索引中不会进行任何输入.从概念上讲,它类似于其他数据库中的部分索引,它允许您WHERE在索引上指定一个子句,以便只索引"有趣"的行.
| 归档时间: | 
 | 
| 查看次数: | 9589 次 | 
| 最近记录: |