Postgresql insertar disparador para establecer el valor


Supongamos que en Postgresql, tengo una tabla T y una de sus columnas es C1.

Quiero activar una función cuando se agrega un nuevo registro a la tabla T. La función debe comprobar el valor de la columna C1 en el nuevo registro y si es null/empty entonces establecer su valor a 'X'.

Es esto posible?

Author: Bohemian, 2013-04-19

2 answers

Tiene razón en que necesita un disparador, porque establecer un valor predeterminado para la columna no funcionará para usted: los valores predeterminados solo funcionan para los valores null y no le ayudan a evitar valores en blanco.

En postgres hay un par de pasos para crear un disparador:

Paso 1: Cree una función que devuelva el tipo trigger:

CREATE FUNCTION my_trigger_function()
RETURNS trigger AS '
BEGIN
  IF NEW.C1 IS NULL OR NEW.C1 = '''' THEN
    NEW.C1 := ''X'';
  END IF;
  RETURN NEW;
END' LANGUAGE 'plpgsql'

Paso 2: Crear un disparador que dispara antes de insertar, que le permite cambiar los valores antes de que se insertan, que invoca el función anterior:

CREATE TRIGGER my_trigger
BEFORE INSERT ON T
FOR EACH ROW
EXECUTE PROCEDURE my_trigger_function()

Y ya está.

Ver el código anterior ejecutándose en SQLFiddle demostrando que funciona correctamente!


Mencionas en un comentario que el valor 'X' se recupera de una subconsulta. Si es así, cambie la línea relevante para algo así como:

NEW.C1 := (select some_column from some_table where some_condition);
 63
Author: Bohemian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-19 13:32:23

Es posible, pero es probable que sea mejor establecer una restricción predeterminada en la columna en su lugar. Al crear la tabla que se vería como:

create table mytable as (
    C1 thetype not null default X
);

Esto dice que si agrega una fila a la tabla y no especifica el valor para C1, entonces se usará X en su lugar. El valor not null no es necesario, pero evita que las actualizaciones anulen esa columna asumiendo que eso es lo que desea.

EDITAR: Esto solo funciona para la constante X, de sus comentarios parece que hay dos posibles solución.

Usando un disparador se vería algo como esto:

create function update_row_trigger() returns trigger as $$
begin
    if new.C1 is NULL then
        new.C1 := X;
    end if;
    return new;
end
$$ language plpgsql;

create trigger mytrigger before insert on mytable for each row execute procedure update_row_trigger();

La variable new en una función de activación es especial, representando la fila que se inserta. Especificar el desencadenador como un desencadenador before insert significa que puede modificar la fila antes de que se escriba en la tabla.

La segunda solución sería usar una columna calculada que Postgres define de una manera inusual:

create or replace function C1(row mytable) returns columntype immutable as $$
begin
    return X; -- where X is an expression using values from `row`
end
$$ language plpgsql;

Esto crea una función que toma una fila de su tabla y devuelve un valor, puede llamar está usando . notación sin embargo, lo que significa que se puede hacer:

select
    *,
    t.C1
from
    mytable t;

La declaración de que la función es inmutable es opcional, pero es necesaria si desea indexar la "columna". Usted sería capaz de indexar esta columna como esta:

create index on mytable (C1(mytable));
 7
Author: Steve,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-19 11:06:32