在 PostgreSQL 视图上插入或更新

jdo*_*dot 5 sql postgresql views

我从 PostgreSQL 视图开始,因为它们对我的用例很有用,并且会提供比函数更好的性能。

(这无关紧要,但我在 Heroku Postgres 上使用 Django 1.7 以防万一)。

我已经创建了一个视图并且可以很好地查询它。我想围绕视图编写一个 Django 包装器,以便我可以将它视为一个表,并相应地查询和写入它。我一直在查看 Postgres 文档INSERTUPDATE查看意见,但老实说,我发现他们的文档很难阅读,我几乎无法解析他们在说什么。

假设我有以下观点:

CREATE OR REPLACE VIEW links AS
  SELECT
    listing.id                                                     AS listing_id,
    CONCAT('/i-', industry.slug, '-j-', listing.slug, '/') AS link,
    'https://www.example.com' || CONCAT(industry.slug, '-SEP-', listing.slug, '/') AS full_link,
    listing.slug AS listing_slug,
    industry.slug AS industry_slug
  FROM listing
    INNER JOIN company ON company.id = listing.company_id
    INNER JOIN industry ON industry.id = company.industry_id
Run Code Online (Sandbox Code Playgroud)

在这里,我正在使用industry.sluglisting.slug来构建链接。我希望能够从此视图更新这两个字段,例如:

UPDATE links
SET listing_slug = 'my-new-slug'
WHERE listing_id = 5;
Run Code Online (Sandbox Code Playgroud)

如何创建规则以正确执行此操作?

Tom*_*ico 3

由于双重连接,最好使用触发器过程。要更新行业表,您需要首先使用外键listing-company-industry查找industry.id。程序可能如下所示:

CREATE OR REPLACE FUNCTION update_listing_and_industry() RETURNS TRIGGER AS
  $$
  DECLARE _company_id int; _industry_id int;
  BEGIN
    _company_id = (SELECT company_id FROM listing WHERE id = OLD.listing_id);
    _industry_id = (SELECT industry_id FROM company WHERE id = _company_id);

    UPDATE listing SET slug = NEW.listing_slug WHERE id = OLD.listing_id;
    UPDATE industry SET slug = NEW.industry_slug WHERE id = _industry_id;
    RETURN NEW;
  END;
  $$
LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

注意:触发器过程是返回 TRIGGER 的正常过程。根据触发器执行的操作,过程必须返回 NEW 或 OLD(在本例中为 NEW)。

以及带有子句的触发器INSTEAD OF UPDATE

CREATE trigger update_view INSTEAD OF UPDATE ON links 
FOR EACH ROW EXECUTE PROCEDURE update_listing_and_industry();
Run Code Online (Sandbox Code Playgroud)