He creado algo como esto:
begin;
create table test (
id integer
);
insert into test(id) select generate_series(1,100);
create or replace function trg_check_max_4_updated_records()
returns trigger as $$
declare
counter_ integer := 0;
tablename_ text := 'temptable';
begin
raise notice 'trigger fired';
select count(42) into counter_
from pg_catalog.pg_tables where tablename = tablename_;
if counter_ = 0 then
raise notice 'Creating table %', tablename_;
execute 'create temporary table ' || tablename_ || ' (counter integer) on commit drop';
execute 'insert into ' || tablename_ || ' (counter) values(1)';
execute 'select counter from ' || tablename_ into counter_;
raise notice 'Actual value for counter= [%]', counter_;
else
execute 'select counter from ' || tablename_ into counter_;
execute 'update ' || tablename_ || ' set counter = counter + 1';
raise notice 'updating';
execute 'select counter from ' || tablename_ into counter_;
raise notice 'Actual value for counter= [%]', counter_;
if counter_ > 4 then
raise exception 'Cannot change more than 4 rows in one trancation';
end if;
end if;
return new;
end; $$ language plpgsql;
create trigger trg_bu_test before
update on test
for each row
execute procedure trg_check_max_4_updated_records();
update test set id = 10 where id <= 1;
update test set id = 10 where id <= 2;
update test set id = 10 where id <= 3;
update test set id = 10 where id <= 4;
update test set id = 10 where id <= 5;
rollback;
La idea principal es tener un disparador en 'antes de actualización para cada fila' que crea (si es necesario) una tabla temporal (que se deja caer en el fin de la transacción). En esta tabla solo hay una fila con un valor, es decir, el número de filas actualizadas en la transacción actual. Para cada actualización, el valor se incrementa. Si el valor es mayor que 4, la transacción se detiene.
Pero creo que esta es una solución incorrecta para su problema. ¿Cuál es el problema para ejecutar una consulta incorrecta sobre la que ha escrito, dos veces, por lo que tendrá 8 filas modificadas? ¿Qué pasa con las filas de borrado o truncarlas?
Consideré el uso de la consulta normal + retrotracción si las filas afectadas son mayores que max, y eso parece tener el mejor valor según veo. Bueno, en el 99% + habrá buenas consultas (4 filas actualizadas como máximo), pero esto es solo seguridad adicional para el sistema. La tabla con este 'problema' es bastante grande y crítica para el sistema, por lo que restaurarla después de una consulta errónea puede ser doloroso para todos. Gracias a todos por las respuestas. No sé cuál aceptar porque todos son útiles :) – sbczk
¿Por qué quieres hacer eso? Tal vez hay una manera mucho más fácil de hacer eso que una consulta tan extraña. Además ... el uso del recuento (si fuera posible) será más lento mientras la tabla crece. –
¿Entonces piensas que cuando tienes un máximo de 4 filas modificadas, la consulta no puede ser mal escrita? Esto suena como una especie de sensación de seguridad falsa. –