2017-04-12 30 views
2

我有一個包含與日常業務數據的兩個表:每獨特價值執行函數一次

CREATE TABLE main_table (
    main_id serial, 
    cola text, 
    colb text, 
    colc text, 
    CONSTRAINT main_table_pkey PRIMARY KEY (main_id) 
); 

CREATE TABLE second_table (
    second_id serial, 
    main_id integer, 
    cold text, 
    CONSTRAINT second_table_pkey PRIMARY KEY (second_id), 
    CONSTRAINT second_table_fkey FOREIGN KEY (main_id) 
    REFERENCES main_table (main_id) MATCH SIMPLE 
    ON UPDATE NO ACTION ON DELETE NO ACTION 
); 

我們有必要知道一些數據在這些表中進行了更新,使出口可以生成並推到第三方。我創建了一個第三個表來保存更新信息:

CREATE TYPE field AS ENUM ('cola', 'colb', 'colc', 'cold'); 
CREATE TABLE table_updates (
    main_id int, 
    field field 
    updated_on date NOT NULL DEFAULT NOW(), 
    CONSTRAINT table_updates_fkey FOREIGN KEY (main_id) 
    REFERENCES main_table (main_id) MATCH SIMPLE 
    ON UPDATE NO ACTION ON DELETE NO ACTION 
); 

main_table具有觸發更新table_updatesUPDATE查詢,滿足需要跟蹤三個四柱更新。

我可以很容易地添加相同類型的觸發器來second_table,但是因爲main_id不是唯一的功能可以爲單個main_id值,這是不希望被執行數次。

如何創建一個函數,在更新second_table中的多個行時,每main_id只執行一次?

回答

2

如何創建一個函數,在更新second_table中的多行時,每個main_id只執行一次?

如果您的刀片通過main_id即批量插入INSERT INTO tbl (main_id...) VALUES (main_id ...),(main_id ...),(main_id ...)可以使用rule systemINSERTUPDATE

對於可通過兩種實現的事情,這是最好的取決於觸發一次關於數據庫的使用。 每個受影響的行觸發器觸發一次。規則會修改查詢或生成其他查詢。因此,如果在一條語句中有很多行受到影響,那麼發出一條額外命令的規則可能會快於爲每一行調用的觸發器,並且必須重新確定多次執行的操作。然而,觸發器方法在概念上比規則方法簡單得多,而且新手更容易獲得正確的方法。

害羞的是,你可能還想看看正常的LISTENNOTIFY。哪些給你使用異步操作的能力。如果這是您的事情,並且您決定保留觸發方法,請考慮觸發更改通知模塊,通過tcn

我的建議是在應用程序中(數據庫外)如果可能的話這樣做。請記住,PostgreSQL temp表是會話本地的。所以,你可以在每個架會議做這樣的事情,

BEGIN 
    CREATE TEMP TABLE UNLOGGED etl_inventory; 
    COPY foo FROM stdin; 
    -- Are they different, if so `NOTIFY` 
    -- UPSERT 
COMMIT; 

然後一個有一個守護進程,做出口的附加在接收到NOTIFY事件隊列出口。

1

雖然Evan的answer是正確的,但我認爲這個問題可以從一個例子中受益。

這是我在這個問題的例子表使用的規則定義:

CREATE OR REPLACE RULE update_update_table 
AS ON UPDATE TO second_table 
DO ALSO (
    INSERT INTO table_updates (
    main_id, field 
) 
    SELECT DISTINCT OLD.main_id, 'cold'::field 
    WHERE NOT EXISTS (
    SELECT TRUE 
    FROM table_updates 
    WHERE main_id = OLD.main_id 
     AND field = 'cold' 
); 
    UPDATE table_updates 
    SET updated_on = NOW() 
    WHERE main_id = OLD.main_id 
    AND field = 'cold' 
)