0

pg_dump を使用して SQL ダンプ ファイルを作成しました。このエクスポート ファイルには、$$ 文字を含む関数が含まれています。psql -f < filename> でファイルをインポートしても問題ありません。

SQLExec タスクを使用して ant でファイルをインポートする場合、次のような例外が発生します。

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 ファミリは、値がトランザクション内で変更されないため、安定しているとみなされることにも注意してください。

  • PostgreSQLにも密接に関連する関数があり、age()ほとんど同じではありませんが、同じことを行います。これは、標準の年と月で「記号的な」結果を返します。したがって、 を使用した式でage()は、長期間にわたって異なる結果が得られる可能性があります。

これらはすべて同等です - より長い期間で逸脱している最後の2つを除いて:

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 に答える