用触发器函数替代DELETE操作:如何返回受影响行数?
如何让替代DELETE的触发器函数返回受影响行数
首先得理清你的场景:你用触发器把DELETE操作替换成了UPDATE(设置归档标记),但原来的DELETE语句会返回受影响行数(比如DELETE 1),现在触发器返回NULL,导致执行DELETE时只会返回DELETE 0,但你想知道实际被UPDATE归档的行数对吧?
这里有两种实用的解决方案,根据你的需求来选:
方案1:在触发器函数中捕获并输出行数
你可以在触发器里执行UPDATE后,用GET DIAGNOSTICS捕获受影响的行数,然后通过RAISE NOTICE/INFO把这个信息返回给客户端。这样执行DELETE时,虽然命令本身返回DELETE 0,但你会收到明确的归档行数通知。
修改后的触发器函数:
CREATE OR REPLACE FUNCTION archive() RETURNS trigger AS $$ DECLARE command text := ' SET timeEnd = current_timestamp WHERE id = $1'; row_count integer; BEGIN -- 执行UPDATE操作 EXECUTE 'UPDATE "' || TG_TABLE_NAME || '"' || command USING OLD.id; -- 获取UPDATE影响的行数 GET DIAGNOSTICS row_count = ROW_COUNT; -- 输出到客户端(NOTICE会在控制台显示,INFO也可以,根据你的日志级别调整) RAISE NOTICE 'Archived % row(s)', row_count; RETURN NULL; END; $$ LANGUAGE plpgsql;
执行DELETE FROM foo_history WHERE id = 123;后,你会看到:
NOTICE: Archived 1 row(s)
DELETE 0
方案2:用存储过程封装操作,直接返回行数
如果希望直接得到行数返回值(而不是依赖通知),可以把归档逻辑封装成存储过程,替代直接执行DELETE语句。这样调用存储过程就能直接拿到受影响的行数。
创建存储过程:
CREATE OR REPLACE FUNCTION archive_foo_history(p_id integer) RETURNS integer AS $$ DECLARE row_count integer; BEGIN UPDATE foo_history SET timeEnd = current_timestamp WHERE id = p_id; GET DIAGNOSTICS row_count = ROW_COUNT; RETURN row_count; END; $$ LANGUAGE plpgsql;
调用方式:
SELECT archive_foo_history(123);
返回结果就是1,和原来DELETE语句的返回值逻辑一致。
为什么不能让DELETE直接返回UPDATE的行数?
这里要说明一下:PostgreSQL中,DELETE语句返回的行数是实际被删除的行数。因为你的触发器返回NULL,相当于告诉数据库“不要执行删除操作”,所以DELETE必然返回0。没办法让DELETE直接返回UPDATE的行数,只能通过上面两种方式间接获取。
内容的提问来源于stack exchange,提问作者jmls
相关产品推荐
相关产品推荐

