#sql #postgresql
#sql #postgresql
Вопрос:
Я хочу создать триггерную функцию для отправки столбца со значением, сгенерированным из объединения двух других столбцов с заранее заданными значениями. Если значение уже существует, я бы увеличил третий столбец соответственно объединенному значению.
ПРИМЕР:
column1 -> 'aaa'
column2 -> 'bbb'
concatenated value -> 'aaabbb'
column1 -> 'xxx'
column2 -> 'yyy'
concatenated value -> 'xxxyyy'`
Если уже есть строки со значением ‘aaabbb’, то третий столбец будет увеличен как:
1 | aaabbb
2 | aaabbb
3 | aaabbb
1 | xxxyyy
2 | xxxyyy
Комментарии:
1. Итак, вы хотите вставить новую строку с объединенным значением и количеством значений, которые ему соответствуют?
2. Точно, ваше описание было идеальным.
3. Итак, после вставки
column1
было бы'aaabbb'
,column2
было быNULL
иcolumn3
количество совпадающих значений? Или обаcolumn1
иcolumn2
являются объединенным значением?4. Объединенное значение из
column1
иcolumn2
будет вставлено в другой столбец и будет содержать столбец для подсчета объединенных значений. В итоге будет четыре столбца.5. Как эмпирическое правило для реляционной базы данных: не храните данные, которые могут быть легко получены из существующих значений. Создайте представление, которое возвращает эту информацию, и забудьте о повторном сохранении данных.
Ответ №1:
Не уверен, хотите ли вы сохранить объединенное значение. Это не сохраняет его, но вы, конечно, можете сохранить объединенное значение в new.concatenated_column
:
create function f_test ()
returns trigger
language plpgsql
as $$
begin
new.column3 := (
select coalesce(max(t.column3) 1, 1)
from test as t
where t.column1 || t.column2 = new.column1 || new.column2
);
return new;
end;
$$
create trigger tr_test
before insert
on test
for each row execute procedure f_test();
Ответ №2:
Вы можете попробовать использовать этот код, его работа заключается только в insert. Но вы также можете дублировать триггер и изменять его на update.
create table test ( column1 varchar, column2 varchar, column3 varchar);
CREATE TRIGGER t_before_test
BEFORE insert
ON test
FOR EACH ROW
EXECUTE PROCEDURE fnt_test();
CREATE OR REPLACE FUNCTION fnt_test()
RETURNS trigger LANGUAGE plpgsql AS
$BODY$
declare
v_count int := 0;
BEGIN
select 1 into v_count from test where column1 = NEW.column1 and column2 = NEW.column2;
if ( NEW.column1 is not null and NEW.column2 is not null and v_count > 0) then
NEW.column3 := NEW.column1 || NEW.column2;
end if;
RETURN NEW;
END;
$BODY$;
insert into test ( column1, column2 ) values ( '1', '2');
select * from test;