代码之家  ›  专栏  ›  技术社区  ›  Dave Vogt

调试PostgreSQL触发器

  •  22
  • Dave Vogt  · 技术社区  · 16 年前

    我在PostgreSQL中有一个触发器,我不能直接开始工作(什么都不做)。为了理解,我是如何定义它的:

    CREATE TABLE documents (
        ...
        modification_time timestamp with time zone DEFAULT now()
    );
    
    CREATE FUNCTION documents_update_mod_time() RETURNS trigger
    AS $$
        begin
        new.modification_time := now();
        return new;
        end
    $$
        LANGUAGE plpgsql;
    
    CREATE TRIGGER documents_modification_time
        BEFORE INSERT OR UPDATE ON documents
        FOR EACH ROW
        EXECUTE PROCEDURE documents_update_mod_time();
    

    现在让它更有趣一点……如何调试触发器?

    3 回复  |  直到 13 年前
        1
  •  46
  •   Kev    16 年前
    1. 在触发器函数中使用以下代码,然后查看pgadmin3中的“messages”选项卡或psql中的输出:

      RAISE NOTICE 'myplpgsqlval is currently %', myplpgsqlval;       -- either this
      RAISE EXCEPTION 'failed';  -- or that
      
    2. 要查看实际调用的触发器、调用的次数等,下面的语句是生命保护程序的选择:

      EXPLAIN ANALYZE UPDATE table SET foo='bar'; -- shows the called triggers
      

      注意,如果您的触发器没有被调用,并且您使用继承,那么可能是您只在父表上定义了一个触发器,而子表不会自动继承触发器。

    3. 要单步执行该函数,可以使用pgadmin3内置的调试器,默认情况下,在Windows上启用该调试器;您所要做的只是执行 …\8.3\share\contrib\pldbgapi.sql 针对正在调试的数据库,重新启动pgadmin3,右键单击触发器函数,单击“设置断点”,然后执行将导致触发触发器的语句,如上面的update语句。

        2
  •  3
  •   Kev    16 年前

    您可以在触发器函数内使用“raise notice”语句来调试它。调试根本不被调用的触发器是另一回事。

    如果您在触发器函数中添加了“引发异常”,您仍然可以进行插入/更新吗?

    另外,如果更新测试与插入测试发生在同一个事务中,那么now()将是相同的(因为每个事务只计算一次),因此更新似乎不会做任何事情。如果是这样,可以在单独的事务中进行,或者如果这是一个单元测试,而您不能这样做,那么可以使用clock_timestamp()。

    我有一个单元测试,它取决于事务之间经过的时间,因此在单元测试的开始,我有如下内容:

    ALTER TABLE documents
       ALTER COLUMN modification_time SET DEFAULT clock_timestamp();
    

    然后在触发器中,使用“设置修改时间=默认”。

    所以通常它不做额外的计算,但在单元测试期间,这允许我在pg_sleep之间进行插入,以模拟时间传递,并将其反映在数据中。

        3
  •  3
  •   Dave Vogt    16 年前

    结果发现我在上面的问题中使用了继承,并且忘记提到它。现在,对于每个可能遇到这种情况的人,这里有一些调试提示:

    使用以下代码调试触发器正在执行的操作:

    RAISE NOTICE 'test';       -- either this
    RAISE EXCEPTION 'failed';  -- or that
    

    要查看实际调用的触发器、调用的次数等,下面的语句是生命保护程序的选择:

    EXPLAIN ANALYZE UPDATE table SET foo='bar'; -- shows the called triggers
    

    还有一件事我以前不知道: 触发器仅在更新其定义的准确表时触发。如果使用继承,还必须在子表上定义它们!