【问题标题】:Compare date if not null如果不为空,则比较日期
【发布时间】:2019-06-07 15:33:15
【问题描述】:

我需要找到创建日期 > X 的所有记录。X 是一个 sql.Timestamp 并且可能为空,在这种情况下我只想返回所有记录。所以我尝试了:(createdAfter is Timestamp)

SELECT *
FROM sample AS s
WHERE s.isActive
  AND (:createdAfter ISNULL OR s.insert_time > :createdAfter)

但我得到的只是

org.postgresql.util.PSQLException: ERROR: could not determine data type of parameter $1

但是,如果我在检查任意 int 是否为 null 时执行相同的查询:

SELECT * 
FROM trades 
WHERE (:sInt ISNULL OR trades.insert_time > :createdAfter ) 

然后就可以了。怎么了?

【问题讨论】:

    标签: java postgresql


    【解决方案1】:

    如果您想坚持使用这样的原生查询,没有简单的解决方案。 null 值转换为 bytea 值。参见例如thisthis

    该值很难转换或与timestamp 值进行比较。

    问题不在于第一次比较,而是使用合并来处理,例如:

    COALESCE(:createdAfter) ISNULL
    

    因为实际值之间没有比较,并且数据类型无关紧要。但是比较

    sometimestamp::timestamp > null::bytea(强制转换只是为了显示实际类型,因此不起作用)

    可能需要更多的逻辑,可能是过程和异常处理等等,不确定。

    因此,如果 JPQL 或 CriteriaQueries 对您来说不可能,那么您只有不好的选择:

    • 通过字符串连接设置参数来构造查询(不是!不确定是否真的有效)
    • 使用PreparedStatement 查询,更多代码和努力
    • 如果使用 Hibernate,也可以使用 this answer 中的会话 api

    【讨论】:

      【解决方案2】:

      您可以尝试使用返回文本字符串的pg_typeof 函数,并使用CASE 语句强制进行哪些比较(否则无法保证postgres 会以正确的顺序短路OR) .然后,您可以通过转换为文本然后再返回时间戳来强制进行正确的转换,这是不优雅但应该有效的。

      SELECT *
      FROM sample AS s
      WHERE s.isActive
        AND 
          CASE WHEN pg_typeof( :createdAfter ) = 'bytea' THEN TRUE
             WHEN s.insert_time > ( ( :createdAfter )::text)::timestamp THEN TRUE
             ELSE FALSE 
          END
      

      【讨论】:

        猜你喜欢
        • 2020-10-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多