纸飞机

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  22 随笔 :: 28 文章 :: 30 评论 :: 0 Trackbacks

问题:对于字母数字的数据,只返回数字值。从字符串“paul123f321”中返回123321。

解决方案

DB2

使用函数TRANSLATE和REPLACE,从字母数字串中提取数字字符:

1 select cast(

2         replace(

3       translate( 'paul123f321',

4                  repeat('#',26),

5                  'abcdefghijklmnopqrstuvwxyz'),'#','')

6         as integer ) as num

7    from t1

Oracle和PostgreSQL

使用函数TRANSLATE和REPLACE,可以从包含字母数字的字符串中提取数字字符:

1 select cast(

2         replace(

3       translate( 'paul123f321',

4                  'abcdefghijklmnopqrstuvwxyz',

5                  rpad('#',26,'#')),'#','')

6         as integer ) as num

7   from t1    

MySQL和SQL Server

到本书编写时为止,这两个供应商都不支持TRANSLATE函数,因此这里不能给出解决方案了。

讨论

两种解决方案的唯一差别是语法,DB2使用函数REPEAT代替RPAD,而且TRANSLATE参数列表的顺序也不同。以下的解释采用了Oracle/PostgreSQL解决方案, DB2也类似。如果从里向外运行该查询(仅仅从TRANSLATE开始),就会发现这非常简单。首先,TRANSLATE把非数字字符转换为“#”:

select translate( 'paul123f321',

                   'abcdefghijklmnopqrstuvwxyz',

                   rpad('#',26,'#')) as num

   from t1

NUM

-----------

####123#321

由于现在所有非数字字符都用“#”表示了,因此只需使用REPLACE去掉它们,然后把结果转换为数值。这个特殊的例子尤其简单,因为字符串中只有字母和数字。如果还有其他字符,那么用另一种方法会更容易:不是找出非数字字符并去掉它们,而是找出所有数字字符,并去掉不属于这些字符范围的其他字符。下面的例子会有助于理解这种技巧:

select replace(

      translate('paul123f321',

        replace(translate( 'paul123f321',

                           '0123456789',

                           rpad('#',10,'#')),'#',''),

                rpad('#',length('paul123f321'),'#')),'#','') as num

   from t1

NUM

------

123321

较之原始方案,该解决方案看起来有点儿费解,但如果把它分解开来就容易理解了。观察一下最内层的TRANSLATE调用:

select translate( 'paul123f321',

                   '0123456789',

                   rpad('#',10,'#'))

   from t1

TRANSLATE('

-----------

paul###f###

与原来方案不同的是,它没有用“#”字符替换每个非数字字符,而是用“#”字符替换所有数字字符。接下来,去掉所有“#”,这样,只剩下非数字字符:

select replace(translate( 'paul123f321',

                           '0123456789',

                           rpad('#',10,'#')),'#','')

   from t1

REPLA

-----

paulf

下一步,再次调用TRANSLATE,这次用“#”字符替换原始字符串中的所有非数字字符(前面查询的结果):

select translate('paul123f321',

        replace(translate( 'paul123f321',

                           '0123456789',

                           rpad('#',10,'#')),'#',''),

                rpad('#',length('paul123f321'),'#'))

   from t1

TRANSLATE('

-----------

####123#321

到这里停一停,检验一下最外层的TRANSLATE调用。RPAD的第二个参数(DB2中REPEAT的第二个参数)是原始字符串的长度。这样做很方便,因为是没有任何字符出现的次数会比它所在的整个字符串长。现在,用“#”字符替换所有非数字字符;最后一步,使用REPLACE去掉所有“#”。至此,仅剩下数字。

posted on 2008-05-14 21:50 纸飞机 阅读(4687) 评论(0)  编辑  收藏 所属分类: Database

只有注册用户登录后才能发表评论。


网站导航: