如何确保postgresql表中只有一列不为空

inb24sb2  于 2021-07-24  发布在  Java
关注(0)|答案(3)|浏览(405)

我正在尝试设置一个表并为其添加一些约束。我计划使用部分索引来添加约束来创建一些复合键,但遇到了处理空值的问题。在这种情况下,我们需要确保表中给定行只填充了两列中的一列,并且填充的值是唯一的。我正在想办法,但我现在很艰难。也许是这样的:

CREATE INDEX foo_idx_a ON foo (colA) WHERE colB is NULL
CREATE INDEX foo_idx_b ON foo (colB) WHERE colA is NULL

这样行吗?另外,有没有一个好的方法可以扩展到更多的列?

rkkpypqq

rkkpypqq1#

您可以使用以下检查:

create table table_name 
(
  a integer, 
  b integer, 
  check ((a is null) != (b is null))
);

如果有更多的列,你可以使用铸造技巧 booleaninteger :

create table table_name 
(
  a integer, 
  b integer,
  ...
  n integer,
  check ((a is not null)::integer + (b is not null)::integer + ... + (n is not null)::integer = 1)
);

在本例中,只有一列不能为null(它只是计算非null列),但您可以将其设为任意数字。

1yjd4xko

1yjd4xko2#

编写此约束的另一种方法是使用 num_nonulls() 功能:

create table table_name 
(
  a integer, 
  b integer, 
  check ( num_nonnulls(a,b) = 1)
);

如果您有更多的列,这将特别有用:

create table table_name 
(
  a integer, 
  b integer, 
  c integer,
  d integer,
  check ( num_nonnulls(a,b,c,d) = 1)
);
bsxbgnwa

bsxbgnwa3#

可以使用insert/update触发器或检查来实现这一点,但必须这样做表明可以做得更好。约束的存在给了你数据的确定性,所以你不必经常检查数据是否有效。如果其中一个不为null,则必须在查询中进行检查。
使用表继承和视图可以更好地解决这个问题。
假设你有(美国)客户。有的是企业,有的是个人。每个人都需要一个纳税人识别号,它可以是一个或一个社会保险号码或雇主识别号等几件事之一。

create table generic_clients (
  id bigserial primary key,
  name text not null
);

create table individual_clients (
  ssn numeric(9) not null
) inherits(generic_clients);

create table business_clients (
  ein numeric(9) not null
) inherits(generic_clients);

ssn和ein都是纳税人识别号,您可以创建一个将两者视为相同的视图。

create view clients as
  select id, name, ssn as tin from individual_clients
  union
  select id, name, ein as tin from business_clients;

现在您可以查询 clients.tin 或者如果你特别想要你查询的业务 business_clients.ein 对于个人而言 individual_clients.ssn . 您还可以看到如何扩展继承的表以容纳不同类型客户机之间更多的不同信息。

相关问题