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

¿Cómo guardar un dato con una coma en carácter variable que pasa por un disparador?

Puedes usar format() para hacer que la creación de una consulta SQL dinámica sea mucho más fácil, ya que tratará automáticamente con identificadores y literales correctamente. Una cosa que la gente suele pasar por alto es que puede expandir una sola expresión de registro a todas sus columnas usando (...).* - esto también funciona para NEW y OLD registrar variables en un activador, p. select (new).*

También puede pasar variables a un SQL dinámico con using palabra clave del execute declaración. No hay necesidad de convertir el registro entre un registro y una representación de texto.

Usando esa posibilidad, su función de activación se puede simplificar a:

DECLARE 
  l_sql text;
BEGIN
    IF TG_TABLE_SCHEMA = 'public' THEN
      newtable := TG_TABLE_NAME || '_actividad';
    ELSE
      newtable := TG_TABLE_SCHEMA || '_' || TG_TABLE_NAME || '_actividad';
    END IF;

    PERFORM creartablaactividad(TG_TABLE_SCHEMA, TG_TABLE_NAME);
    l_sql := 'INSERT INTO actividad.%I  SELECT current_user, current_timestamp, %L, ($1).*';

    IF TG_OP = 'DELETE' THEN
      execute format(l_sql, newtable, 'D') using OLD;
      RETURN OLD;
    ELSE
      -- covers UPDATE and INSERT
      execute format(l_sql, newtable, 'U') using NEW;
      RETURN NEW;
    END IF;

    RETURN NULL; -- result is ignored since this is an AFTER trigger
END;

Usar marcadores de posición como %I y %L también hace posible definir el SQL real solo una vez y reutilizarlo. Esos "parámetros" son reemplazados por format() función (que conserva el $1 )

Tenga en cuenta el uso de ($1).* dentro de la cadena SQL. Eso hará que execute instrucción expanda el parámetro de registro $1 a todas sus columnas. El registro en sí se pasa "de forma nativa" con USING palabra clave.

El uso de INSERT sin una lista de columnas de destino (insert into some_table ... en lugar de insert into some_table (col1, col2, ...) ... ) es algo bastante frágil de hacer. Si el origen y el destino no coinciden, la inserción puede fallar fácilmente. .

Si no ejecuta informes masivos en las tablas de auditoría (donde tener nombres de columna explícitos sería mucho más eficiente), es posible que desee pensar en un activador de auditoría más genérico usando un JSON o HSTORE columna para almacenar todo el registro. Hay varios activadores de auditoría listos para usar disponibles: