使用Oracle SQL将ID值更新为XXXXXXXX-X格式

时间:2019-06-24 11:08:03

标签: sql regex oracle

表名:TEST 列名称:ID [VARCHAR(200)]

ID的格式为‘XXXXXXXX-X’,其中‘X’是从0到9的数字。 如果不满足上述格式,则需要执行其他操作:

  1. 如果ID由9位数字组成,并且在第8位和第9位数字之间有双破折号,则多余的破折号将被删除(例如08452142--6-> 08452142-6)

  2. 如果ID由9位数字组成,并且第八位和第九位数字和/或非数字和/或非字母符号之间存在空格,则将其替换为破折号(例如, 08452142-。3-> 08452142-3)

  3. 如果ID包含9位数字,并且以非数字和/或非字母符号开头/结尾,则删除该符号直至数字(例如08452142-2 ..-> 08452142 -2)

  4. 如果ID仅包含9位数字,则在最后一位数字前加上破折号(例如123456789-> 12345678-9)

通过使用以下代码段,我已经获得了必要的格式。

UPDATE TEST
  SET ID = (SELECT REGEXP_REPLACE(ID,'^\d{8}-\d{1}$','') AS "ID" 
            from TEST 
            WHERE PK = 11;
)

在单个查询中,如以上要点[1-4]所述,添加转换的可能方法是什么?

使用REGEXP_REPLACE,我可以以上述格式获得ID。但是如果格式不正确,并且需要对ID进行转换(例如删除多余的破折号,或者在接收到9位数字的情况下添加破折号)以获得令人满意的格式,那么如何在单个UPDATE查询中实现?

4 个答案:

答案 0 :(得分:0)

您可以使用以下我认为的内容:

UPDATE TEST
   SET ID = REGEXP_REPLACE(ID,'^\D*(\d{8})\D*(\d)\D*$','\1-\2')
 WHERE REGEXP_LIKE(ID,'^\D*(\d{8})\D*(\d)\D*$')

这样,您将忽略所有非数字字符,并搜索8位数字,然后搜索1位数字。取这两个数字,并在其之间插入一个“-”。

您可能会需要一些慷慨的选项,但应该可以使用您提供的所有示例。

答案 1 :(得分:0)

我认为您想输入前8位数字,然后是连字符,然后是9位数字:

select ( substr(regexp_replace(id, '[^0-9]', ''), 1, 8) ||
         '-' ||
         substr(regexp_replace(id, '[^0-9]', ''), 9, 1)
       )

答案 2 :(得分:0)

无论如何,您都需要在第一步中从字符串中提取9位数字。接着 在最后一个字符之前添加连字符。对于这两个步骤,请使用regexp_replace()函数

with test(id) as
(
 select '08452142--6'    from dual union all
 select '08452142 - . 3' from dual union all
 select '08452142-2..'   from dual union all
 select '123456789'      from dual union all
 select '1234567890'     from dual
)
select case when length(regexp_replace(id,'(\D)'))=9 then
            regexp_replace(regexp_replace(id,'(\D)'),
                                     '(^[[:digit:]]{8})(.*)([[:digit:]]{1}$)','\1-\3')
       end as id
  from test;

ID
----------
08452142-6
08452142-3
08452142-2
12345678-9
<null>

Demo

答案 3 :(得分:0)

我根据@BarbarosÖzhan的建议尝试了一种方法:

with source as (
    select  '02426467--6' id from dual union all
    select  '02426467-6' id from dual union all
    select  '02597718 -- .   3' id from dual union all
    select  '02597718 --dF5 .   3' id from dual union all
    select  '00120792-2..' id from dual union all
    select  '..00120792-2..' id from dual union all
    select  '123456789' id from dual union all
    select  '1234567890' id from dual
)
select
    case
        when regexp_like(id, '\d{8}-\d{1}')
            then id
        else
            case
        when regexp_like(id, '\d{8}-\d{1}')
            then id
        else
            case
                when regexp_count(id, '\d') = 9
                    then
                        case
                            when
                                regexp_like(
                                    regexp_replace(
                                        regexp_replace(
                                            id, '(\d{8}-)(-)(\d{1})', '\1\3' 
                                        ), '(\d{8})([^A-Za-z1-9])(\d{1})', '\1-\3' 
                                    )
                                , '\d{8}-\d{1}')
                                then
                                    regexp_replace(
                                        regexp_replace(
                                            id, '(\d{8}-)(-)(\d{1})', '\1\3' 
                                        ), '(\d{8})([^A-Za-z1-9])(\d{1})', '\1-\3' 
                                    )
                            else id
                        end
                else id
            end
    end id_tr
    from source

但是,在情况3和4中,我无法摆脱空格,点和字母。如果长度超过9,我认为逻辑有些问题。我以“ id”结尾,因此结果是相同的,没有任何修改。 有什么建议可以改善这一点吗?