是否可以将视图中的列称为外键(PostgreSQL 9.4)?

Jor*_*rdi 8 postgresql postgresql-9.4

我知道在旧版本中它是不可能的,是否与版本9.4相同?

我正在尝试做这样的事情:

CREATE VIEW products AS 
    SELECT d1.id AS id, d1.price AS pr FROM dup.freshProducts AS d1
    UNION
    SELECT d2.id AS id, d2.price AS pr FROM dup.cannedProducts AS d2;

CREATE TABLE orderLines
( 
    line_id integer PRIMARY KEY, 
    product_no integer REFERENCES productView.id
);
Run Code Online (Sandbox Code Playgroud)

我正在尝试实现继承关系,其中freshProductscannedProducts都继承自products.我使用两个不同的表实现它,我创建了一个products只有freshProducts和之间只有公共属性的视图cannedProducts.另外,每一行都orderLines与a product,a freshProduct或a 有关系cannedProduct.请参阅图像以获得澄清.

我正在尝试建模.

如果还不能引用视图,您认为哪种解决方案最好?我曾想过使用触发器实现物化视图或实现限制.您能否建议使用此类触发器作为基础的任何好例子?

非常感谢你!

MyB*_*rts 7

引用(物化)视图不起作用,触发器可能如下所示:

CREATE OR REPLACE FUNCTION reject_not_existing_id()
    RETURNS "trigger" AS
    $BODY$
        BEGIN
            IF NEW.product_no NOT IN (SELECT id FROM dup.freshProducts UNION SELECT id FROM dup.cannedProducts) THEN
                RAISE EXCEPTION 'The product id % does not exist', NEW.product_no;
            END IF;
            RETURN NEW;
        END;
    $BODY$
        LANGUAGE 'plpgsql' VOLATILE;

CREATE TRIGGER tr_before_insert_or_update
    BEFORE INSERT OR UPDATE OF product_no
    ON orderLines
    FOR EACH ROW
    EXECUTE PROCEDURE reject_not_existing_id();
Run Code Online (Sandbox Code Playgroud)

(另见http://www.tek-tips.com/viewthread.cfm?qid=1116256)

物化视图可能看起来像一个好方法,但失败有两个原因:像一个视图你根本无法引用它,因为它不是表(继续尝试).假如你能,仍然会有阻止两个相同的ID在的问题freshProductscannedProducts.是的,您可以在物化视图上定义UNIQUE INDEX,但是如何确保在新的罐头中不使用相同的ID?如果使用触发器,那么你仍需要解决这个问题orderLines.

这让我建议重新考虑你的模型.'Fresh'和'canned'也可能是单个表属性的值products,因此使所有麻烦变得多余.如果新鲜和罐装产品的属性(数量)显着不同(不能想到创建两个不同表的任何其他原因),那么在另外两个表中引用产品ID.喜欢

CREATE TABLE products
(
    id ... PRIMARY KEY
    , fresh_or_canned ...
    , price ...
    , another_common_attribute_1 ...
    , ...
    , another_common_attribute_n ...
);

CREATE TABLE canned_specific_data
(
    canned_id ... REFERENCES products (id)
    , type_of_can ...
    , ...
    , another_attribute_that_does_not_apply_to_fresh ...
);

CREATE TABLE fresh_specific_data
(
    fresh_id ... REFERENCES products (id)
    , date_of_harvest ...
    , ...
    , another_attribute_that_does_not_apply_to_canned ...
);
Run Code Online (Sandbox Code Playgroud)


Rob*_*ard 5

防止 ID 重复的简单答案是简单地使用与 freshProducts 和 cannedProducts 中 ID 的默认值相同的序列。

现在,问题来了,你为什么需要外键?通常这是为了防止删除另一个表所依赖的数据,但是,您可以编写触发器来防止这种情况发生。此外,您已将该值更新为键控表中不存在的值,但您也可以为此编写触发器。

因此,基本上您可以编写触发器来实现外键的所有所需功能,而实际上不需要外键,另外的好处是它们将与这样的视图一起使用。