Postgres constraint ensuring one column of many is present?

前端 未结 6 1502
天命终不由人
天命终不由人 2021-02-01 03:01

What are good ways to add a constraint to PostgreSQL to check that exactly one column (from a set of columns) contains a non-null value?

Update: It is likely th

6条回答
  •  一生所求
    2021-02-01 03:45

    I think the most clean and generic solution is to create a function to count the null values from some arguments. For that you can use the pseudo-type anyarray and a SQL function like that:

    CREATE FUNCTION count_not_nulls(p_array anyarray)
    RETURNS BIGINT AS
    $$
        SELECT count(x) FROM unnest($1) AS x
    $$ LANGUAGE SQL IMMUTABLE;
    

    With that function, you can create your CHECK CONSTRAINT as:

    ALTER TABLE your_table
    ADD chk_only_one_is_not_null CHECK(count_not_nulls(array[col1, col2, col3]) = 1);
    

    This will only work if the columns are of the same data type. If it's not the case, you can cast them, as text for instance (as you just care for the null case):

    ALTER TABLE your_table
    ADD chk_only_one_is_not_null CHECK(count_not_nulls(array[col1::text, col2::text, col3::text]) = 1);
    

    As well remembered by @muistooshort, you can create the function with variadic arguments, which makes it clear to call:

    CREATE FUNCTION count_not_nulls(variadic p_array anyarray)
    RETURNS BIGINT AS
    $$
        SELECT count(x) FROM unnest($1) AS x
    $$ LANGUAGE SQL IMMUTABLE;
    
    ALTER TABLE your_table
    ADD chk_only_one_is_not_null CHECK(count_not_nulls(col1, col2, col3) = 1);
    

提交回复
热议问题