如何在不使用正则表达式的情况下向Oracle字符函数中的现有字符串添加空格

时间:2016-09-01 09:27:20

标签: sql oracle

我在一个表中有一个字段作为名称,插入的名称没有空格。例如:“MarkJones”。

现在,我想在同一列中的人的名字和姓氏之间创建一个空格,以便使用Oracle函数显示为“Mark Jones”。

我试过这个查询

SELECT instr('MarkJones', '%||Upper(*)||%') AS substr1,
       SUBSTR('MarkJones', instr('MarkJones', '%lower(*)upper(*)%')) AS substr2,
       substr1||' '||substr2
FROM dual
;

但是,此查询无效。我想尝试使用oracle函数,包括translatesubstrinstr,但没有正则表达式。

2 个答案:

答案 0 :(得分:2)

此方法适用于给定的简单示例,但如果名称中包含多于2个大写字母,则会失败。如果这是预期的课程,可能要求解析名称的要求并不太难,因为我们都知道这充满了心痛,你永远不会占所有国家名字的100%。

无论如何,我的方法是在字符串中查找大写字母,如果找到则用空格后跟字母替换它们。我使用ASCII函数来测试它们的ascii值,看它们是否是一个大写字符。 CONNECT BY构造(需要循环遍历字符串的每个字符)返回其自己行中的每个字符,因此使用LISTAGG()重新组合回字符串并使用ltrim删除前导空格。

我怀疑如果这是课程作业,它可能会使用你不应该使用的一些功能。至少你应该明白接收和/或提供完整规范的重要性!

SQL> with tbl(name) as (
     select 'MarkJones' from dual
   )
   select ltrim(listagg(case
          when ascii(substr(name, level, 1)) >= 65 AND
               ascii(substr(name, level, 1)) <= 90 THEN
            ' ' || substr(name, level, 1)
          else substr(name, level, 1)
          end, '')
          within group (order by level)) fixed
   from tbl
   connect by level <= length(name);

FIXED
------------------------------------
Mark Jones

当你准备好了,无论如何这里是regexp_replace版本:-) 查找并“记住”第二次出现的大写字符,然后用空格和“记住的”大写字符替换它。

SQL> with tbl(name) as (
     select 'MarkJones' from dual
   )
   select regexp_replace(name, '([A-Z])', ' \1', 1, 2) fixed
   from tbl;

FIXED
----------
Mark Jones

答案 1 :(得分:1)

不确定我们是否应该反对@Alex Poole的建议,但它看起来像是一项家庭作业。

所以我的想法是指出第二个大写。如果你创建一组大写的情况,你可以在其上评估输入字符串iStr中的位置。然后,如果您被允许使用length,您也可以使用此职位来构建firstName

SELECT  substr(iStr, 1, length(iStr)-length(substr(iStr, instr(iStr, u)))) firstName
      , substr(iStr, instr(iStr, u))                                       lastName
      , substr(iStr, 1, length(iStr)-length(substr(iStr, instr(iStr, u)))) ||' '|| 
        substr(iStr, instr(iStr, u))                                       BINGO
FROM (           select 'MarkJones' iStr from dual
       union all select 'SomeOtherNames' from dual -- 2 u-cases gives 2 different results
       union all select 'SomeOtherOols'  from dual -- only one result
       union all select 'AndJim'         from dual
       union all select 'JohnLenon'      from dual
       union all select 'LemingWay'      from dual
     ),
     (           select 'A' U from dual
       union all select 'B'   from dual
       union all select 'C'   from dual
       union all select 'D'   from dual
       union all select 'E'   from dual
       union all select 'F'   from dual
       union all select 'G'   from dual
       union all select 'H'   from dual
       union all select 'I'   from dual
       union all select 'J'   from dual
       union all select 'K'   from dual
       union all select 'L'   from dual
       union all select 'M'   from dual
       union all select 'N'   from dual
       union all select 'O'   from dual
       union all select 'P'   from dual
       union all select 'Q'   from dual
       union all select 'R'   from dual
       union all select 'S'   from dual
       union all select 'T'   from dual
       union all select 'U'   from dual
       union all select 'V'   from dual
       union all select 'W'   from dual
       union all select 'X'   from dual
       union all select 'Y'   from dual
       union all select 'Z'   from dual
) upper_cases
where instr(iStr, U) > 1
;