【问题标题】:how to get the affected base table row count in a statement level trigger如何在语句级触发器中获取受影响的基表行数
【发布时间】:2016-05-06 04:44:57
【问题描述】:

我有这些表:

CREATE EXTENSION citext;
CREATE EXTENSION "uuid-ossp";

CREATE TABLE cities
(
    city_id serial PRIMARY KEY,
    city_name citext NOT NULL UNIQUE
);

INSERT INTO cities(city_name) VALUES
('New York'), ('Paris'), ('Madrid');

CREATE TABLE etags
(
    etag_name varchar(128) PRIMARY KEY,
    etag_value uuid
);

INSERT INTO etags(etag_name, etag_value)
VALUES ('cities', uuid_generate_v4());

我想在城市表更改时更新城市 etag。如果insert、update或delete语句不影响任何行,我想避免更改城市etag,所以我编写了以下语句级触发器:

CREATE OR REPLACE FUNCTION update_etag()
  RETURNS trigger AS
$BODY$
    DECLARE 
        record_count integer;
        vetag_name varchar(128);
    BEGIN
    GET DIAGNOSTICS record_count = ROW_COUNT;
    vetag_name := TG_ARGV[0];
    RAISE NOTICE 'affected %:%', vetag_name, record_count;
    IF record_count = 0 THEN 
        RETURN NULL;
    END IF;
    UPDATE etags SET etag_value = uuid_generate_v4() 
    WHERE etag_name = vetag_name;
    RETURN null;
    END;
$BODY$
  LANGUAGE plpgsql VOLATILE;

CREATE TRIGGER update_cities_etag_trigger
  AFTER INSERT OR UPDATE OR DELETE
  ON cities
  FOR EACH STATEMENT
  EXECUTE PROCEDURE update_etag('cities');

但是GET DIAGNOSTICS record_count = ROW_COUNT; 对我不起作用,因为它总是返回 0。

如果我执行以下操作:

 DELETE FROM cities;

以下是输出:

注意:受影响的城市:0 查询成功返回:3 行 受影响,47 毫秒的执行时间。

有没有办法确定在 PostgreSQL 语句级触发器中触发触发器的语句影响了多少行?

【问题讨论】:

    标签: postgresql triggers


    【解决方案1】:

    第 10 版

    CREATE TRIGGER

    ...
    [ REFERENCING { { OLD | NEW } TABLE [ AS ] transition_relation_name } [ ... ] ]
    ...
    

    https://www.postgresql.org/docs/current/static/release-10.html

    添加 AFTER 触发器转换表以记录更改的行 (Kevin 格里特纳,托马斯·芒罗)

    可以从服务器端编写的触发器访问转换表 语言。

    Example

    解决它:

    CREATE OR REPLACE FUNCTION update_etag()
      RETURNS trigger AS
    $BODY$
        DECLARE 
            record_count integer;
            vetag_name varchar(128);
        begin
        IF (TG_OP = 'DELETE') or (TG_OP = 'UPDATE') THEN
           select count(*) from oldtbl into record_count ;
        ELSE
           select count(*) from newtbl into record_count ;
        END IF;    
        vetag_name := TG_ARGV[0];
        RAISE NOTICE 'affected %:%:%', vetag_name,TG_OP, record_count;
        IF record_count = 0 THEN 
            RETURN NULL;
        END IF;
        UPDATE etags SET etag_value = uuid_generate_v4() 
        WHERE etag_name = vetag_name;
        RETURN null;
        END;
    $BODY$
      LANGUAGE plpgsql VOLATILE;
    
    CREATE TRIGGER update_ins_cities_etag_trigger
      AFTER INSERT
      ON cities
      REFERENCING NEW TABLE AS newtbl 
      FOR EACH STATEMENT
      EXECUTE PROCEDURE update_etag('cities'); 
    
    CREATE TRIGGER update_upd_cities_etag_trigger
      AFTER UPDATE
      ON cities
      REFERENCING OLD TABLE AS oldtbl 
      FOR EACH STATEMENT
      EXECUTE PROCEDURE update_etag('cities');  
    
    CREATE TRIGGER update_del_cities_etag_trigger
      AFTER DELETE
      ON cities
      REFERENCING OLD TABLE AS oldtbl 
      FOR EACH STATEMENT
      EXECUTE PROCEDURE update_etag('cities');  
    
    
    so=# INSERT INTO cities(city_name) VALUES
    so-# ('New York'), ('Paris'), ('Madrid');
    NOTICE:  affected cities:INSERT:3
    INSERT 0 3
    so=# select * from etags;
     etag_name |              etag_value              
    -----------+--------------------------------------
     cities    | dc7d1525-eea7-4822-b736-5141a20764f8
    (1 row)
    
    so=# insert into cities(city_name) values ('Budapest');
    NOTICE:  affected cities:INSERT:1
    INSERT 0 1
    so=# select * from etags;
     etag_name |              etag_value              
    -----------+--------------------------------------
     cities    | df835f44-dada-4a94-bb62-5890f2316103
    (1 row)
    
    so=# delete from cities where city_id > 42;
    NOTICE:  affected cities:DELETE:0
    DELETE 0
    so=# select * from etags;
     etag_name |              etag_value              
    -----------+--------------------------------------
     cities    | df835f44-dada-4a94-bb62-5890f2316103
    (1 row)
    

    【讨论】:

    • 如果您需要在 BEFORE 触发器中使用该计数?
    猜你喜欢
    • 2012-02-04
    • 2015-11-19
    • 1970-01-01
    • 2011-08-19
    • 1970-01-01
    • 2014-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多