如何使用SQL替换电话号码中的某些字符?

如何使用SQL替换电话号码中的某些字符?,sql,regex,oracle,oracle11g,regexp-replace,Sql,Regex,Oracle,Oracle11g,Regexp Replace,我有一个表Contact,其中包含所有带有电话号码的用户联系人,需要对电话号码进行一些转换 我需要查看所有电话号码,并: 删除电话号码中出现的下列字符序列(0) 当缺少和插入电话号码时,添加前缀+ 示例: +-----+-----------+----------+---------+------------------------+ | id | firstname | lastname | country | phone | +-----+------

我有一个表
Contact
,其中包含所有带有电话号码的用户联系人,需要对电话号码进行一些转换

我需要查看所有电话号码,并:

  • 删除电话号码中出现的下列字符序列
    (0)

  • 当缺少和插入电话号码时,添加前缀
    +

  • 示例:

    +-----+-----------+----------+---------+------------------------+
    | id  | firstname | lastname | country | phone                  |
    +-----+-----------+----------+---------+------------------------+
    | 100 | Frank     | Grob     |   PL    | +48 22 121 121 121     | <- OK
    | 101 | Bob       | Bloby    |   PL    | (0)22 121 121 121      | <- Wrong
    | 102 | Alice     | Wonder   |   US    | +1 (0) 121 121 121     | <- Wrong
    | 103 | Chris     | Black    |   US    | +1 (0) 121 121 121     | <- Wrong
    | 104 | Rocky     | Rocky    |   US    |  +1 (0) 121 121 121    | <- Wrong
    +-----+-----------+----------+---------+------------------------+
    
    +-----+--------------+--------+
    | id  | country_code | prefix |
    +-----+--------------+--------+
    | 100 | PL           | 48     |
    | 101 | US           | 1      |
    +-----+--------------+--------+
    
    CREATE TABLE contact_newphone AS
    SELECT c.id, c.firstname, c.lastname, c.country, c.phone
         , REGEXP_REPLACE(REGEXP_REPLACE(c.phone, '\(0\)\s*'), '^([^+])', '+' || cm.prefix || ' \1') AS new_phone
      FROM contact c, country_mapping cm
     WHERE REGEXP_LIKE(c.phone, '(^[^+]|\(0\))')
       AND c.country = cm.country_code
    
    UPDATE contact c
       SET c.phone = ( SELECT cn.newphone FROM contact_newphone cn
                        WHERE cn.id = c.id )
     WHERE REGEXP_LIKE(c.phone, '(^[^+]|\(0\))') -- don't want to update anyone's phone# that might have been fixed!
       AND EXISTS ( SELECT 1 FROM contact_newphone cn
                     WHERE cn.id = c.id )
    
    电话号码:
    +1(0)121

    需要转换为:
    +12121

    电话号码:
    (0)121

    需要转换为:
    +12121

    电话号码:
    121

    需要转换为:
    +12121

    根据第1点: 我们可以通过查询选择所有电话号码:

    select phone from contact where phone like '%(0)%';
    
    但是如何仅从数字中删除该序列
    (0)
    ?如何为此创建更新查询

    根据第2点: 如何识别电话号码是否不包含国家/地区直拨号码(前缀
    +
    ),如果缺少,如何添加正确的号码? 也许可以通过此查询选择这些数字:

    select phone from contact where phone not like '%+%';
    
    我们可以这样假设。我们还假设Contact table中有一列country,对于country Code List,我们可以基于此->创建临时映射表。我们可以简单地创建一个包含国家代码国家前缀映射的临时表,如下所示

    我想应该可以调用更新查询,在第一步中,该查询将选择错误格式的所有电话号码,在第二步中,该查询将使用新的正确值进行更新,对吗? 我不太懂SQL,所以请帮我创建这样一个SQL查询

    表格联系人:

    +-----+-----------+----------+---------+------------------------+
    | id  | firstname | lastname | country | phone                  |
    +-----+-----------+----------+---------+------------------------+
    | 100 | Frank     | Grob     |   PL    | +48 22 121 121 121     | <- OK
    | 101 | Bob       | Bloby    |   PL    | (0)22 121 121 121      | <- Wrong
    | 102 | Alice     | Wonder   |   US    | +1 (0) 121 121 121     | <- Wrong
    | 103 | Chris     | Black    |   US    | +1 (0) 121 121 121     | <- Wrong
    | 104 | Rocky     | Rocky    |   US    |  +1 (0) 121 121 121    | <- Wrong
    +-----+-----------+----------+---------+------------------------+
    
    +-----+--------------+--------+
    | id  | country_code | prefix |
    +-----+--------------+--------+
    | 100 | PL           | 48     |
    | 101 | US           | 1      |
    +-----+--------------+--------+
    
    CREATE TABLE contact_newphone AS
    SELECT c.id, c.firstname, c.lastname, c.country, c.phone
         , REGEXP_REPLACE(REGEXP_REPLACE(c.phone, '\(0\)\s*'), '^([^+])', '+' || cm.prefix || ' \1') AS new_phone
      FROM contact c, country_mapping cm
     WHERE REGEXP_LIKE(c.phone, '(^[^+]|\(0\))')
       AND c.country = cm.country_code
    
    UPDATE contact c
       SET c.phone = ( SELECT cn.newphone FROM contact_newphone cn
                        WHERE cn.id = c.id )
     WHERE REGEXP_LIKE(c.phone, '(^[^+]|\(0\))') -- don't want to update anyone's phone# that might have been fixed!
       AND EXISTS ( SELECT 1 FROM contact_newphone cn
                     WHERE cn.id = c.id )
    

    这应该不难。如果您的
    联系人
    表中有一个国家代码列,并且有一个单独的表
    国家/地区映射
    ,那么这样的查询可能如下所示(仅供参考,波兰的前缀是
    48
    ,正如您在
    联系人
    表中正确显示的那样,而不是
    22
    您在
    国家/地区映射
    表中正确显示的那样):

    对于
    更新
    ,我建议如下:

    1。根据上面的查询创建一个临时表:

    +-----+-----------+----------+---------+------------------------+
    | id  | firstname | lastname | country | phone                  |
    +-----+-----------+----------+---------+------------------------+
    | 100 | Frank     | Grob     |   PL    | +48 22 121 121 121     | <- OK
    | 101 | Bob       | Bloby    |   PL    | (0)22 121 121 121      | <- Wrong
    | 102 | Alice     | Wonder   |   US    | +1 (0) 121 121 121     | <- Wrong
    | 103 | Chris     | Black    |   US    | +1 (0) 121 121 121     | <- Wrong
    | 104 | Rocky     | Rocky    |   US    |  +1 (0) 121 121 121    | <- Wrong
    +-----+-----------+----------+---------+------------------------+
    
    +-----+--------------+--------+
    | id  | country_code | prefix |
    +-----+--------------+--------+
    | 100 | PL           | 48     |
    | 101 | US           | 1      |
    +-----+--------------+--------+
    
    CREATE TABLE contact_newphone AS
    SELECT c.id, c.firstname, c.lastname, c.country, c.phone
         , REGEXP_REPLACE(REGEXP_REPLACE(c.phone, '\(0\)\s*'), '^([^+])', '+' || cm.prefix || ' \1') AS new_phone
      FROM contact c, country_mapping cm
     WHERE REGEXP_LIKE(c.phone, '(^[^+]|\(0\))')
       AND c.country = cm.country_code
    
    UPDATE contact c
       SET c.phone = ( SELECT cn.newphone FROM contact_newphone cn
                        WHERE cn.id = c.id )
     WHERE REGEXP_LIKE(c.phone, '(^[^+]|\(0\))') -- don't want to update anyone's phone# that might have been fixed!
       AND EXISTS ( SELECT 1 FROM contact_newphone cn
                     WHERE cn.id = c.id )
    
    2。从临时表更新:

    +-----+-----------+----------+---------+------------------------+
    | id  | firstname | lastname | country | phone                  |
    +-----+-----------+----------+---------+------------------------+
    | 100 | Frank     | Grob     |   PL    | +48 22 121 121 121     | <- OK
    | 101 | Bob       | Bloby    |   PL    | (0)22 121 121 121      | <- Wrong
    | 102 | Alice     | Wonder   |   US    | +1 (0) 121 121 121     | <- Wrong
    | 103 | Chris     | Black    |   US    | +1 (0) 121 121 121     | <- Wrong
    | 104 | Rocky     | Rocky    |   US    |  +1 (0) 121 121 121    | <- Wrong
    +-----+-----------+----------+---------+------------------------+
    
    +-----+--------------+--------+
    | id  | country_code | prefix |
    +-----+--------------+--------+
    | 100 | PL           | 48     |
    | 101 | US           | 1      |
    +-----+--------------+--------+
    
    CREATE TABLE contact_newphone AS
    SELECT c.id, c.firstname, c.lastname, c.country, c.phone
         , REGEXP_REPLACE(REGEXP_REPLACE(c.phone, '\(0\)\s*'), '^([^+])', '+' || cm.prefix || ' \1') AS new_phone
      FROM contact c, country_mapping cm
     WHERE REGEXP_LIKE(c.phone, '(^[^+]|\(0\))')
       AND c.country = cm.country_code
    
    UPDATE contact c
       SET c.phone = ( SELECT cn.newphone FROM contact_newphone cn
                        WHERE cn.id = c.id )
     WHERE REGEXP_LIKE(c.phone, '(^[^+]|\(0\))') -- don't want to update anyone's phone# that might have been fixed!
       AND EXISTS ( SELECT 1 FROM contact_newphone cn
                     WHERE cn.id = c.id )
    
    3。删除“临时”表,或者将其作为旧的、坏的电话号码的备份。

    更新:如果在
    phone
    列中有前导空格,您可以在步骤1中执行以下操作

    CREATE TABLE contact_newphone AS
    SELECT c.id, c.firstname, c.lastname, c.country, c.phone
         , REGEXP_REPLACE(REGEXP_REPLACE(REGEXP_REPLACE(c.phone, '^\s+'), '\(0\)\s*'), '^([^+])', '+' || cm.prefix || ' \1') AS new_phone
      FROM contact c, country_mapping cm
     WHERE REGEXP_LIKE(c.phone, '(^[^+]|\(0\))')
       AND c.country = cm.country_code
    

    这也将删除电话号码中的前导空格。乍一看,我想说的是查看regexp\u replace没有一个简单的解决方案。例如,您可以在这里查看类似的问题(php+regexp)@TomášFejfar引用了通过正则表达式满足的标准要求,这相当具有挑战性,@Patrick,我不同意。这在支持POSIX正则表达式的Oracle中并不难做到。@David Faber是的,如果我们只清理带有
    (0)
    或缺少国家/地区直拨号码的电话号码,这是可行的(您的解决方案可以实现这一点)。如果我们想确保一个数字符合E.164标准,这是一个挑战(这里没有要求)。谢谢David,这是一个极好的解决方案!还有一个问题需要澄清另一种可能的情况:您的正则表达式条件应该如何更改以“+前缀”开头的电话号码-正如您在mark
    +
    之前看到的,我们可以有一个空格,甚至两个空格?我会使用
    TRIM()
    在应用正则表达式覆盖该情况之前,在
    c.phone
    的值上。如果您必须担心其他空白字符,那么可以使用
    REGEXP\u REPLACE()
    来完成此操作。如果您需要帮助,请告诉我,我会相应地更新我的答案。我对如何更新您的查询非常感兴趣,可以吗?我正在使用
    \s*
    添加regex表达式中的某个地方,但到目前为止还没有成功。