【问题标题】:PostgreSQL: Syntax Error when trying to access field in arrayPostgreSQL:尝试访问数组中的字段时出现语法错误
【发布时间】:2017-10-08 18:53:52
【问题描述】:

我正在从 Oracle 9i 迁移到 PostgreSQL 9.3,我需要迁移一些包及其内容。

我在大部分工作中都使用 Ora2PG,但考虑到代码对 Oracle 的具体程度,需要手动迁移包。

我有一个名为RelevCaspTyp 的用户定义类型,其定义如下:

CREATE TYPE pkgstesa5152com.relevcasptyp AS (
   -- SOME OTHER DATA
   d1           timestamp,
   d2           timestamp,
   d1min        timestamp,
   d2min        timestamp,
   d1max        timestamp,
   d2max        timestamp,
   -- SOME OTHER DATA
);

然后,我在另一个类型中创建了一个这种类型的对象数组:

CREATE TYPE pkgstesa5152com.relevcasptabtyp AS (relevcasptabtyp pkgstesa5152com.relevcasptyp[]);

最后是触发语法错误的函数:

CREATE OR REPLACE FUNCTION PkgStesa5152Com.calculd1d2 (RelevCaspTab INOUT pkgstesa5152com.RelevCaspTabTyp, i integer) AS $body$
BEGIN
IF RelevCaspTab[i].d1max IS NULL OR RelevCaspTab[i].d1min >= RelevCaspTab[i].d1max THEN
   RelevCaspTab[i].d1 := RelevCaspTab[i].d1min;
ELSE
   RelevCaspTab[i].d1 := RelevCaspTab[i].d1max;
END IF;
IF RelevCaspTab[i].d2max IS NULL OR RelevCaspTab[i].d2min >= RelevCaspTab[i].d2max THEN
   RelevCaspTab[i].d2 := RelevCaspTab[i].d2min;
ELSE
   RelevCaspTab[i].d2 := RelevCaspTab[i].d2max;
END IF;
END;
$body$
LANGUAGE PLPGSQL
;

当我尝试在我的 PostgreSQL 数据库中导入此函数时,我收到以下消息:

ERROR:  syntax error at or near "."
LINE 5:    RelevCaspTab[i].d1 := RelevCaspTab[i].d1min;
                          ^

尽管看起来很奇怪,但第 4 行(带有 IF/THEN)似乎正确通过,除非这是另一个误报并且问题实际上出在其他地方。

编辑:看起来问题实际上来自对 RelevCaspTab[i].d1 的值的影响。如果我把函数中的所有做作都注释掉,就创建成功了。

【问题讨论】:

  • 我删除了 Oracle 标记。

标签: postgresql syntax-error plpgsql database-migration


【解决方案1】:
if r[i].d1max is null or r[i].d1min >= r[i].d1max then
   r[i] := (r[i].d1min,r[i].d2,r[i].d1min,r[i].d2min,r[i].d1max,r[i].d2max);

编辑

按照 cmets 的建议:

create type relevCaspTyp as (
   d1           timestamp,
   d1min        timestamp,
   d1max        timestamp
);

create or replace function calculd1d2 (
    r inout relevCaspTyp[], i integer
) as $body$
declare a relevCaspTyp;
begin
    a := r[i];
    if a.d1max is null or a.d1min >= a.d1max then
       a.d1 := a.d1min;
    else
       a.d1 := a.d1max;
    end if;
    r[i] := a;
end;
$body$
language plpgsql
;

with r (r) as (values (array[('2017-01-01','2017-01-04','2017-01-03')::relevCaspTyp]))
select calculd1d2(r,1)
from r;
                                  calculd1d2                                   
-------------------------------------------------------------------------------
 {"(\"2017-01-04 00:00:00\",\"2017-01-04 00:00:00\",\"2017-01-03 00:00:00\")"}

【讨论】:

  • 那么,如果我做对了,我需要重新影响所有字段以更改单个值吗?这会有点烦人,因为我的类型共有 44 个字段......但如果没有其他解决方案,我会接受它。
  • @Gyoo 你可以声明变量:DECLARE x pkgstesa5152com.RelevCaspTabTyp; 然后x := r[i]; 然后更改其中的字段,然后r[i] := x;
  • @Abelisto 这似乎工作......至少它“编译”!我还不能测试这个函数,因为我还有很多代码要转换,但这肯定减轻了我的负担!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-14
相关资源
最近更新 更多