Python Postgres触发器找不到返回

Python Postgres触发器找不到返回,python,postgresql,triggers,sqlalchemy,flask-sqlalchemy,Python,Postgresql,Triggers,Sqlalchemy,Flask Sqlalchemy,这是我的扳机: CREATE OR REPLACE FUNCTION update_played () RETURNS trigger AS $BODY$ DECLARE v_count_played integer; BEGIN SELECT count(*) INTO STRICT v_count_played FROM history WHERE song_id = NEW.song_id; EXCEPTION WHEN NO_DATA_FOU

这是我的扳机:

CREATE OR REPLACE FUNCTION update_played ()
  RETURNS trigger
AS
$BODY$
  DECLARE
    v_count_played integer;
BEGIN

    SELECT count(*) INTO STRICT v_count_played FROM history WHERE song_id = NEW.song_id;
    EXCEPTION
      WHEN NO_DATA_FOUND THEN
        RAISE EXCEPTION 'history count for song % not found', NEW.song_id;
      WHEN TOO_MANY_ROWS THEN
        RAISE EXCEPTION 'history count did not aggregate';

    EXECUTE 'UPDATE song SET count_played = $1 WHERE id = $2'
        USING v_count_played, NEW.song_id;

    RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;


create trigger update_played_trigger
after insert on history
for each row
execute procedure update_played();
它给出了错误:

sqlalchemy.exc.InternalError:(psycopg2.InternalError)控制到达触发器过程的末尾,但未返回


您误解了
异常
关键字。如果我改变你的缩进来匹配它的工作原理,可能会帮助你理解<代码>异常与
开始
结束
一起作为块的一部分出现,就像其他语言中的
try{}catch{}
一样。所以它是这样工作的:

BEGIN

    SELECT count(*) INTO STRICT v_count_played 
    FROM history WHERE song_id = NEW.song_id;

EXCEPTION
    WHEN NO_DATA_FOUND THEN
        RAISE EXCEPTION 'history count for song % not found', NEW.song_id;
    WHEN TOO_MANY_ROWS THEN
        RAISE EXCEPTION 'history count did not aggregate';

        EXECUTE 'UPDATE song SET count_played = $1 WHERE id = $2'
            USING v_count_played, NEW.song_id;

        RETURN NULL;
END;
这里发生的事情是运行
选择
。如果发现
无数据
异常,则
引发
。如果
引发的
异常行太多,则在同一块中,
引发异常
后存在无法访问的代码,该异常执行
并返回

如果
选择中没有异常,则不会采取进一步的操作,该过程只会退出,不返回任何内容

我认为你打算写的是:

BEGIN
    BEGIN
      SELECT count(*) INTO STRICT v_count_played FROM history WHERE song_id = NEW.song_id;
    EXCEPTION
      WHEN NO_DATA_FOUND THEN
        RAISE EXCEPTION 'history count for song % not found', NEW.song_id;
      WHEN TOO_MANY_ROWS THEN
        RAISE EXCEPTION 'history count did not aggregate';
    END;

    EXECUTE 'UPDATE song SET count_played = $1 WHERE id = $2'
        USING v_count_played, NEW.song_id;

    RETURN NULL;
END;

谢谢你明确的回答。我注意到它在
历史记录
中的所有行中都运行(现在已修复),尽管它在后续插入中没有运行。触发器就是这样工作的吗?如果我添加一个新触发器,它将在第一次运行时对每一个现有行执行该操作,即使只插入一个新行?@Tjorriemorrie-Er。否。触发器对现有行不执行任何操作,只对新行触发。我怀疑你的触发逻辑不对。如果你不明白,请发布一个新的问题,并链接回这个问题,以了解上下文。