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
关键字。如果我改变你的缩进以匹配它的工作方式,它可能会帮助你理解。 EXCEPTION
与 BEGIN
和 END
一起作为块的一部分出现,就像其他语言中的 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 在执行 EXECUTE
的 RAISE 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;
这是我的触发器:
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
关键字。如果我改变你的缩进以匹配它的工作方式,它可能会帮助你理解。 EXCEPTION
与 BEGIN
和 END
一起作为块的一部分出现,就像其他语言中的 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 在执行 EXECUTE
的 RAISE 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;