Обновите другую таблицу с помощью триггера, где новое значение является результатом запроса SELECT - PullRequest
0 голосов
/ 15 июня 2019

У меня есть эти таблицы:

  • Пользователи
  • Навыки ( имя - строка, количество - целое число)
  • Has_skills ( skill_id - skill.id, user_id users.id)

Has_skills - таблица «многие ко многим» между первыми двумя через эти FK: user_id (users.id) и skill_id (skill.id).

Я хочу обновить столбец count внутри skill , когда новая строка вставлена ​​в has_skills . Я хочу сделать это через триггер обновления для таблицы has_skills . Новое значение для количества я получу через запрос выбора:

SELECT COUNT(*) AS cnt FROM skills 
JOIN has_skills hs ON skills.id = hs.skill_id 
WHERE hs.skill_id = 1;

Идентификатор выше жестко закодирован (1), но он работает.

Я также тестировал этот код изолированно, и он работает (хотя и жестко закодировано):

UPDATE skills
SET count = subquery.cnt
FROM (
    SELECT COUNT(*) AS cnt FROM skills 
    JOIN has_skills hs ON skills.id = hs.skill_id 
    WHERE hs.skill_id = 1
) AS subquery
WHERE skills.id = 1;
RETURN NEW;

Хорошо, так вот, вероятно, где проблема. Ниже представлена ​​функция триггера, а также сам триггер.

Функция:

CREATE OR REPLACE FUNCTION update_skill_count() RETURNS trigger AS
$func$
BEGIN
UPDATE skills
SET count = subquery.cnt
FROM (
    SELECT COUNT(*) AS cnt FROM skills 
    JOIN has_skills hs ON skills.id = hs.skill_id 
    WHERE hs.skill_id = NEW.skill_id
) AS subquery
WHERE skills.id = NEW.skill_id;
RETURN NEW;
END;
$func$ LANGUAGE plpgsql;

Trigger:

CREATE TRIGGER on_has_skills_insert
AFTER INSERT ON has_skills
FOR EACH ROW
EXECUTE PROCEDURE update_skill_count();

Я успешно создал функцию и триггер, но когда я вставляю новые данные в has_skills , он не меняет столбец count внутри skill . В чем может быть проблема?

Ответы [ 2 ]

1 голос
/ 17 июня 2019

Нет необходимости выбора в функции триггера вообще. Ключ для таблицы навыков доступен непосредственно в new.skill_id, поэтому просто используйте его напрямую:

-- trigger function and trigger
create or replace function update_skill_count() 
  returns trigger  
as $func$
begin
    update skills sk
       set count = count+1
     where sk.skill_id = new.skill_id;
    return new;
end;
$func$ language plpgsql;

create trigger on_has_skills_insert
       after insert on has_skills
       for each row
       execute procedure update_skill_count();
0 голосов
/ 16 июня 2019

Я не очень хорошо знаком с postgresql, но, имея представление об Oracle и SQL Server, похоже, что это проблема мутирующего триггера, а именно: Попытка чтения или записи в одну и ту же таблицу в пределах триггера уровня строки, для котороготриггер размещен.

Одним из способов избавления от мутирующей проблемы триггера / таблицы может быть изменение триггера уровня строки на триггер уровня оператора и, соответственно, изменение функции.Вот псевдокод, который вы можете попробовать (не предоставляя точный проверенный код, поскольку у меня не установлен Postgresql):

Функция :

CREATE OR REPLACE FUNCTION update_skill_count() RETURNS trigger AS
$func$
BEGIN
UPDATE skills
SET count = subquery.cnt
FROM (
        SELECT hs.skill_id, COUNT(*) AS cnt
        FROM   new_table hs
        GROUP  BY hs.skill_id
     ) AS subquery
WHERE skills.id = subquery.skill_id;
RETURN NULL;
END;
$func$ LANGUAGE plpgsql;

Триггер :

CREATE TRIGGER on_has_skills_insert
AFTER INSERT ON has_skills
REFERENCING NEW TABLE AS new_table
FOR EACH STATEMENT EXECUTE PROCEDURE update_skill_count();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...