2017-02-03 10 views
1

이 질문을 작성하는 과정에서 답변을 찾았으며 아래에 게시합니다. 이 질문이 이미 중복 된 경우 알려 주시면 제거하겠습니다. 찾을 수 없습니다.포스트 그레스 기본값은 생성시뿐만 아니라 업데이트시 적용됩니다.

나는 포스트 그레스의 테이블에 변경 사항을 추적하는 두 개의 열이있어 :

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 열이 기본값으로 업데이트된다는 것입니다. 현재 쿼리가 시작된 시점이 아니라 현재 트랜잭션이 시작된 시점).

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 그것을 값이 컬럼에 이미 있기 때문에, 변경되지, 너무합니다

내 예상되는 동작은 라인이 업데이트 될 때 updated_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$ 

이 질문을 작성하는 과정에서, 나는 대답을 발견하고 아래에 게시 할 예정입니다. 이 질문이 이미 중복 된 경우 알려 주시면 제거하겠습니다. 찾을 수 없습니다. created_at 이었기 때문에

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

:

답변

1

문제는 여기에 테이블의 스키마가 같은 라인을 포함 쿼리의 동적 생성의 결과에 끌려 가고 한 동안 내 UPSERT 처리했다 EXCLUDED.created_at에 자동으로 설정되면, 그렇게하도록 지시했기 때문에 기본값으로 인해 기존 값을 정확하게 덮어 쓰게됩니다.

그래서 UPSERT 처리기를 작성할 때이 사실을 알고 있어야합니다.

(참고 :이 문제를 피하는 방법은 column_default가 null이 아닌 열을 가져 오지 않는 것입니다.)