PostgreSQL ON INSERT CASCADE

时间:2011-11-19 22:53:11

标签: postgresql triggers insert

我有两个表 - 一个是Product,一个是ProductSearchResult。

每当有人尝试使用未在Product表中列出的产品插入SearchResult时,外键约束都是违规的,因此我收到错误。

我想知道如何让数据库自动在产品表中创建缺少的产品(只是ProductID,所有其他属性都可以留空)

是否有CASCADE ON INSERT这样的东西?如果有的话,我无法让它发挥作用。

插入后,

规则正在执行,因为如果你使用“DO ALSO”,我们事先得到一个错误就没用了。如果你使用“DO INSTEAD”并在结尾添加INSERT命令,你最终会得到无休止的递归。

我认为触发器是要走的路 - 但我写的所有尝试都失败了。

有什么建议吗?

表格结构:

CREATE TABLE Product (
    ID char(10) PRIMARY KEY,
    Title varchar(150),
    Manufacturer varchar(80),
    Category smallint,
    FOREIGN KEY(Category) REFERENCES Category(ID) ON DELETE CASCADE);


CREATE TABLE ProductSearchResult (
    SearchTermID smallint NOT NULL,
    ProductID char(10) NOT NULL,
    DateFirstListed date NOT NULL DEFAULT current_date,
    DateLastListed date NOT NULL DEFAULT current_date,
    PRIMARY KEY (SearchTermID,ProductID),
    FOREIGN KEY (SearchTermID) REFERENCES SearchTerm(ID) ON DELETE CASCADE,
    FOREIGN KEY (ProductID) REFERENCES Product ON DELETE CASCADE);

2 个答案:

答案 0 :(得分:2)

是的,触发器是要走的路。但是在你开始在plpgsql中使用触发器之前,你 必须启用该语言。作为用户postgres,使用适当的参数运行命令createlang

完成后,您必须

  1. 在plpgsql中编写函数
  2. 创建一个触发器来调用该函数
  3. 有关基本示例,请参阅example 39-3

    请注意,Postgres中的函数体是一个字符串,具有特殊的引用机制:2个美元符号,它们之间带有可选字,作为引号。 (这个词允许你引用其他类似的引号。)

    另请注意,您可以为多个表重用触发器过程,只要它们具有您的过程使用的列。

    所以函数必须

    1. 使用select语句(您应该能够使用SELECT count(*) ... INTO someintSELECT EXISTS(...) INTO somebool
    2. 检查ProductSearchResult表中是否存在NEW.ProductID的值
    3. 如果没有,请在该表中插入新行
    4. 如果你仍然卡住,请回到这里。

答案 1 :(得分:0)

在任何情况下(规则OR触发器),insert都需要在products表中创建一个新键(以及属性的新值)。在大多数情况下,这意味着应在产品表中使用(串行,序列)代理主键,并且“真实世界”product_id(“产品编号”)应默认为NULL,并降级为候选键

BTW:可以使用规则 ,对于N:1关系,规则只是很难实现(它们需要与Bart上面的答案中相同的EXISTS逻辑)。

毕竟,在INSERT上级联并不是一个好主意。如果有人为不存在的产品插入ProductSearchResult记录,您希望发生什么? [IMO FK永远是一个领域;你不能只是通过引用一个不存在的值来扩展一个域;这将使FK约束无意义]