【问题标题】:How to replace some characters in phone number using SQL?如何使用 SQL 替换电话号码中的某些字符?
【发布时间】:2015-03-22 20:07:05
【问题描述】:

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

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

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

  2. 前缀+<country_code>在缺失和插入电话号码时添加;

示例:

电话号码:
+1 (0) 121 121 121
需要转换为:
+1 121 121 121

电话号码:
(0) 121 121 121
需要转换为:
+1 121 121 121

电话号码:
121 121 121
需要转换为:
+1 121 121 121

根据第1点:

我们可以选择所有有查询的电话号码:

select phone from contact where phone like '%(0)%';

但是如何仅从数字中删除该序列(0)?如何为此创建更新查询?

根据第2点:

如何识别电话号码是否不包含国家直拨号码(前缀+<country_code>)并在缺少时添加正确的号码? 也许这个查询应该可以选择这些数字:

select phone from contact where phone not like '%+%';

我们可以假设。假设我们在联系人表中有一个国家列,对于国家代码列表,我们可以基于此创建临时映射表 -> http://countrycode.org/。我们可以简单地创建一个包含国家代码 国家前缀映射的临时表,如下所示。

我想应该可以调用一个更新查询,它在第一步将选择格式错误的所有电话号码,在第二步将使用新的正确值进行更新,对吗? 我对 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
+-----+-----------+----------+---------+------------------------+

表 COUNTRY_MAPPING:

+-----+--------------+--------+
| id  | country_code | prefix |
+-----+--------------+--------+
| 100 | PL           | 48     |
| 101 | US           | 1      |
+-----+--------------+--------+

【问题讨论】:

  • 乍一看,我说看看 regexp_replace
  • 对此没有简单的解决方案。例如,您可以在这里查看类似的问题 (php + regexp),stackoverflow.com/questions/12551473/…。 @Tomáš Fejfar 引用了通过正则表达式来满足的标准要求,en.wikipedia.org/wiki/E.164
  • @Patrick,我不同意。这在支持 POSIX 正则表达式的 Oracle 中并不难做到。
  • @David Faber 是的,如果我们只是清理带有(0) 或缺少国家/地区直拨号码的电话号码,这是可行的(您的解决方案可以做到这一点)。如果我们想确保某个号码符合 E.164,这是具有挑战性的(此处未要求)。

标签: sql regex oracle oracle11g regexp-replace


【解决方案1】:

这应该不难。如果您的CONTACT 表中有一个国家代码列和一个单独的表COUNTRY_MAPPING,那么这样的查询可能看起来像这样(仅供参考,波兰的前缀是48,正如您在CONTACT 表中正确使用的那样,而不是22 就像您在 COUNTRY_MAPPING 表中一样):

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

Please see SQL Fiddle demo here.

对于UPDATE,我建议如下:

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

2。从该临时表更新:

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

Please see SQL Fiddle demo here. 这也将删除电话号码中原本不错的前导空格。

【讨论】:

  • 谢谢大卫,它的出色解决方案!澄清另一种可能情况的一个问题:如何更改您的正则表达式条件以涵盖以`+prefix`开头的电话号码-正如您在标记+之前看到的那样,我们可以有一个空格甚至几个空格?
  • 在应用正则表达式覆盖这种情况之前,我会在 c.phone 的值上使用 TRIM()。如果您必须担心其他空白字符,那么您可以使用 REGEXP_REPLACE() 来做到这一点。如果您需要帮助,请告诉我,我会相应地更新我的答案。
  • 我真的很感兴趣如何更新您的查询,请问可以吗?我正在使用\s* 在正则表达式中添加某处,但到目前为止还没有成功。
猜你喜欢
  • 1970-01-01
  • 2012-07-01
  • 2019-03-04
  • 2023-03-04
  • 2020-05-03
  • 1970-01-01
  • 2015-12-14
  • 1970-01-01
  • 2012-03-30
相关资源
最近更新 更多