什么是在Postgres中继承唯一约束的最佳解决方法?

问题描述 投票:0回答:1

在Postgres中,我试图从父级继承其子级的唯一属性。父表是一个抽象表,其中没有条目。所有孩子的名字都应该是独一无二的。参考下面的小(愚蠢)例子:应该没有与香蕉同名的苹果(当然还有其他苹果)。

这个场景的Minimalistic Postgres示例:

CREATE TABLE fruit(CONSTRAINT fruit_uniq_name UNIQUE (name))
CREATE TABLE banana(name text, length integer) INHERITS (fruit)
CREATE TABLE apple(name, diameter integer NOT NULL,) INHERITS (fruit)

在阅读了很多关于这个问题的帖子之后。所有这些人都得出结论,只有Postgres的继承才能掌握这种情况,我想知道是否有最佳实践解决方法,例如:使用触发器和函数,针对这个问题?

我会为每一小段代码感到高兴,这可以帮助我摆脱这个烦人的陷阱。

sql postgresql inheritance constraints unique
1个回答
0
投票

我遵循Laurenz Albe的建议,我认为我通过在表apple和banana上使用触发器以及测试唯一性的触发器函数tgf_name_exists()来解决问题。

这是测试子名称唯一性的触发器函数:

CREATE OR REPLACE FUNCTION tgf_name_exits()
    RETURNS trigger
    LANGUAGE 'plpgsql'
    VOLATILE
    COST 100
AS $BODY$
    declare
    count_apple integer;
    count_banana integer;
    name text;
    schema text;
    error_text text;
BEGIN
    -- Variables
    error_text = '';
    schema = TG_TABLE_SCHEMA; -- actual schema
    name = NEW.name; --- actual attribute name

    -- Check
    EXECUTE format('SELECT count(*) FROM %s.apple apl WHERE apl.name=%L', schema, name) INTO count_apple;
    EXECUTE format('SELECT count(*) FROM %s.banana ban WHERE ban.name=%L', schema, name) INTO count_banana;

    -- Info 
    RAISE NOTICE 'Schema: %', schema;
    RAISE NOTICE 'Name: %', name;
    RAISE NOTICE 'Count: %', count_apple;
    RAISE NOTICE 'Count: %', count_banana;

    IF count_apple > 0 OR count_banana > 0 THEN
        -- Name ist already used
        if count_apple > 0 then
            error_text = error_text || "apple "
        end if;
        if count_banana > 0 then
            error_text = error_text || "banana "
        end if;
        RAISE EXCEPTION 'Name % already existing in table %', name, error_text;
    ELSE
        -- Name is unused -> OK 
        RETURN NEW;
    END IF;
END;
$BODY$;

这些是苹果和香蕉表的触发器

CREATE TRIGGER tg_apple_name_instert_update
    BEFORE INSERT OR UPDATE 
    ON apple
    FOR EACH ROW
    EXECUTE PROCEDURE tgf_name_exits();

CREATE TRIGGER tg_banana_name_uniq
    BEFORE INSERT OR UPDATE 
    ON banana
    FOR EACH ROW
    EXECUTE PROCEDURE tgf_name_exits();

如果有人能检查这个,那将是非常友好的。从这里看起来它很有效。

© www.soinside.com 2019 - 2024. All rights reserved.