可为null的复合主键



我希望能够做到以下几点:

insert into myTable values ('myParamName', NULL, 'alskdjflas');
insert into myTable values ('myParamName', 'A', 'asdf');

但当我在之后运行时,它需要给出一个错误

insert into myTable values ('myParamName', 'A', 'asdf2');

我还需要能够做到这一点:

select * 
from parameters p 
left join myTable mt on mt.parameter_id = p.parameter_id 
and mt.visible_mask_substring = NULL

这个:

select * 
from parameters p 
left join myTable mt on mt.parameter_id = p.parameter_id 
and mt.visible_mask_substring = 'A'

因此,我需要能够在第二列上LEFT JOIN,但如果不将第二列设为主键,就无法做到这一点,但它不能成为主键,因为主键不能为null,但我的数据需要有一个可选的null第二列。

我离放弃和插入单词";NULL";在引号中,这样我就可以让第二列是PK,但允许它为空(可能不是一个合适的解决方案(:

DROP TABLE myTable;
CREATE TABLE myTable 
(
parameter_id varchar2(40),
visible_mask_substring varchar2(1),
someVal varchar2(50),
PRIMARY KEY (parameter_id, visible_mask_substring),
CONSTRAINT idek_ibfk_1 
FOREIGN KEY (parameter_id) REFERENCES parameters (parameter_id)
);
insert into myTable values ('myParamName', 'NULL', 'alskdjflas');
insert into myTable values ('myParamName', 'A', 'asdf');
主键毕竟只是表中某些不可为null的列的唯一约束。您希望在列parameter_idvisible_mask_substring上有一个唯一的键。但与SQL中常见的情况不同,您希望将visible_mask_substring中的NULL视为另一个特定值。

由于visible_mask_substring可以包含任何可能的字符串,因此从技术上讲,不可能仅在这两列上具有唯一索引并将NULL作为附加值。

有两种解决方案,都使用函数索引:

如果您知道一个永远不会被使用的值,那么就用它来表示NULL。例如字符串"###NULL###"。该指数看起来像

create index idx on mytable 
(
parameter_id,
nvl(visible_mask_substring, '###NULL###')
);

如果您不能保证任何值永远不会被使用(或者如果您只是想要一个清晰的通用解决方案(,请使用三列:

create unique index idx on mytable 
(
parameter_id,
nvl(visible_mask_substring, 'NULL'),
decode(visible_mask_substring, null, 'NULL', 'NOTNULL')
);

演示:https://dbfiddle.uk/8HwR8Hox

最新更新