Postgres 触发器未找到 return

Postgres trigger does not find return

这是我的触发器:

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 =  WHERE id = '
        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) control reached end of trigger procedure without RETURN

您误解了 EXCEPTION 关键字。如果我改变你的缩进以匹配它的工作方式,它可能会帮助你理解。 EXCEPTIONBEGINEND 一起作为块的一部分出现,就像其他语言中的 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 =  WHERE id = '
            USING v_count_played, NEW.song_id;

        RETURN NULL;
END;

这里发生的是你 运行 SELECT。如果有 NO_DATA_FOUND 异常,你 RAISE。如果有一个 TOO_MANY_ROWS 异常你 RAISE,那么在同一个块中有 unreachable code 在执行 EXECUTERAISE EXCEPTION 之后和 RETURN.

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

我认为您打算写的是:

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 =  WHERE id = '
        USING v_count_played, NEW.song_id;

    RETURN NULL;
END;