【问题标题】:How to make sure only one column is not null in postgresql table如何确保postgresql表中只有一列不为空
【发布时间】:2020-07-23 18:53:51
【问题描述】:

我正在尝试设置一个表并为其添加一些约束。我计划使用部分索引来添加约束以创建一些复合键,但遇到了处理 NULL 值的问题。我们有一种情况,我们希望确保在一个表中,只为给定行填充两列中的一列,并且填充的值是唯一的。我试图弄清楚如何做到这一点,但我遇到了困难。也许是这样的:

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

这行得通吗?此外,有没有一种好方法可以将其扩展到更多列?

【问题讨论】:

  • 这可以通过触发器来完成,但通过模式更改可以更优雅地完成。您能否提供更多关于列中内容的背景信息?它们都是相似类型的值吗?
  • 不一定是相似的类型。我正在尝试构建一个通用系统,可以从模式生成这些类型的约束。

标签: sql postgresql indexing constraints


【解决方案1】:

编写此约束的另一种方法是使用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)
);

【讨论】:

  • 这个比我的版本更优雅,我不知道postgres有这个
【解决方案2】:

您可以使用以下检查:

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

如果有更多列,您可以使用将boolean 转换为integer 的技巧:

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)
);

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

【讨论】:

    【解决方案3】:

    可以使用插入/更新触发器或checks 来做到这一点,但必须这样做表明它可以做得更好。存在约束以使您对数据具有确定性,因此您不必经常检查数据是否有效。如果其中一个不为空,则必须在查询中进行检查。

    table inheritance 和视图可以更好地解决这个问题。

    假设您有(美国)客户。有些是企业,有些是个人。每个人都需要Taxpayer Identification Number,它可以是社会安全号码或雇主识别号码等多种信息之一。

    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。您还可以看到如何扩展继承的表以适应不同类型客户端之间的更多不同信息。

    【讨论】:

      猜你喜欢
      • 2019-11-11
      • 2021-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多