在同一查询中将日期和时间戳与时区与 now() 进行比较?

Chr*_*ris 8 postgresql datatypes timestamp date-format

我有多个数据库服务器,我正在使用将过期列与now(). 问题是服务器的过期列之一是timestamp with time zone,其余的都是date。我无法更改此设置,因为我没有管理员访问权限,而且实际上我只是在查询视图。Postgres 对我来说相当陌生,所以我真的不明白日期和时间是如何相互配合的。

当我尝试timestamp with time zone通过将timestampa转换为 a 来查询服务器时date

...
WHERE
    (
        status_code = '30000'
        OR status_code = '30005'
    )
AND CAST(expiration AS DATE) > now()
Run Code Online (Sandbox Code Playgroud)

它有效,但在expiration已经date失败的服务器上使用相同的查询:

[Err] 错误:类型日期的无效输入语法:“无结束日期”

任何帮助将不胜感激,我真的不想硬编码这个数据库服务器的异常。

Erw*_*ter 9

这应该永远不会失败(我简化了一点):

WHERE status_code IN ('30000','30005')
AND   expiration > now() 
Run Code Online (Sandbox Code Playgroud)

PostgreSQL 可以自动比较datetimestamp(有或没有时区)。如果是 adate它会timestamp自动转换为(0:0 小时)。

错误消息讲述了一个不同的故事。您实际上是在尝试输入date语法无效的a 。

我最近写了一个关于在 PostgreSQL 中处理带或不带时区的时间戳的详细答案 - 如果这应该是问题的话:


事实证明,expiration是一text列。您需要将其转换为datetimestamp(以您的需要为准)。如果它是有效格式:

...
AND   expiration::timestamptz > now() 
Run Code Online (Sandbox Code Playgroud)

如果该文本列中有无效字符串,例如“无结束日期”,则需要清理源代码或在CASE构造中专门处理这些字符串:

...
AND   CASE WHEN expiration::text = 'No End Date' THEN 'infinity'::timestamp
           WHEN expiration::text = 'foo' THEN '-infinity'::timestamp
           ELSE expiration::timestamp
      END > now()
Run Code Online (Sandbox Code Playgroud)

关于特殊价值的手册infinity

转换为文本 ( ::text) 是多余的text,但使表达式也适用于date/timestamp值。

如果时间戳文字的格式可能不明确,请使用to_date()to_timestamp()明确定义格式:

to_date('07/08/2013', 'DD/MM/YYYY')
Run Code Online (Sandbox Code Playgroud)

使用AT TIME ZONE构造ifexpiration应该是另一个时区的本地时间戳:

expiration::timestamp AT TIME ZONE 'UTC' -- desired time zone here
Run Code Online (Sandbox Code Playgroud)

如果expiration格式不明确/非标准格式,请使用to_timestamp()

to_timestamp(expiration::text, 'yyyy-mm-dd')
Run Code Online (Sandbox Code Playgroud)