PL/pgSQL 中的“格式错误的数组文字”错误

Posted

技术标签:

【中文标题】PL/pgSQL 中的“格式错误的数组文字”错误【英文标题】:"malformed array literal" error in PL/pgSQL 【发布时间】:2019-11-22 12:26:47 【问题描述】:

PL/pgSQL 出现错误:

“错误:格式错误的数组文字:“2019-11-22 09:18:07.248537”详细信息: 数组值必须以“”或维度信息开头。语境: PL/pgSQL 函数 chargelengtth() 第 11 行 FOR over SELECT 行"

CREATE OR REPLACE FUNCTION chargelengtth() RETURNS text AS
$$
DECLARE chargetime integer;
DECLARE othertime integer;
DECLARE total integer;
DECLARE charge_length text[];
DECLARE chargestatus text;
DECLARE otherstatus text;
BEGIN
    total := 0;
    chargetime := 0;
FOR charge_length IN
    SELECT * FROM table_name
LOOP
    RAISE NOTICE 'Stuff: %', charge_length;
    IF(charge_length[diagnostic] = 'Charging' AND chargetime = 0) THEN
        chargetime := extract(epoch from charge_length[time]);
    END IF;

    IF(charge_length[diagnostic] != 'Charging') THEN
        othertime := extract(epoch from charge_length[time]);
        total := total + (othertime - chargetime);
        chargetime := 0;
    END IF;

END LOOP;
RETURN to_char(total * interval '1 sec','HH24h MIm');
END$$ LANGUAGE plpgsql;
SELECT * FROM chargelengtth()`

您能否分享您的知识来解决此问题。

【问题讨论】:

与你的问题无关,但是:你只需要写declare一次 你为什么一开始就使用这样一个低效的循环?您可以使用单个查询来完成此操作,无需循环 如何在单个查询中做到这一点,你能给我样本吗? 请看我的回答——不过我并不完全清楚你在做什么。如果您提供了一些示例数据和预期结果,这会更容易。 【参考方案1】:

As documented in the manual 当你想循环一个 SELECT 语句时,你需要使用一个记录变量:

CREATE OR REPLACE FUNCTION chargelengtth() 
  RETURNS text AS
$$
DECLARE 
  chargetime integer;
  othertime integer;
  total integer;
  chargestatus text;
  otherstatus text;
  l_row record; --<< here
BEGIN
  total := 0;
  chargetime := 0;
  FOR l_row IN SELECT * FROM table_name
  LOOP
      RAISE NOTICE 'Stuff: %', l_row;
      IF (l_row.diagnostic = 'Charging' AND chargetime = 0) THEN
          chargetime := extract(epoch from l_row.time);
      END IF;

      IF (l_row.diagnostic != 'Charging') THEN
          othertime := extract(epoch from l_row.time);
          total := total + (othertime - chargetime);
          chargetime := 0;
      END IF;

  END LOOP;
  RETURN to_char(total * interval '1 sec','HH24h MIm');
END$$ LANGUAGE plpgsql;

SELECT chargelengtth()

据我所知,您可以将其替换为单个 SELECT 语句。假设time 列是timestamp,我认为以下内容等同于您正在执行的操作(除了末尾的interval 的格式):

with ct (chargetime) as (
  select time 
  from table_name
  where diagnostic = 'Charging'
  limit 1
)
select sum(t.time - ct.chargetime) 
from the_table t
  cross join ct
where t.diagnostic <> 'Charging'

chargetime 的检索有点令人困惑,因为您似乎依赖于某些行顺序,但您的查询没有 order by。没有order bylimit 1 本质上是相同的,但是如果您想要可重现的结果,您应该真正指定order by(也用于您的 FOR 循环语句)

【讨论】:

DATETIME, C DATETIME, CPE DATETIME, C DATETIME, C DATETIME, C DATETIME, CPE DATETIME, PDE 对于上述结果,我需要计算第一和第二(C 和 CPE)记录的时间差异为 C,第二和第三记录为 CPE(CPE 和 C),第三和第四记录作为 C 并找到总的 C 和 CPE 总时间差。

以上是关于PL/pgSQL 中的“格式错误的数组文字”错误的主要内容,如果未能解决你的问题,请参考以下文章

执行 SELECT 语句并丢弃 PL/pgSQL 中的结果

Pl/pgSQL 匿名代码块在 [42601] 错误上失败:查询没有结果数据的目的地

PL/pgSQL 语法错误

关于 Pl/pgsql 中游标的一些错误

PL/pgSQL 函数不能正常工作

PL/pgSQL 中的光标