【问题标题】:Syntax error on $$ double dollars in Postgres function creation [duplicate]Postgres函数创建中$$双美元的语法错误[重复]
【发布时间】:2020-05-14 14:02:12
【问题描述】:

我试图在 postgres 实例启动期间创建一个简单的函数。我通过将一些.sh 文件映射到/docker-entrypoint-initdb.d 目录来做到这一点。

我不断遇到这个简单功能的问题。

#!/bin/bash
set -e

psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
    CREATE OR REPLACE FUNCTION hi() RETURNS TEXT AS $$
    BEGIN
        RETURN 'hi'
    END;
    $$;
EOSQL
2020-01-29 05:12:30.817 UTC [62] ERROR:  syntax error at or near "1" at character 49
2020-01-29 05:12:30.817 UTC [62] STATEMENT:  CREATE OR REPLACE FUNCTION hi() RETURNS TEXT AS 1
        BEGIN
            RETURN 'hi'
        END;
ERROR:  syntax error at or near "1"
LINE 1: CREATE OR REPLACE FUNCTION hi() RETURNS TEXT AS 1

如果我将其更改为具有实际内容的内容:

#!/bin/bash
set -e

psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
    CREATE OR REPLACE FUNCTION hi() RETURNS TEXT AS $func$
    BEGIN
        RETURN 'hi'
    END;
    $func$;
EOSQL

我在同一个地方遇到另一个错误:

2020-01-29 05:17:36.161 UTC [62] ERROR:  syntax error at or near "$" at character 49
2020-01-29 05:17:36.161 UTC [62] STATEMENT:  CREATE OR REPLACE FUNCTION hi() RETURNS TEXT AS $
        BEGIN
            RETURN 'hi'
        END;
ERROR:  syntax error at or near "$"
LINE 1: CREATE OR REPLACE FUNCTION hi() RETURNS TEXT AS $

使用最新的 postgres 版本运行:12.1

这个函数定义到底有什么问题,为什么会出现这个错误?

【问题讨论】:

    标签: bash postgresql function heredoc


    【解决方案1】:

    &lt;&lt;-EOSQLEOSQL 的脚本部分称为“此处文档”,该功能记录在the Bash Reference Manual, §3.6.6 "Here Documents"。根据该部分:

    如果 word [在您的情况下为 EOSQL] 的任何部分被引用,[...] here-document 中的行不会被扩展。如果 word 没有被引用,则 here-document 的所有行都会进行参数扩展、命令替换和算术扩展,[…]

    换句话说——因为你没有引用 EOSQL 的任何部分,Bash 正在对 here-document 的内容执行参数扩展(和其他类似的替换),其中包括将 $$ 替换为进程—— ID 和 $func 和空字符串,在 PostgreSQL 看到它们之前。

    如果您只是将&lt;&lt;-EOSQL 更改为&lt;&lt;-'EOSQL',则不会这样做。

    【讨论】:

    • 谢谢!那成功了。你能引用那段来解释吗?
    • @MirroredFate:当然——完成。
    【解决方案2】:

    $func$$bash 中的变量。第一个是 shell 实例的进程 ID,它解释了错误输出中的数字;第二个只是一个普通的用户定义变量,可能是空的,所以$test$ 变成了$(因为$test 被一个空字符串替换)。

    您可以使用\$\$\$test\$ 转义bash 认为重要的美元符号,也可以使用&lt;&lt;-'EOSQL' 在heredoc 上使用单引号(无变量替换)语义。

    这与 PostgreSQL 无关,它是 bash 做它认为你想做的事。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-11
      • 1970-01-01
      • 2017-10-17
      • 1970-01-01
      相关资源
      最近更新 更多