【问题标题】:postgres function returns operator doesn't exist integer - timestamppostgres 函数返回运算符不存在整数 - 时间戳
【发布时间】:2021-10-03 14:35:03
【问题描述】:

您好,我有一个函数,在调用它进行测试时会返回问题中的错误。我知道这与我如何将变量插入到查询的一部分中有关,但我无法弄清楚为什么,我尝试更改其上的类型转换但没有运气。任何帮助将不胜感激

create or replace function ageing_balance_calc(start_date text, client_id text) returns void 
AS $BODY$ 
declare 
_absd date;
_client_id text;
req text; 
BEGIN
_absd:=(to_date(start_date,'YYYY-MM-DD'));
_client_id:= client_id;
with cte as 
(
Select * from crosstab('
select * from (
select absd, 
case when a.days_ago between 0 and 30 then ''0-30''
     when a.days_ago between 31 and 60 then ''31-60''
     when a.days_ago between 61 and 90 then ''61-90''
     when a.days_ago >90 then ''90+''
     else ''not due'' end as bucket, sum(a.item_amount)
from (select date_part(''day'',((due_date::timestamp) - ('||_absd||' ::text::timestamp)) )as days_ago, item_amount, '||_absd||'::text::date as absd  from fdw_test) a
group by bucket, absd)b order by 1,2') as   (absd date,
    bucket0_30 numeric,
    bucket31_60 numeric,
    bucket61_90 numeric,
    bucket90_plus numeric,
    not_due numeric)
)
update  ddva.kpi_calc_results
set 
absd = a.absd, 
bucket0_30 = a.bucket0_30,
bucket31_60 = a.bucket31_60, 
bucket61_90 = a.bucket61_90,
bucket90_plus = a.bucket90_plus, 
not_due = a.not_due from (
select absd, bucket0_30, bucket31_60, bucket61_90, bucket90_plus, not_due from cte) as a 
where ddva.kpi_calc_results.client_id = _client_id ; 
END; 
$BODY$
LANGUAGE plpgsql

更新 如果我将 date_part 删除到自己的查询中,然后使用 $date 以这种方式将日期作为字符串插入,则 date_part 有效。如果我在函数开始时删除 to_date 部分,我仍然会得到与以前相同的错误。做'||x||'对数据类型做些什么?

【问题讨论】:

  • 您需要告知问题的更新,您希望select date_part(''day'',((due_date::timestamp) - ('||_absd||' ::text::timestamp)) 返回什么?
  • 这只需要返回自到期日以来的天数。所以 absd 是计算的开始日期。

标签: postgresql date-arithmetic


【解决方案1】:

问题出在这里:

结果查询如下所示:(2021-07-07::text::timestamp) 并导致错误:iteger - timestamp。

您必须添加更多引号:('''||_absd||'''::text::timestamp)

【讨论】:

  • 这样不行:'''||_absd||'''::text::timestamp invalid input syntax for type timestamp: "'||_absd||'
  • 那行得通,你忘了它都在引号内作为 crosstab() 的第一个参数
  • 是的,我错过了。
【解决方案2】:

嗯:

date_part(''day'',((due_date::timestamp)

将返回一个整数:

select date_part('day', now());
27

我猜你想要的更像是:

select now()::date;  2021-07-27

更新

这部分:

'''||_absd||'''::text::timestamp

也不行:

select '''||_absd||'''::text::timestamp;
ERROR:  invalid input syntax for type timestamp: "'||_absd||'"

【讨论】:

    【解决方案3】:

    下面一行:

    (select date_part(''day'',((due_date::timestamp) - ('||_absd||' ::text::timestamp)) )as days_ago, item_amount, '||_absd||'::text::date as absd  from fdw_test)
    

    稍作改动:

    (select date_part(''day'',((due_date::timestamp) - ('''||_absd||'''::timestamp)) )as days_ago, item_amount, '''||_absd||'''::date as absd  from fdw_test)
    

    该功能现在按预期工作

    【讨论】:

    • 处理双引号或三引号可能很棘手,更好的方法是使用 Dollar-qouting 或 FORMAT() 函数
    猜你喜欢
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 2010-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-03
    相关资源
    最近更新 更多