函数整数IBM DB2的参数无效

时间:2018-06-19 06:04:28

标签: sql db2

我需要过滤出表中numer_lini列中有数字的行,它在100到999之间,当我注释掉我将marsnr转换为整数的行时,下面的代码工作得很好。但是,当我尝试使用它时,我得到错误:在函数" INTEGER"的字符串参数中找到无效字符。当查看列表时看起来像替换和翻译过滤器只有数字就好并且选择仅包含合法数字(唯一值列表不长,因此易于通过眼睛扫描)。那么为什么它没有投出一些东西呢?我也尝试使用整数(marsnr),但它会产生相同的错误。我需要施法,因为我需要数值范围,否则我得到像7,80等结果。正如我所提到的,我正在使用IBM DB2数据库。

select numer_lini, war_trasy, id_prz1, id_prz2
from alaska.trasa
where numer_lini in (
    select marsnr
    from (
        select
        distinct numer_lini marsnr
        from alaska.trasa
        where case
        when replace(translate(numer_lini, '0','123456789','0'),'0','') = ''
        then numer_lini
        else 'no'
        end <> 'no'
    )
    where cast(marsnr as integer) between 100 and 999
)
fetch first 300 rows only 

1 个答案:

答案 0 :(得分:1)

如果您从Db2解释中查看优化的SQL,您将看到Db2已将您的代码折叠为单个选择。

SELECT DISTINCT Q2.NUMER_LINI AS "NUMER_LINI",
   Q2.WAR_TRASY AS "WAR_TRASY",
   Q2.ID_PRZ1 AS "ID_PRZ1",
   Q2.ID_PRZ2 AS "ID_PRZ2",
   Q1.NUMER_LINI 
FROM ALASKA.TRASA AS Q1,
   ALASKA.TRASA AS Q2 
WHERE (Q2.NUMER_LINI = Q1.NUMER_LINI) 
AND (100 <= INTEGER(Q1.NUMER_LINI)) 
AND (INTEGER(Q1.NUMER_LINI) <= 999) 
AND (CASE WHEN (REPLACE(TRANSLATE(Q1.NUMER_LINI,
   '0',
   '123456789',
   '0'),
   '0',
   '') = '') THEN Q1.NUMER_LINI 
ELSE 'no' END <> 'no') 

使用CASE强制Db2执行&#34;是整数&#34;先检查一下。另外,你不要检查空字符串。

E.g。使用此表和数据

‪create‬‎ ‪TABLE‬‎ ‪alaska‬‎.‪trasa‬‎ ‪‬‎(‪numer_lini‬‎ ‪VARCHAR‬‎(‪10‬‎)‪‬‎,‪‬‎ ‪war_trasy‬‎ ‪INT‬‎ ‪‬‎,‪‬‎ ‪id_prz1‬‎ ‪INT‬‎,‪‬‎ ‪id_prz2‬‎ ‪INT‬‎)‪;
insert into alaska.trasa values ('',1,1,1),('99',1,1,1),('500',1,1,1),('3000',1,1,1),('00300',1,1,1),('AXS',1,1,1);

此SQL工作

select numer_lini, war_trasy, id_prz1, id_prz2
from alaska.trasa
where case when translate(numer_lini, '','0123456789') = ''
            and numer_lini <> ''
           then integer(numer_lini) else 0 end 
     between 100 and 999

如果输入中存在嵌入空间,则会失败。例如。 '30 0'。为了满足这一要求,可能首选常规表达。 E.g。

select numer_lini, war_trasy, id_prz1, id_prz2
from alaska.trasa
where case when regexp_like(numer_lini, '^\s*[+-]?\s*((\d+\.?\d*)|(\d*\.?\d+))\s*$'))
           then integer(numer_lini) else 0 end 
     between 100 and 999