我在Informix 12.10 (Linux x86_64)中有一个这样定义的视图。
create view "dbo".perinexv
(
ac0, ri0, wf0, up0, di0, dp0, if0, iu0, ts0, dv0, dc0, ca0, m0, ax0, ce0, al0, tg0, ti0, tf0, tn0, pu0, tr0, fm0, pq0, av0, ad0, ab0, af0, an0, ct0, et0, ft0, fn0, nb0, pi0, hb0, rx0, rz0, az0, as0, dr0, ii0, xr0, le0, sk0, sl0, wd0
)
as
select
('SK' || x1.kat_c ) ::varchar(8),
'PE' ::char(2),
CASE WHEN ((x0.dat_zru < CURRENT year to month ) OR ((x0.dat_zru IS NULL ) AND (((mod(x0.vestzru,100 ) - YEAR (TODAY ) ) < 0. ) OR ((mod(x0.vestzru,100 ) - YEAR (TODAY ) ) > 20. ) ) ) ) THEN '.' ELSE ' ' END ::char(1),
CASE WHEN (x0.dat_zru < (CURRENT year to month - interval( 1) month(9) to month ) ) THEN 'H' WHEN (x0.dat_zru < CURRENT year to month ) THEN 'W' WHEN (x1.datzv < (CURRENT year to month - interval( 1) month(9) to month ) ) THEN ('U' || CASE WHEN EXISTS (select x5.datzv from "dbo".evuknor x5 where ((((x5.datzv < CURRENT year to month ) AND (x5.zmop != '1' ) ) AND (x5.identif = x0.identif ) ) AND (x5.rokvyd = x0.rokvyd ) ) ) THEN '*M' ELSE ' ' END ) ELSE ('N' || CASE WHEN EXISTS (select x6.datzv from "dbo".evuknor x6 where ((((x6.datzv < CURRENT year to month ) AND (x6.zmop != '1' ) ) AND (x6.identif = x0.identif ) ) AND (x6.rokvyd = x0.rokvyd ) ) ) THEN '*M' ELSE ' ' END ) END ::char(3),
TRIM ( BOTH ' ' FROM x0.identif ) ::varchar(50),
x1.datzv ::date,
CASE WHEN (x0.identif NOT MATCHES ((((('*' || LPAD (x0.cistn,2,'0' )) || ' ' ) || x0.cisskn ) || LPAD (x0.cisnsk,2,'0' )) || '*' ) ) THEN (((LPAD (x0.cistn,2,'0' )|| ' ' ) || x0.cisskn ) || LPAD (x0.cisnsk,2,'0' )) END ::char(7),
'Normalization office' ::varchar(128),
'ST*N' ::char(4),
x1.datuc ::date,
x1.datsch ::date,
(select informix.concagr(TRIM ( BOTH ' ' FROM x7.ics ),'*' ) ::varchar(64) from "dbo".charcsn x7 where ((x7.identif = x0.identif ) AND (x7.rokvyd = x0.rokvyd ) ) ) ::varchar(64),
((('TK ' || x2.cistnk ) || ' ' ) || x2.nametnk ::varchar(255) ),
NULL ::date,
NULL ::char(1),
x1.jazyk ::char(2),
NULL ::char(1),
REPLACE (x3.nazang,'|','/' )::char(440),
NULL ::char(1),
REPLACE (x0.nazevn,'|','/' )::char(440),
'UNMS SR' ::varchar(24),
NULL ::char(1),
NVL ((x1.str_celk || CASE WHEN (x1.format != 'A4' ) THEN ('/' || x1.format ) ELSE '' END ),'not applicable' )::varchar(14),
(x4.cena_kc || ' EUR' ::varchar(13) ),
NULL ::char(1),
NULL ::char(1),
NULL ::char(1),
NULL ::char(1),
rmnl(REPLACE (x3.abstr,'|','/' ))::lvarchar(2046),
NULL ::char(1),
(select informix.concagr(TRIM ( BOTH ' ' FROM x9.heslo ),'*' ) ::lvarchar(2046) from "dbo".deskrcsn x8,"dbo".klicslo x9 where (((((x8.identif = x0.identif ) AND (x8.rokvyd = x0.rokvyd ) ) AND (x8.isoroot = x9.isoroot ) ) AND (x9.jazyk = 'en' ) ) AND (x9.heslo > '' ) ) ) ::lvarchar(2046),
NULL ::char(1),
(select informix.concagr(TRIM ( BOTH ' ' FROM x11.heslo ),'*' ) ::lvarchar(2046) from "dbo".deskrcsn x10,"dbo".klicslo x11 where (((((x10.identif = x0.identif ) AND (x10.rokvyd = x0.rokvyd ) ) AND (x10.isoroot = x11.isoroot ) ) AND (x11.jazyk = 'sk' ) ) AND (x11.heslo > '' ) ) ) ::lvarchar(2046),
rmnl(REPLACE (x0.pozncsn,'|','/' ))::varchar(255),
NULL ::char(1),
NULL ::char(1),
(select informix.concagr((((TRIM ( BOTH ' ' FROM x13.identif ) || '(' ) || REPLACE (LPAD (x13.rokvyd ::varchar(7),7,'0' ),'.','-' )) || ')' ),'*' ) ::lvarchar(2046) from "dbo".zmena x12,"dbo".evuknor x13 where (((((x12.kat_c = x13.kat_c ) AND (x12.identif = x0.identif ) ) AND (x12.rokvyd = x0.rokvyd ) ) AND (x12.zmzr IN ('0','S' )) ) AND (x12.rokvyd > 1900.00 ) ) ) ::lvarchar(2046),
(select informix.concagrl((((TRIM ( BOTH ' ' FROM x14.identif ) || '(' ) || REPLACE (LPAD (x14.rokvyd ::varchar(7),7,'0' ),'.','-' )) || ')' ),'*' ) ::lvarchar(4094) from "dbo".zmena x14 where (((x14.kat_c = x1.kat_c ) AND (x14.zmzr IN ('0','S' )) ) AND (x14.rokvyd > 1900.00 ) ) ) ::lvarchar(4094),
(select informix.concagr((((x15.zmop || ' ' ) || TRIM ( BOTH ' ' FROM x15.idzm ) ) || NVL ((' ' || LPAD (REPLACE ((x15.vestnik / 100.0000000000000000 ) ::decimal(4,2),'.','/' ),5,'0' )),'' )),'*' ) from "dbo".evuknor x15 where ((((x15.identif = x0.identif ) AND (x15.rokvyd = x0.rokvyd ) ) AND (x15.zmop != '1' ) ) AND (x15.datzv < CURRENT year to month ) ) ) ::varchar(255),
NULL ::char(1),
NULL ::char(1),
(select informix.concagr(((((CASE WHEN (x16.stupshod = 'E' ) THEN 'eqv' WHEN (x16.stupshod = 'H' ) THEN 'har' WHEN (x16.stupshod = 'I' ) THEN 'idt' WHEN (x16.stupshod = 'M' ) THEN 'mod' WHEN (x16.stupshod = 'N' ) THEN 'neq' WHEN (x16.stupshod = 'O' ) THEN 'idt' WHEN (x16.stupshod = 'R' ) THEN 'rel' WHEN (x16.stupshod = 'Z' ) THEN 'zap' ELSE NVL (x16.stupshod ::char(3),' ' ) END || ' ' ) || TRIM ( BOTH ' ' FROM x17.identzn ) ) || ':' ) || x17.rokvzn ),'*' ) from "dbo".prevzeti x16,"dbo".meznorm x17 where ((x16.kat_c = x1.kat_c ) AND (x16.xmezn = x17.xmezn ) ) ) ::varchar(255),
NULL ::char(1),
NULL ::char(1),
(CASE WHEN (x0.dat_zru < CURRENT year to month ) THEN 'Z' ELSE 'A' END || sortkey(x0.identif )::varchar(50) ),
NULL ::char(1),
x0.dat_zru ::date
from "dbo".csn x0,
"dbo".evuknor x1,
outer("dbo".tnk x2 ),
outer("dbo".csntext x3 ),
outer("dbo".censkup x4 )
where
(
(
(
(
(
(
(
((x0.rokvyd > 1900.00 ) AND (x1.zmop = '1' ) )
AND (x1.datzv < CURRENT year to month )
)
AND (x1.identif = x0.identif )
)
AND (x1.rokvyd = x0.rokvyd )
)
AND (x0.cistnk = x2.cistnk )
)
AND (x3.identif = x0.identif )
)
AND (x3.rokvyd = x0.rokvyd )
)
AND (x4.censk = x1.censk )
)
;
当我运行命令select count(ac0) from perinexv
时,它给了我正确的结果
> select count(ac0) from perinexv;
(count)
71476
1 row(s) retrieved.
但是当我尝试运行select count(*) from perinexv
时,我收到错误683。
> select count(*) from perinexv;
683: Specified STEP expression will not traverse RANGE.
Error in line 1
Near character position 28
如果我运行select ac0 from perinexv
,输出是正确的
> select ac0 from perinexv;
ac0
SK68386
SK68387
...
SK136374
SK136375
71476 row(s) retrieved.
对于每个单独的列也是正确的。不返回任何错误。错误683表示:
683指定的STEP表达式不能遍历RANGE.
FOR语句中STEP表达式的求值将导致无限循环。
错误示例:
FOR i = 10 TO 20;- error…END FOR
纠正:纠正范围或步进表达式,使增量值在范围内
我在视图定义中没有看到任何阶跃函数,而且,当我尝试分别选择每列时,它没有错误。
当我限制返回的行数时,例如select first 100 * from perinexv
,它可以工作到大约20000,但是,当我添加排序(order by ca0
)时,它会因上面的错误而失败。
当我运行select * from perinexv
时,它总是以相同的ac0值结束,所以这似乎是数据中的一个问题。有什么方法可以找到结果的下一行吗?
你知道是什么原因导致这个问题吗?
问题已确定。这是数据的问题。
在视图perinexv
中有sk0
列,其定义如下:
(CASE WHEN (x0.dat_zru < CURRENT year to month ) THEN 'Z' ELSE 'A' END || sortkey(x0.identif )::varchar(50) )
有一个函数sortkey()
和参数x0.identif
(x0
在本例中是表evuknor
)。在sortkey()
的定义中可以找到以下FOR循环:
LET txt = TRIM(txt);
FOR posa=1 TO LENGTH(txt) STEP 1
IF SUBSTR(txt,posa,1)=' ' THEN
LET txt = SUBSTR(txt,posa);
EXIT FOR;
END IF
END FOR
可以看到,当LENGTH(txt)
(其中txt
由x0.identif
的值组成)等于0(空字符串)时,就会出现我提到的错误。
不幸的是,源表中存在空字符串值,这导致了这个问题。
解决方案是将缺失的值添加到源表中,并更改列定义以不允许空字符串。