2015-02-10 69 views
0

我有一个简单的表:无限递归检测(psycopg2,蟒2.7,Postgres的9.3)

CREATE TABLE IF NOT EXISTS someTable (
    row_id     smallserial PRIMARY KEY, 
    name     text NOT NULL, 
    creation_date   timestamp with time zone DEFAULT current_timestamp, 
    last_updated_date  timestamp with time zone DEFAULT current_timestamp, 
    created_by    text DEFAULT "current_user"(), 
    last_updated_by  text DEFAULT "current_user"() 
); 

具有以下规则:

CREATE OR REPLACE RULE log_update_some_table AS 
    ON UPDATE TO someTable 
    DO ALSO 
     UPDATE someTable 
      SET last_updated_date = current_timestamp, 
       last_updated_by = current_user; 

和一个非常简单的函数在plpgsql:

CREATE OR REPLACE FUNCTION test_update() 
RETURNS void AS $$ 
BEGIN 
    UPDATE someTable 
    SET name = 'test' 
    WHERE row_id = 1; 
END; 
$$ LANGUAGE plpgsql; 

有人会认为该函数会运行得很好,但我得到以下错误:

psycopg2.ProgrammingError: infinite recursion detected in rules for relation "sometable" 
CONTEXT: SQL statement "UPDATE someTable 
    SET name = 'test' 
    WHERE row_id = 1" 
PL/pgSQL function test_update() line 3 at SQL statement 

为什么不能正常工作,我该如何解决?谢谢!

+0

那么这是罪魁祸首?规则的目标是每当有人更新'someTable'时只更新'last_updated_date'和'last_updated_by'字段。我需要改变什么来防止它无限循环?我是否摆脱了“DO ALSO”条款? – Teboto 2015-02-10 02:03:39

回答

1

所以在someTable您更新规则触发对someTable其执行哪些更新someTable执行该规则的规则更新...

我会使用一个简单的触发器代替,像这样:

create or replace function log_update_some_table() returns trigger as $$ 
begin 
    NEW.last_updated_date = current_timestamp; 
    NEW.last_updated_by = current_user; 
    return NEW; 
end; 
$$ language plpgsql; 

create trigger log_update_some_table_trigger 
before update on someTable 
for each row execute procedure log_update_some_table(); 

应该做的伎俩。这将修改之前的行发生更新,而不是向队列添加另一个更新(这会触发递归问题)。

+0

这也不起作用:(完全删除触发器摆脱了错误,但它会很好的自动更新这些字段。 – Teboto 2015-02-10 03:12:44

+0

你是什么意思的“不起作用”?对我来说工作正常在添加触发器之前,你是否放弃了规则? – 2015-02-10 04:26:56

+0

是的,我用你的触发器和函数取代了我的规则当我试图更新时,我仍然得到递归错误,这很奇怪 – Teboto 2015-02-10 06:16:59