sql >> Base de Datos >  >> RDS >> PostgreSQL

Acceda al nombre de la columna dinámica del tipo de fila en la función de activación

Esto debería hacerlo:

CREATE OR REPLACE FUNCTION device_bid_modifiers_count_per()
  RETURNS TRIGGER AS
$func$
DECLARE
   devices_count int      := device_types_count();
   table_name    regclass := TG_ARGV[0];
   column_name   text     := TG_ARGV[1];
BEGIN
   LOCK TABLE device_types IN EXCLUSIVE MODE;
   EXECUTE format('LOCK TABLE %s IN EXCLUSIVE MODE', table_name);

   IF TG_OP = 'DELETE' THEN
      PERFORM validate_bid_modifiers_count(table_name
                                         , column_name
                                         , (row_to_json(OLD) ->> column_name)::bigint
                                         , devices_count);
   ELSE
      PERFORM validate_bid_modifiers_count(table_name
                                         , column_name
                                         , (row_to_json(NEW) ->> column_name)::bigint
                                         , devices_count);
   END IF;

   RETURN NEW;
END
$func$  LANGUAGE plpgsql;

La causa inmediata del mensaje de error fue el SELECT externo . Sin objetivo, debe reemplazarlo con PERFORM en plpgsql. Pero el PERFORM interno en la cadena de consulta pasada a EXECUTE también estaba mal. PERFORM es un comando plpgsql, no válido en una cadena SQL pasada a EXECUTE , que espera código SQL. Tienes que usar SELECT allá. Finalmente OLD y NEW no son visibles dentro de EXECUTE y cada uno plantearía una excepción propia de la forma en que lo tenía. Todos los problemas se solucionan dejando caer EXECUTE .

Una forma sencilla y rápida de obtener el valor de un nombre de columna dinámico de los tipos de fila OLD y NEW :enviar a json , luego puede parametrizar el nombre de la clave como se muestra. Debería ser un poco más simple y rápido que la alternativa con SQL dinámico, que también es posible, como:

  ...
  EXECUTE format('SELECT validate_bid_modifiers_count(table_name
                                                    , column_name
                                                    , ($1.%I)::bigint
                                                    , devices_count)', column_name)
  USING OLD;
  ...

Relacionado:

Aparte:no estoy seguro de por qué necesita las cerraduras pesadas.

Aparte 2:Considere escribir una función de disparador separada para cada disparador en su lugar. DDL más ruidoso, pero más simple y rápido de ejecutar.