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
相关产品推荐
相关产品推荐

