Postgresql 错误:带时区的时间戳类型的输入语法无效

Postgresql 错误:带时区的时间戳类型的输入语法无效,postgresql,postgresql-9.3,Postgresql,Postgresql 9.3,我有一个PostgreSQL查询,如下所示,运行良好。我从shell脚本调用它,如下所示 Result=$(psql -U username -d database -t -c $'SELECT round(sum(i.total), 2) AS "ROUND(sum(i.total), 2)" FROM invoice i WHERE i.create_datetime = '2019-03-01 00:00:00-06' AND i.is_review = '1' AND

我有一个PostgreSQL查询,如下所示,运行良好。我从shell脚本调用它,如下所示

Result=$(psql -U username -d database -t -c 
$'SELECT round(sum(i.total), 2) AS "ROUND(sum(i.total), 2)" 
  FROM invoice i 
  WHERE i.create_datetime = '2019-03-01 00:00:00-06' 
  AND i.is_review = '1' AND i.user_id != 60;')
现在,我希望我硬编码为
I.create_datetime='2019-03-01 00:00:00-06'
的值替换为可变日期值

我试过两种方法

方式1:

Result=$(psql -U username -d database -t -c 
$'WITH var(reviewMonth) as (values(\'$reviewMonth\')) 
SELECT round(sum(i.total),2) AS "ROUND(sum(i.total),2)" 
FROM var,invoice i 
WHERE i.create_datetime = var.reviewMonth::timestamp 
AND i.is_review = \'1\' AND i.user_id != 60;')

方式2:

Result=$(psql -U username -d database -t -c 
$'SELECT round(sum(i.total),2) AS "ROUND(sum(i.total),2)" 
FROM invoice i 
WHERE i.create_datetime = \'$reviewMonth\' 
AND i.is_review = \'1\' AND i.user_id != 60;')
但这两方面都是错误的

方式1抛出错误为:

错误:运算符不存在:时区为文本的时间戳

方式2抛出错误为:

错误:时区为“$reviewMonth”的时间戳类型的输入语法无效


请建议我的方法。

您应该尝试使用psql变量。下面是一个例子:

# Put the query in a file, with the variable TSTAMP:

> echo "SELECT :'TSTAMP'::timestamp with time zone;" > query.sql
> export TSTAMP='2019-03-01 00:00:00-06'
> RESULT=$(psql -U postgres -t --variable=TSTAMP="$TSTAMP" -f query.sql )
> echo $RESULT
2019-03-01 06:00:00+00

注意我们如何在查询中格式化字符串文字替换::'TSTAMP'

你也可以自己做替换。下面是一个使用heredoc的示例:

> export TSTAMP='2019-03-01 00:00:01-06'
> RESULT=$(psql -U postgres -t << EOF
SELECT '$TSTAMP'::timestamp with time zone;
EOF
)
> echo $RESULT
2019-03-01 06:00:01+00
>导出TSTAMP='2019-03-01 00:00:01-06'
>结果=$(psql-U postgres-t echo$结果
2019-03-01 06:00:01+00
在本例中,我们没有使用psql的变量替换,因此我们必须引用像“$TSTAMP”这样的变量。使用heredoc使引用比使用-c简单得多,因为您没有尝试引用整个命令

编辑:更多的例子,因为它看起来不够清晰。TSTAMP不需要硬编码,它只是一个bash变量,可以像其他bash变量一样设置

> TSTAMP=$(date -d 'now' +'%Y-%m-01 00:00:00')
> RESULT=$(psql -U postgres -t << EOF
SELECT '$TSTAMP'::timestamp with time zone;
EOF
)
> echo $RESULT
2019-06-01 00:00:00+00
>TSTAMP=$(日期-d'现在'+%Y-%m-01 00:00:00')
>结果=$(psql-U postgres-t echo$结果
2019-06-01 00:00:00+00
然而,如果您真的只是在寻找月初,那么根本不需要shell变量

> RESULT=$(psql -U postgres -t << EOF
SELECT date_trunc('month', now());
EOF
)
> echo $RESULT
2019-06-01 00:00:00+00
>RESULT=$(psql-U postgres-t echo$RESULT
2019-06-01 00:00:00+00

它是postgresql还是mysql?@nacho它是postgresql所以不要将它标记为mysql我不认为这样对我有帮助。我的reviewMonth为reviewMonth=$(日期-d'now'+'%Y-%m-01 00:00:00')现在,我想将此reviewMonth值用作i.create_datetime=reviewMonth值此方法对您来说应该很好。上面的第二个方法由于引用问题而失败。我将向您展示如何解决这些问题。您在执行导出TSTAMP时对值进行了硬编码。在我的情况下,它不能硬编码为“2019-03-01 00:00:01-06”此值来自reviewMonth=$(日期-d'now'+%Y-%m-01 00:00:00')更详细地说,想象一个场景,我有一个postgresql查询1,它提供了100行不同的Id。现在对于所有不同的Id,我必须使用while read Id运行查询2;do query 2。在查询2中,现在如何动态使用Id,该Id必须从变量IdFor one中动态读取值,这种技术在这两种情况下都有效。导出不必硬编码,它可以像任何其他bash变量一样设置。其次,对于您提到的两种情况,最好在postgres中完成所有工作,而不涉及shell变量。@abhisek我又添加了几个示例。