如何为db2表中的行子集创建唯一索引

时间:2019-02-23 09:38:56

标签: db2 db2-luw

我正在尝试为特定表中的数据子集创建唯一索引。现有数据是这样的-

enter image description here

但是实际数据应如下所示-

enter image description here

行的子集将是条件状态为A或B的行。对于这些行集,unique_id和金额值组合应该是唯一的。

在Windows服务器上,这里使用的DB2版本是9.7。在DB2中是否可以使用部分索引或条件索引?

1 个答案:

答案 0 :(得分:0)

新表格

create or replace function generate_unique_det()
returns varchar(13) for bit data
deterministic
no external action
contains sql
return generate_unique();

create table test_unique (
  unique_id int not null
, status char(1) not null
, amount int not null
, status2 varchar(13) for bit data not null generated always as 
  (case when status in ('A', 'B') then '' else generate_unique_det() end)
) in userspace1;

create unique index test_unique1 on test_unique (unique_id, amount, status2);

insert into test_unique (unique_id, status, amount) 
values
  (1234, 'A', 400)
--, (1234, 'B', 400)
, (1234, 'Z', 400)
, (1234, 'Z', 400);

标准generate_unique函数不是确定性的。 generated always子句中不允许使用此类功能。 这就是为什么我们基于标准函数创建自己的函数的原因。 此类“伪造”函数的问题可能是,如果在多行更改操作期间Db2并未为每个更新/插入的行实际调用此函数(为什么要在同一组上多次调用deterministic函数)参数(如果足以执行一次,然后将结果重新用于其他受影响的行)。但这实际上可行-Db2确实为每个受影响的行调用了此函数,这在我们的情况下是需要的。 您不能在最后一条语句中插入注释掉的行。

现有表格

set integrity for test_unique off;

alter table test_unique add 
status2 varchar(13) for bit data not null 
generated always as (case when status in ('A', 'B') then '' else generate_unique_det() end);

set integrity for test_unique immediate checked force generated;

-- If you need to save the rows violated future unique index
create table test_unique_exc like test_unique in userspace1;

-- If you don't need to save the the rows violated future unique index,  
-- then just run the inner DELETE statement only,
-- which just removes these rows.
-- The whole statement inserts the deleted rows into the "exception table".
with d as (
  select unique_id, status, amount, status2
  from old table (
    delete from (select t.*, rownumber() over (partition by unique_id, amount, status2) rn_ from test_unique t) where rn_>1
  )
)
select count(1)
from new table (
  insert into test_unique_exc select * from d
);

create unique index test_unique1 on test_unique (unique_id, amount, status2);