2017-02-03 61 views
1

在編寫此問題的過程中,我找到了答案,並將其發佈到下面。如果這個問題已經有重複,請通知我,我將刪除它,我找不到任何。postgres默認值適用於更新,而不僅僅是在創建

我有兩列跟蹤的Postgres對錶所作的更改:

created_at timestamp default now() 
updated_at timestamp 

的的updated_at列正在由觸發器更新:

united_states_congress=> \d congressional_bill_summaries; 
             Table "public.congressional_bill_summaries" 
    Column |   Type    |         Modifiers         
-------------+-----------------------------+--------------------------------------------------------------------------- 
id   | bigint      | not null default nextval('congressional_bill_summaries_id_seq'::regclass) 
text  | text      | 
created_at | timestamp without time zone | default now() 
updated_at | timestamp without time zone | 
bill_kid | integer      | not null 
date  | date      | not null 
description | character varying(255)  | not null 
text_hash | uuid      | 
Indexes: 
    "congressional_bill_summaries_pkey" PRIMARY KEY, btree (id) 
    "congressional_bill_summaries_bill_kid_date_description_key" UNIQUE CONSTRAINT, btree (bill_kid, date, description) 
Triggers: 
    hash_all_the_things BEFORE INSERT ON congressional_bill_summaries FOR EACH ROW EXECUTE PROCEDURE hash_this_foo() 
    update_iz_yoo BEFORE UPDATE ON congressional_bill_summaries FOR EACH ROW EXECUTE PROCEDURE update_iz_now() 

一樣,是一個其他列該表,text_hash

我的預期行爲是,當第一次插入行時,created_at列將更新爲默認值(我明白是當前事務開始的時間,而不是特定查詢的時間)。

我預期的行爲是,當行被更新時,的updated_at線將通過該功能更新:

CREATE OR REPLACE FUNCTION public.update_iz_now() 
RETURNS trigger 
LANGUAGE plpgsql 
AS $function$ 
BEGIN 
    NEW.updated_at = now(); 
    RETURN NEW; 
END; 
$function$ 

但created_at將保持不變,因爲值已經在列,所以它不應該用默認值覆蓋。

created_at最初工作正常:

united_states_congress=> select created_at, updated_at from congressional_bill_actions limit 5; 
     created_at   | updated_at 
----------------------------+------------ 
2017-01-28 00:08:11.238773 | 
2017-01-28 00:08:11.255533 | 
2017-01-28 00:08:15.036168 | 
2017-01-28 00:08:15.047991 | 
2017-01-28 00:08:15.071715 | 
(5 rows) 

但是當行被更新,created_at被改變以匹配的updated_at的插入值,留下我:

united_states_congress=> select created_at, updated_at from congressional_bill_actions where updated_at is not null limit 5; 
     created_at   |   updated_at   
----------------------------+---------------------------- 
2017-01-28 07:55:34.078783 | 2017-01-28 07:55:34.078783 
2017-02-01 18:47:50.673996 | 2017-02-01 18:47:50.673996 
2017-02-02 14:50:33.066341 | 2017-02-02 14:50:33.066341 
2017-02-02 14:50:33.083343 | 2017-02-02 14:50:33.083343 
2017-02-03 13:58:34.950716 | 2017-02-03 13:58:34.950716 
(5 rows) 

我有已經遍佈互聯網試圖找出這個問題,但互聯網保持有效地向我提供有關「如何創建默認值」和「如何製作觸發器」的問題。

這顯然必須是我的一個地方的使用問題,但我無法識別它。以防萬一,這裏是另一個觸發被放在桌子上(插入)運行:

CREATE OR REPLACE FUNCTION public.hash_this_foo() 
RETURNS trigger 
LANGUAGE plpgsql 
AS $function$ 
BEGIN 
    NEW.text_hash = md5(NEW.text)::uuid; 
    RETURN NEW; 
END; 
$function$ 

在寫這個問題的過程中,我找到了答案,並會發布它下面。如果這個問題已經有重複,請通知我,我將刪除它,我找不到任何。這裏

回答

1

問題是我UPSERT處理,在此期間,該表的架構是拉進,導致查詢的動態創建,其中包括像這樣的臺詞:

ON CONFLICT ON CONSTRAINT congressional_bill_actions_bill_kid_date_action_actor_key DO UPDATE SET created_at = EXCLUDED.created_at, 

因爲created_at是被自動設置爲EXCLUDED.created_at,這會導致默認值覆蓋現有值,因爲我正在指示它這樣做。

所以在編寫UPSERT處理程序時,這似乎是要注意的事情。

(注意:避免這種情況的方法根本不在於column_default不爲空的任何列)

相關問題