0

我使用 pg_dump 创建了一个 sql 转储文件。此导出文件包含包含 $$ 字符的函数。使用 psql -f <filename> 导入文件没有问题。

如果想使用 ant 使用 SQLExec 任务导入文件,我会收到如下异常:

org.postgresql.util.PSQLException: ERROR: syntax error at or near "$"

有没有办法导入包含 $$ 的文件?

在 postgres 日志中,似乎 SQLExec 任务将 $$ 转换为导致错误的 $。

错误:字符 87 处的“$”或附近的语法错误声明:CREATE FUNCTION process_create_servicenumber() RETURNS trigger LANGUAGE plpgsql AS $ BEGIN IF (TG_OP = 'DELETE') THEN RETURN OLD

这是我的方法

protected void importNewDbFromDumpFile() {

    final class SqlExecuter extends SQLExec {
        public SqlExecuter() {
            Project project = new Project();
            project.init();
            setProject(project);
            setTaskType("sql");
            setTaskName("sql");
        }
    }
    try {
        SqlExecuter executer = new SqlExecuter();
        executer.setSrc(new File(dbDumpFileLocation));
        executer.setClasspath(createClasspath());
        executer.setEscapeProcessing(true);
        executer.setDriver("org.postgresql.Driver");
        executer.setUrl("jdbc:postgresql://localhost/test");
        executer.setPassword("test");
        executer.setUserid("manager");
        executer.execute();
    } catch (Exception e) {
        log.info("Exception importing database ...", e);
    }
}
4

1 回答 1

2

$$只是美元报价的最低要求。通过在美元之间放置一个字符串,使其(非常!)不太可能与封闭文字中的字符串发生冲突:


CREATE OR REPLACE FUNCTION time_to_sec(timepoint timestamp with time zone)
  RETURNS bigint LANGUAGE plpgsql AS
$BODY$
DECLARE
 seconds bigint;
 secondsFromEpoch bigint;
 secondsFromMidnight bigint;
BEGIN
 secondsFromEpoch = EXTRACT(EPOCH FROM timepoint)::bigint;
 secondsFromMidnight = EXTRACT(EPOCH FROM CURRENT_TIMESTAMP::date)::bigint;
 seconds = secondsFromEpoch - secondsFromMidnight;
 return seconds;
END;
$BODY$;

更多建议

  • plpgsql 中的赋值运算符是:=. = 未记录在案,可能会在未来的版本中消失。更多在这个相关问题下。

  • 使用CURRENT_DATE而不是CURRENT_TIMESTAMP::date.

  • 这是允许的,但我建议不要在 plpgsql 中使用大小写混合的参数名称。它们不区分大小写。

  • 最重要的是,简化

    CREATE OR REPLACE FUNCTION time_to_sec2(timepoint timestamp with time zone)
      RETURNS bigint LANGUAGE plpgsql STABLE AS
    $BODY$
    BEGIN
        RETURN EXTRACT(EPOCH FROM timepoint - current_date)::bigint;
    END;
    $BODY$;
    

    甚至:

    CREATE OR REPLACE FUNCTION time_to_sec3(timepoint timestamp with time zone)
      RETURNS bigint LANGUAGE sql AS
    $BODY$
        SELECT EXTRACT(EPOCH FROM timepoint - current_date)::bigint;
    $BODY$;
    
  • 可以申报STABLE

另请注意,current_timestamp 系列函数有资格作为稳定函数,因为它们的值在事务中不会改变。

  • age()PostgreSQL中还有一个密切相关的函数,几乎但不完全一样:它返回一个带有标准年份和月份的“符号”结果。因此,表达式 withage()可以在较长时间内产生不同的结果。

这些都是等价的——除了最后两个偏离时间更长:

WITH x(t) AS (VALUES ('2012-07-20 03:51:26+02'::timestamptz))
SELECT time_to_sec(t)  AS t1
      ,time_to_sec2(t) AS t2
      ,time_to_sec3(t) AS t3
      ,EXTRACT(EPOCH FROM t - current_date)::bigint AS t4
      ,EXTRACT(EPOCH FROM age(t, current_date))::bigint AS t5 -- deviates
      ,EXTRACT(EPOCH FROM age(t))::bigint * -1  AS t6  -- deviates
FROM   x;

至于最初的问题:这个 PostgreSQL 错误消息并不一定意味着问题出在美元符号上:

错误:“$”处或附近的语法错误

大多数情况下,;该行之前缺少它。或者可能是 XML 中未转义的特殊字符,例如< > &?美元符号$应该没问题。但我不是蚂蚁专家。PostgreSQL 日志中应该有更多上下文。

于 2012-07-30T00:55:29.303 回答