0

我有这些表:

  • 用户
  • 技能(名称- 字符串,计数- 整数)
  • Has_skills ( Skill_id - Skills.id, user_id users.id)

Has_skills 是前两个之间的多对多表,通过这些 FK:user_id (users.id) 和 Skill_id (skills.id)。

我想要做的是在将新行插入has_skills时更新技能内的计数列。我想通过表has_skills上的更新触发器来做到这一点。我将通过选择查询获得 count 的新值:

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

上面的 ID 是硬编码的 (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;

扳机:

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

我成功创建了函数和触发器,但是当我将新数据插入has_skills时,它不会更改Skills中的计数列。可能是什么问题呢?

4

2 回答 2

1

触发器功能中根本不需要选择。技能表的键直接在 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();
于 2019-06-17T02:26:24.440 回答
0

我对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();
于 2019-06-16T02:02:24.250 回答