Informix 14.10.FC10视图创建报错:SELECT投影列表不允许行内聚合
Informix 14.10.FC7到FC10迁移中视图创建报错问题分析
我正在将数据库从Informix Dynamic Server 14.10.FC7W1AEE迁移至14.10.FC10AEE(均部署在RHEL 8系统的不同机器上),同时PortMaster从7升级到10。目前除某视图创建命令外,其余操作均正常执行。
该视图创建命令如下:
create view "dbo".dirdoc1 ( typv,predpona,eecyear,eecnum,popivaz ) as select x0.typv , min(row(x1.eecyear , x1.eecnum , x1.predpona )::eec ).predpona , min(row(x1.eecyear , x1.eecnum , x1.predpona )::eec ).eecyear , min(row(x1.eecyear , x1.eecnum , x1.predpona )::eec ).eecnum , max(x0.popivaz ) from "dbo".typv x0 , outer("dbo".dirdoc x1 ) where ( x0.typv = x1.typv ) group by x0.typv ;
执行后收到报错:
Aggregate within a ROW in a SELECT projection list is not allowed
现象说明
当仅保留一个聚合项(比如只保留min(row(x1.eecyear,x1.eecnum,x1.predpona)::eec).eecnum)时,命令可正常执行;但使用2个及以上min()列时,就会触发上述报错。该命令(或仅SELECT部分)在FC7环境中完全正常,在FC10中则报错。我已经核对了FC8、FC9、FC10的版本发布说明、onconfig文件及环境变量(两台机器配置尽可能保持一致),想了解FC7到FC10之间的哪些变更可能导致此问题?
问题复现步骤(FC7W1可行,FC10不可行)
1. 创建基础表dbo.typv
CREATE TABLE dbo.typv ( typv char(8) NOT NULL, popivaz varchar(254) NOT NULL, poznvaz varchar, nazevc varchar, snp smallint DEFAULT 0 NOT NULL, peca smallint DEFAULT 0 NOT NULL, uveu smallint, PRIMARY KEY (typv) CONSTRAINT typv_pk );
2. 创建表dbo.dirdoc
create table dbo.dirdoc ( typv char(8) not null , eecyear datetime year to year not null , eecnum integer not null , oj char(14), predpona varchar(7) default 'EEC' not null , celex char(10), check (((((oj MATCHES 'OJ [0-9][0-9]/[CL] [1-9][0-9/ ][0-9/ ][0-9/ ][0-9/ ][0-9/ ]' ) AND ((oj MATCHES '*[0-9]/[0-9][0-9]*' ) OR (oj MATCHES '????????[1-9][0-9 ][0-9 ] ' ) ) ) AND (oj NOT MATCHES '*/*/*/*' ) ) AND (oj NOT MATCHES '*[0-9] [0-9]*' ) ) AND (oj NOT MATCHES '*/[0-9][0-9][0-9]*' ) ) constraint dbo.oj_dirdoc ) extent size 16 next size 16 lock mode page;
3. 创建行类型informix.eec
create row type informix.eec ( eecyear datetime year to year, eecnum integer, predpona varchar(7) );
4. 创建自定义比较函数informix.lessthanorequal
CREATE FUNCTION informix.lessthanorequal(eec1 eec, eec2 eec) RETURNING BOOLEAN WITH(NOT VARIANT,NEGATOR=greaterthan); IF eec1.eecyear IS NULL OR eec2.eecyear IS NULL THEN RETURN NULL::BOOLEAN; ELIF eec1.eecyear < eec2.eecyear THEN RETURN 't'; ELIF eec1.eecyear > eec2.eecyear THEN RETURN 'f'; END IF IF eec1.eecnum IS NULL OR eec2.eecnum IS NULL THEN RETURN NULL::BOOLEAN; ELIF eec1.eecnum < eec2.eecnum THEN RETURN 't'; ELIF eec1.eecnum > eec2.eecnum THEN RETURN 'f'; END IF IF eec1.predpona IS NULL AND eec2.predpona IS NULL THEN RETURN 't'; ELIF eec1.predpona < eec2.predpona THEN RETURN 't'; ELIF eec1.predpona > eec2.predpona THEN RETURN 'f'; ELIF eec2.predpona IS NULL THEN RETURN 't'; ELIF eec1.predpona IS NULL THEN RETURN 'f'; ELSE RETURN 't'; END IF END FUNCTION;
5. 创建报错的视图dbo.dirdoc1
create view dbo.dirdoc1 (typv,predpona,eecyear,eecnum,popivaz) as select x0.typv, min(row(x1.eecyear,x1.eecnum,x1.predpona)::eec).predpona, min(row(x1.eecyear,x1.eecnum,x1.predpona)::eec).eecyear, min(row(x1.eecyear,x1.eecnum,x1.predpona)::eec).eecnum, max(x0.popivaz) from dbo.typv x0, outer(dbo.dirdoc x1) where (x0.typv = x1.typv) group by x0.typv;
可能的版本变更原因分析
从FC7到FC10的版本迭代中,Informix对SQL语法的合规性检查进行了强化,尤其是针对聚合函数与行类型结合的场景:
- SQL语法解析器严格性提升:FC7版本的解析器可能存在漏洞,允许在SELECT投影列表中多次对行类型执行聚合函数并提取字段的操作;而FC8/FC9/FC10中修复了该漏洞,严格执行官方规范——不允许在投影列表中同时存在多个“聚合函数嵌套行类型操作”的表达式。
- UDT聚合交互逻辑调整:针对自定义行类型(如
eec)的聚合操作,FC10调整了执行计划生成逻辑。当多个min(row(...))::eec.xxx表达式共存时,解析器会判定为“聚合内部嵌套行类型操作”的违规场景,单个表达式则因执行路径简单未触发检查。 - PortMaster升级的间接影响:PortMaster从7升级到10同步更新了SQL语法校验规则,部分之前被允许的非标准语法在新版本中被限制。
内容的提问来源于stack exchange,提问作者Ondřej Žižka
相关产品推荐
相关产品推荐

