从Bash传递变量到psql

6

我在将变量从Bash传递到psql命令时遇到了一些问题。我无法确定在哪里放置引号或括号。

本质上,我正在尝试将今天的日期插入到PostGres表格的日期列中。

today=$(date +"%m-%d-%Y")

echo $today
#10-05-2015

psql -h hostname -U admin -d db-p 5439 -c \
"INSERT INTO public.log_table (day, rowcount) VALUES ("$today", $rowcount)";

我已经尝试过以不加引号的$today和其他几种变化方式来调用它,但是无法得到我想要的结果,即 10-05-2015。相反,插入了-2010的值,这是10减去5再减去2015的结果……

3个回答

2
要在引号中嵌入引号,您需要通过在引号前加上反斜杠(\)来转义它们。现在,bash会将紧挨着$today左侧的引号解释为终止一个带引号的字符串,右侧的引号则被解释为开始一个新的字符串。
看起来这就是您想要做的事情:
psql -h hostname -U admin -d db-p 5439 -c \
"INSERT INTO public.log_table (day, rowcount) VALUES (\"$today\", $rowcount)";

或者,您可以在命令中使用撇号而不是引号,这将更符合标准SQL语法:

psql -h hostname -U admin -d db-p 5439 -c \
"INSERT INTO public.log_table (day, rowcount) VALUES ('$today', $rowcount)";

您不能使用撇号引用整个命令,因为这会抑制$today的扩展。

2

您需要转义引号:

"INSERT INTO public.log_table (day, rowcount) VALUES (\"$today\", $rowcount)";

如果不对它们进行转义,shell会将它们解释为字符串的结尾。然后插入日期(因为shell正在将先前的字符串与此非引用字符串连接),最后,在日期之后,shell看到另一个字符串来完成SQL命令的其余部分并将其连接到其他字符串中。

因此,psql接收到的是

INSERT INTO public.log_table (day, rowcount) VALUES (10-05-2015, <rowcount_value>)

它将其视为整数,因此psql解析出您要插入整数-2010

在正确引用后,psql收到:

INSERT INTO public.log_table (day, rowcount) VALUES ("10-05-2015", <rowcount_value>)

我有另一个与转义相关的问题。查询有点不同,看起来像 "BEGIN READ WRITE; COPY public.tablename FROM 's3://location/filename.txt' " 我想创建一个变量,如 locationname=directoryname 并在最后一部分中调用它。因此,查询将看起来像 "BEGIN READ WRITE; COPY public.tablename FROM 's3://$locationname/filename.txt' " 这次我该如何转义引号? - simplycoding
@simplycoding 这次不需要转义引号 - Alvaro Gutierrez Perez

1
给出的答案是正确的,它们可以解决你的查询问题,但如果字符串本身包含引号,像那样插值 bash 变量仍然可能失败。更简单、更安全的选择是使用 Postgres 的美元引用字符串
对于你的查询,你可以这样做:
today=$(date +"%m-%d-%Y")

psql -h hostname -U admin -d db-p 5439 -c \
"INSERT INTO public.log_table (day, rowcount)
VALUES (\$\$ $today \$\$, $rowcount)";

更多细节:https://textquery.app/2022/07/15/properly-escape-postgres-sql-queries-bash/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接