我是Postgres数据库的新手。我得到错误:
时区的类型timestamp的无效输入语法:">
当尝试从java运行以下查询时":从_日期"以及":upto_date";在java中执行时将被替换为null。关于如何解决这个问题有什么想法吗?
select tm.*
from team tm
and tm.schedule_finish >= (case
when :from_date is null or :upto_date is null
then TO_CHAR(to_date(concat(TO_CHAR(LOCALTIMESTAMP - INTERVAL '1 month','YYYY-MM') , '-01'),'YYYY-MM-DD'),'YYYY-MM-DD')
when (date_part('year',age(:upto_date,:from_date))*12+date_part('month',age(:upto_date,:from_date)))>36
then TO_CHAR(to_date(concat(TO_CHAR(LOCALTIMESTAMP -INTERVAL '1 month','YYYY-MM') , '-01'),'YYYY-MM-DD'),'YYYY-MM-DD')
else TO_CHAR(:from_date,'YYYY-MM-DD')
end)::timestamp
我有点不清楚这些参数在传递到查询时的类型。
TO_CHAR(:from_date,'YYYY-MM-DD')
表明它是timestamp
或timestamptz
值(例如作为java.time.LocalDate
或java.time.OffsetTime
传递(
然而,错误消息似乎表明您正在将字符串作为参数传递(这有点危险,因为在这种情况下,调用age()
函数时依赖于隐式数据类型转换(。
假设您确实传递了字符串,您可以通过将第一个WHEN部分中的空字符串转换为NULL来处理它们。这样,后续表达式就不必处理空字符串。
我将为age((函数的调用添加一个显式转换。您也不需要调用age()
两次,您可以直接将结果与interval
常量age(...) > interval '36 month'
进行比较。to_date()
和to_char()
之间的来回只是为了获得上个月第一天的时间戳值也是不必要的。
如果then
部分中的所有表达式都已返回timestamp
,则不再需要将整个CASE表达式强制转换为timestamp
(case
when nullif(trim(:from_date),'') is null or nullif(trim(:upto_date), '') is null
then date_trunc('month', LOCALTIMESTAMP - INTERVAL '1 month')
when age(to_date(:upto_date, 'yyyy-mm-dd'), to_date(:from_date, 'yyyy-mm-dd')) > interval '36 month'
then date_trunc('month', LOCALTIMESTAMP - INTERVAL '1 month')
else to_timestamp(:from_date,'YYYY-MM-DD')
end)
如果你想用你的";日期串";,你必须首先转换它们:
to_date(:from_date, 'yyyy-mm-dd') - interval '1 month'