Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 使行中的所有非空值唯一_Sql_Postgresql_Check Constraints - Fatal编程技术网

Sql 使行中的所有非空值唯一

Sql 使行中的所有非空值唯一,sql,postgresql,check-constraints,Sql,Postgresql,Check Constraints,我有一个包含以下列的表:id、col1、col2、col3、col4、col5、col6 约束表示至少有3列被填充(因此最多有3个空值)。(列不是按顺序填充的,因此可以有col1、col2、col5填充,col3、col4、col6为空) 如何确保该列不为NULL时,它在此行的其他列中是唯一的? 如何确保非空值的组合在所有行中都是唯一的 我当前添加了以下约束(以确保至少3个非空): 这不是一个有趣的约束,因为所有的NULL值都是空的,但我认为这样做了 alter table my_table a

我有一个包含以下列的表:id、col1、col2、col3、col4、col5、col6

约束表示至少有3列被填充(因此最多有3个空值)。(列不是按顺序填充的,因此可以有col1、col2、col5填充,col3、col4、col6为空)

如何确保该列不为NULL时,它在此行的其他列中是唯一的? 如何确保非空值的组合在所有行中都是唯一的

我当前添加了以下约束(以确保至少3个非空):


这不是一个有趣的约束,因为所有的
NULL
值都是空的,但我认为这样做了

alter table my_table add constraint chk_ugly check
     ( (col1 is null or col1 <> all (array_remove(array[col2, col3, col4, col5, col6], null))) and
       (col2 is null or col2 <> all (array_remove(array[col1, col3, col4, col5, col6], null))) and
       (col3 is null or col3 <> all (array_remove(array[col1, col2, col4, col5, col6], null))) and
       (col4 is null or col4 <> all (array_remove(array[col1, col2, col3, col5, col6], null))) and
       (col5 is null or col5 <> all (array_remove(array[col1, col2, col3, col4, col6], null))) and
       (col6 is null or col6 <> all (array_remove(array[col1, col2, col3, col4, col5], null))) 
     )

这不是一个有趣的约束,因为所有的
NULL
值都是空的,但我认为这样做了

alter table my_table add constraint chk_ugly check
     ( (col1 is null or col1 <> all (array_remove(array[col2, col3, col4, col5, col6], null))) and
       (col2 is null or col2 <> all (array_remove(array[col1, col3, col4, col5, col6], null))) and
       (col3 is null or col3 <> all (array_remove(array[col1, col2, col4, col5, col6], null))) and
       (col4 is null or col4 <> all (array_remove(array[col1, col2, col3, col5, col6], null))) and
       (col5 is null or col5 <> all (array_remove(array[col1, col2, col3, col4, col6], null))) and
       (col6 is null or col6 <> all (array_remove(array[col1, col2, col3, col4, col5], null))) 
     )

据我所知,这实际上是三个不同的约束条件。至少必须存在三个非空值的方法很简单:

ALTER TABLE my_table
   ADD CONSTRAINT my_constraint CHECK ( num_nonnulls(c1, c2, c3, c4, c5, c6) >= 3);
通过创建一个函数检查以下内容,可以实现一行的6列中不应存在重复值的要求:

create or replace function all_unique(p_row my_table)
  returns boolean
as
$$
  select not exists (
    select v
    from (
        values (p_row.c1), (p_row.c2), (p_row.c3), (p_row.c4), (p_row.c5), (p_row.c6)
    ) t(v)
    where v is not null
    group by v
    having count(*) > 1);
$$
language sql
immutable
strict;
如果一行中的所有非空值都是唯一的,则函数返回true。我将其定义为接收一个完整的行,以便在添加或删除新列时更容易适应。我不确定这是否是最有效或最简单的方法,但我现在想不出其他方法

这可用于检查约束:

ALTER TABLE my_table
    ADD CONSTRAINT all_unique CHECK ( all_unique(my_table) );
最后一个要求是跨多行的非空值应该是唯一的,这可以通过一个唯一的索引来实现。但为此,我们需要一个函数,该函数以排序方式创建非空值数组:

create or replace function non_null_values(p_row my_table)
  returns text[]
as
$$
  select array(
    select distinct v
    from (
        values (p_row.c1), (p_row.c2), (p_row.c3), (p_row.c4), (p_row.c5), (p_row.c6)
    ) t(v)
    where v is not null
    order by v);
$$
language sql
immutable
strict;
为什么要分类呢?因为Postgres认为数组
[1,2,3]
与唯一索引使用的数组
[3,1,2]
不相等(
=

然后,此函数可用于唯一索引:

create unique index on my_table (non_null_values(my_table));

据我所知,这实际上是三个不同的约束条件。至少必须存在三个非空值的方法很简单:

ALTER TABLE my_table
   ADD CONSTRAINT my_constraint CHECK ( num_nonnulls(c1, c2, c3, c4, c5, c6) >= 3);
通过创建一个函数检查以下内容,可以实现一行的6列中不应存在重复值的要求:

create or replace function all_unique(p_row my_table)
  returns boolean
as
$$
  select not exists (
    select v
    from (
        values (p_row.c1), (p_row.c2), (p_row.c3), (p_row.c4), (p_row.c5), (p_row.c6)
    ) t(v)
    where v is not null
    group by v
    having count(*) > 1);
$$
language sql
immutable
strict;
如果一行中的所有非空值都是唯一的,则函数返回true。我将其定义为接收一个完整的行,以便在添加或删除新列时更容易适应。我不确定这是否是最有效或最简单的方法,但我现在想不出其他方法

这可用于检查约束:

ALTER TABLE my_table
    ADD CONSTRAINT all_unique CHECK ( all_unique(my_table) );
最后一个要求是跨多行的非空值应该是唯一的,这可以通过一个唯一的索引来实现。但为此,我们需要一个函数,该函数以排序方式创建非空值数组:

create or replace function non_null_values(p_row my_table)
  returns text[]
as
$$
  select array(
    select distinct v
    from (
        values (p_row.c1), (p_row.c2), (p_row.c3), (p_row.c4), (p_row.c5), (p_row.c6)
    ) t(v)
    where v is not null
    order by v);
$$
language sql
immutable
strict;
为什么要分类呢?因为Postgres认为数组
[1,2,3]
与唯一索引使用的数组
[3,1,2]
不相等(
=

然后,此函数可用于唯一索引:

create unique index on my_table (non_null_values(my_table));

我的第一反应是,您可能想更改您的桌子设计。与其有六列,不如有一列,再加上第二列以跟踪原始“列”。@TimBiegeleisen恐怕我不明白您的点有一个检查约束,每个非空列加1,并验证总和至少为3。@jarlh但唯一的要求是什么?这是一种跨行而不是跨列聚合的方法。@TimBiegeleisen,哦,错过了这一部分。我的第一反应是您可能想更改表设计。与其有六列,不如有一列,再加上第二列以跟踪原始“列”。@TimBiegeleisen恐怕我不明白您的点有一个检查约束,每个非空列加1,并验证总和至少为3。@jarlh但唯一的要求是什么?这是跨行而不是跨列聚合的问题。@TimBiegeleisen,oops,遗漏了这一部分。可以简化现有约束,以注意当前约束可以简化为
检查((num_nonnulls(col1,col2,col3,col4,col5,col6)>=3))
谢谢您的回答。实际上,我目前的结构是每列和每id一行。这种方法的问题是:多个其他表与此表相关(
other\u table有许多My\u table
),我不想在每次插入/删除时使用触发器约束锁定表来检查最小数量的相关记录。所以我确信这种结构会缓解这个问题在ORM级别验证要容易得多(因为我验证单个记录的字段,而不是3到6个记录的字段)。但我也希望确保数据库级的完整性,即c
select'foo'any(array['foo','bar')产生
t
,而它应该是
f
我相信现有约束可以简化为注意当前约束可以简化为
检查((num_nonnulls(col1,col2,col3,col4,col5,col6)>=3))
谢谢你的回答。实际上,我目前的结构是每列和每id一行。这种方法的问题是:多个其他表与此表相关(
other\u table有许多My\u table
),我不想在每次插入/删除时使用触发器约束锁定表来检查最小数量的相关记录。所以我确信这种结构会缓解这个问题在ORM级别验证要容易得多(因为我验证单个记录的字段,而不是3到6个记录的字段)。但我也希望确保数据库级的完整性,即c
select'foo'any(array['foo','bar')产生
t
,而它应该是
f
我相信谢谢你的回答!当我试着运行它时