如何从Bash向psql传递Timestamp参数?
解决psql传递Timestamp参数的转义问题
这个问题的核心原因很明确:当你直接把字面量时间字符串(比如2017-10-23 10:42:48)拼接到SQL语句中时,PostgreSQL会把2017-10-23当成数学减法运算(2017减10减23),后面的10:42:48就成了语法错误;而NOW() - INTERVAL '5 months'是合法的SQL表达式,不需要引号包裹,所以能正常执行。
最安全且通用的解决方案是使用psql的变量参数化功能,它会自动处理不同类型的输入(字面量或表达式),同时避免SQL注入风险,完全不需要手动转义引号。具体操作如下:
1. 格式检查语句
psql -v since="$since" --command "SELECT (:since)::TIMESTAMPTZ;"
2. 调用函数的语句
psql -v since="$since" --command "SELECT myfunc(:since);" "$DBNAME"
为什么这个方法有效?
- 当
$since是字面量时间(比如2017-10-23 10:42:48)时,psql会自动为其添加单引号,生成合法的SQL:SELECT ('2017-10-23 10:42:48')::TIMESTAMPTZ; - 当
$since是SQL表达式(比如NOW() - INTERVAL '5 months')时,psql会直接解析表达式,不需要额外处理,保持原有的语法正确性。
如果你非要手动处理引号(不推荐,存在SQL注入风险且兼容性差),需要区分输入类型:
- 对于字面量时间字符串,必须用单引号包裹:
cmd="SELECT myfunc('$since');" psql --command "$cmd" "$DBNAME" - 对于SQL表达式,不能加引号,保持原样拼接。但这种方式需要额外判断输入类型,非常麻烦,远不如参数化变量的方式可靠。
内容的提问来源于stack exchange,提问作者Michal Špondr
相关产品推荐
相关产品推荐

