2011-07-07 61 views
2

我們的一個名爲rep_event的Postgres表具有一個timestamp列,用於指示每行何時插入。但所有的行都有一個時間戳值2000-01-01 00:00:00,所以有些東西沒有正確設置。在函數中調用now()

有一個將行插入表的函數,它是將行插入到表中的唯一代碼 - 沒有其他代碼插入到該表中。 (目前也沒有在該表更新行的任何代碼。)下面是函數的定義:

CREATE FUNCTION handle_event() RETURNS "trigger" 
AS $$ 
BEGIN 
    IF (TG_OP = 'DELETE') THEN 
     INSERT INTO rep_event SELECT 'D', TG_RELNAME, OLD.object_id, now(); 
     RETURN OLD; 
    ELSIF (TG_OP = 'UPDATE') THEN 
     INSERT INTO rep_event SELECT 'U', TG_RELNAME, NEW.object_id, now(); 
     RETURN NEW; 
    ELSIF (TG_OP = 'INSERT') THEN 
     INSERT INTO rep_event SELECT 'I', TG_RELNAME, NEW.object_id, now(); 
     RETURN NEW; 
    END IF; 
    RETURN NULL; 
END; 
$$ LANGUAGE plpgsql; 

下面是表的定義:

CREATE TABLE rep_event 
(
operation character(1) NOT NULL, 
table_name text NOT NULL, 
object_id bigint NOT NULL, 
time_stamp timestamp without time zone NOT NULL 
) 

正如你所看到的, now()函數被調用來獲取當前時間。在數據庫中執行「select now()」會返回正確的時間,因此在函數內調用now()會有什麼問題嗎?

+0

你能告訴我觸發器的定義嗎?它綁定了什麼桌子? – Flimzy

+1

很奇怪。在函數內部調用'now()'應該沒有問題,我敢打賭在其他地方有一些問題。順便說一句,如果這意圖是一個創建/修改時間戳,它應該最好是一個「帶時區的時間戳」(不是直觀的,但它是這樣),而不是'now()'更好地調用'CURRENT_TIMESTAMP'。但這不是必需的。 – leonbloy

回答

4

一個更簡單的解決方法就是修改表的定義有NOW()爲默認值:

CREATE TABLE rep_event (
    operation character(1) NOT NULL, 
    table_name text NOT NULL, 
    object_id bigint NOT NULL, 
    time_stamp timestamp without time zone NOT NULL DEFAULT NOW() 
); 

然後你就可以擺脫現在()調用您的觸發器。另外作爲一個附註,我強烈建議在你的函數中包括列順序... IOW;

INSERT INTO rep_event (operation,table_name,object_id,time_stamp) SELECT ... 

這樣,如果你曾經添加一個新的列或做出改變表的內部排序表的其他變化,你的功能不會突然斷裂。

1

您的問題必須在其他地方,因爲您的功能運作良好。創建測試數據庫,粘貼引用代碼並運行:

create table events (object_id bigserial, data text); 
create trigger rep_event 
    before insert or update or delete on events 
    for each row execute procedure handle_event(); 

insert into events (data) values ('v1'),('v2'),('v3'); 
delete from events where data='v2'; 
update events set data='v4' where data='v3'; 

select * from events; 
  object_id | data 
    -----------+------ 
      1 | v1 
      3 | v4 
select * from rep_event; 
  operation | table_name | object_id |   time_stamp   
    -----------+------------+-----------+---------------------------- 
    I   | events  |   1 | 2011-07-08 10:31:50.489947 
    I   | events  |   2 | 2011-07-08 10:31:50.489947 
    I   | events  |   3 | 2011-07-08 10:31:50.489947 
    D   | events  |   2 | 2011-07-08 10:32:12.65699 
    U   | events  |   3 | 2011-07-08 10:32:33.662936 
    (5 rows) 

檢查其他觸發,觸發創建命令等,並改變這種timestamp without timezonetimestamp with timezone