我知道在旧版本中它是不可能的,是否与版本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
);
我正在尝试实现继承关系,其中freshProducts
和cannedProducts
都从products
继承。我使用两个不同的表实现了它,并创建了一个视图products
,它只包含freshProducts
和cannedProducts
之间的公共属性。此外,orderLines
中的每一行都与product
有关系,freshProduct
或cannedProduct
。见图片以便澄清。
如果无法引用视图,您认为哪种解决方案最好?我曾想过使用触发器实现物化视图或实现限制。您能否建议将此类触发器的任何好例子用作基础?
非常感谢你!
答案 0 :(得分: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();
(另见http://www.tek-tips.com/viewthread.cfm?qid=1116256)
物化视图可能看起来像一个好方法,但失败有两个原因:就像一个视图你根本无法引用它,因为它不是表(继续尝试)。假设你可以,在freshProducts
和cannedProducts
中仍然存在阻止两个相等ID的问题。是的,你可以在物化视图上定义一个独特的索引,但是如何确保在新的罐头中同时使用相同的ID?
如果在orderLines
中使用触发器,您仍需要解决这个问题。
这让我建议重新考虑你的模特。 '新鲜'和'罐头'也可能是单个表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 ...
);
答案 1 :(得分:4)
防止ID复制的简单答案是在freshProducts和cannedProducts中使用与默认值相同的序列。
现在,有一个问题,为什么你需要外键呢?通常这是为了防止删除另一个表所依赖的数据,但是,您可以编写一个触发器来防止这种情况。 Alsowise,您已将该值更新为keyed-to表中不存在的内容,但您也可以为此编写触发器。
因此,基本上你可以编写触发器来实现外键所需的所有功能,而不需要实际需要外键,这样可以增加他们使用这种视图的好处。