Estoy escribiendo un activador de validación. El disparador debe validar que la suma de una matriz es igual a otro campo. Como tengo muchas instancias de esta validación, quiero escribir un solo procedimiento y crear múltiples disparadores, cada uno con un conjunto diferente de campos para verificar.
Por ejemplo, tengo el siguiente esquema:
CREATE TABLE daily_reports(
start_on date
, show_id uuid
, primary key(start_on, show_id)
-- _graph are hourly values, while _count is total for the report
, impressions_count bigint not null
, impressions_graph bigint[] not null
-- interactions_count, interactions_graph
-- twitter_interactions_count, twitter_interactions_graph
);
La validación debe confirmar eso impressions_count = sum(impressions_graph).
Estoy atascado porque no sé cómo acceder dinámicamente a un campo desde NEWplpgsql:
CREATE FUNCTION validate_sum_of_array_equals_other() RETURNS TRIGGER AS $$
DECLARE
total bigint;
array_sum bigint;
BEGIN
-- TG_NARGS = 2
-- TG_ARGV[0] = 'impressions_count'
-- TG_ARGV[1] = 'impressions_graph'
-- How to access impressions_count and impressions_graph from NEW?
RETURN NEW;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER validate_daily_reports_impressions
ON daily_reports BEFORE INSERT OR UPDATE
FOR EACH ROW EXECUTE
validate_sum_of_array_equals_other('impressions_count', 'impressions_graph');
Intenté ejecutar comandos dinámicos haciendo EXECUTE 'SELECT $1 FROM NEW' INTO total USING TG_ARGV[0], pero PL / PGsql se queja de que NUEVO es una relación desconocida.
Me dirijo específicamente a PostgreSQL 9.1.
postgresql
trigger
plpgsql
composite-types
François Beausoleil
fuente
fuente

NEWen este momento es usarhstore(NEW)y luego acceder a los campos comohstorevalores ingresados por nombre de columna. Lo que apesta, porque entonces todos están emitidostexty si quieres trabajar con ellos en su tipo original, tienes que devolverlos. Alternativamente, puede escribir un activador en otro lenguaje de procedimiento como PL / Python que tenga un mejor soporte para el acceso dinámico a registros.Respuestas:
En realidad, dado que
NEWes un tipo compuesto bien definido, puede acceder a cualquier columna con notación de atributo simple y llanamente. El propio SQL no permite identificadores dinámicos (nombres de tabla o columna, etc.). Pero puede usar SQL dinámico conEXECUTEuna función PL / pgSQL.Manifestación
El reparto a
textes opcional. Usándolo, porque funciona universalmente. Si conoce el tipo, puede trabajar sin lanzar ...Usando
format()con%s, porque el identificador ya se escapó en ese punto.De lo contrario, el uso
format()de%Ipara proteger contra la inyección de SQL.Alternativamente , en Postgres 9.3 o posterior, puede convertir
NEWa JSON conto_json()y acceder a las columnas como claves:Dado que el nombre de la columna no se concatena en una cadena SQL, la inyección SQL no es posible y no es necesario escapar del nombre.
db <> violín aquí (con en
EXCEPTIONlugar deNOTICEhacer visible el efecto).Relacionado:
fuente