You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Play框架演化脚本执行PostgreSQL触发器创建失败求助

解决Play框架演化脚本中PostgreSQL触发器的美元引号错误

我之前也踩过这个坑!这个错误的核心原因是Play框架的演化脚本解析器会把PostgreSQL的美元引号(比如$BODY$)当成变量替换的标记,导致它没能正确识别完整的触发器函数体,提前截断了SQL语句,所以才会抛出“unterminated dollar-quoted string”的报错。

下面给你两个可靠的解决方案:

方案一:禁用Play的变量替换功能

在你的演化脚本开头(-- !Ups之后)添加-- !NoVariableSubstitution注释,明确告诉Play不要解析SQL中的$符号。这样PostgreSQL的美元引号语法就能正常被数据库识别了。

示例脚本:

-- !Ups
-- !NoVariableSubstitution

CREATE OR REPLACE FUNCTION update_match_processed()
RETURNS TRIGGER AS $BODY$
BEGIN
  IF NEW.status <> OLD.status and NEW.status = 'FT' THEN
    UPDATE "match" SET processed = true WHERE id = NEW.match_id;
  END IF;
  RETURN NEW;
END;
$BODY$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_update_match_processed
AFTER UPDATE ON event
FOR EACH ROW EXECUTE FUNCTION update_match_processed();

-- !Downs
DROP TRIGGER IF EXISTS trigger_update_match_processed ON event;
DROP FUNCTION IF EXISTS update_match_processed();

方案二:修改美元引号的分隔符

如果你的Play版本不支持!NoVariableSubstitution标记,那就把触发器函数体的分隔符从$BODY$改成更独特的字符串,比如$UPDATE_MATCH_TRIGGER$,避免被Play的解析器误判。

示例修改后的SQL:

-- !Ups
CREATE OR REPLACE FUNCTION update_match_processed()
RETURNS TRIGGER AS $UPDATE_MATCH_TRIGGER$
BEGIN
  IF NEW.status <> OLD.status and NEW.status = 'FT' THEN
    UPDATE "match" SET processed = true WHERE id = NEW.match_id;
  END IF;
  RETURN NEW;
END;
$UPDATE_MATCH_TRIGGER$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_update_match_processed
AFTER UPDATE ON event
FOR EACH ROW EXECUTE FUNCTION update_match_processed();

-- !Downs
DROP TRIGGER IF EXISTS trigger_update_match_processed ON event;
DROP FUNCTION IF EXISTS update_match_processed();

优先推荐方案一,因为它不需要修改你的核心SQL逻辑,只是让Play停止不必要的解析~

内容的提问来源于stack exchange,提问作者simonC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:47:44