识别PL / SQL迭代中的电话号码

时间:2015-09-16 10:33:20

标签: oracle plsql

我想更新一个包含PHONE_NUMBER和COUNTRY列的表(T_NUMBERS)。 COUNTY col为空(全为NULL),电话号码不唯一,格式为:“420575757111”(以国家代码开头,不带+或00)。国际呼叫代码存储在另一个表(INT_CODES)中,两列:INT_CODE,COUNTRY。看起来像这样:

COUNTRY     ||   INT_CODE
-------------------------
USA/CANADA  ||  1
RUSSIA      ||  7
EGYPT       ||  20
GREECE      ||  30
BELGIUM     ||  32
FRANCE      ||  33
HUNGARY     ||  36
COLOMBIA    ||  57
KENYA       ||  254
IRELAND     ||  353
GRENADA     ||  1473

等等。

我的概念是创建一个以下列方式工作的脚本:

  • 在第一轮比较电话号码的前4位数到INT_CODE并用INT_CODES.COUNTRY更新T_NUMBERS.COUNTRY字段,在那里找到匹配项,如下所示:

    INT_CODES.INT_CODE = SUBSTR(T_NUMBERS.PHONE_NUMBER,1,4)
    
  • 此后第二轮比较T_NUMBERS.COUNTRY仍为NULL的前3位数。

  • 在接下来的两轮中,以相同的方式检查2位和1位数代码,以便填写所有国家/地区字段,但不覆盖已填充的字段。

我的问题是我无法运行一个至少执行第一步的脚本,因为Oracle似乎不支持UPDATE语句中的JOIN,例如你可以在这里阅读:

Update statement with inner join on Oracle

我从答案中尝试了解决方案,但它不起作用:

SQL错误:ORA-01427:单行子查询返回多行

之后我尝试了这个(只有第一轮):

begin
for t_rows in c_code
loop

    update (select TN.COUNTRY as C_OLD, IC.COUNTRY as C_NEW from T_NUMBERS TN
    left join INT_CODES IC on IC.INT_CODE = substr(TN.PHONE_NUMBER,1,4) where
    TN.COUNTRY IS NULL) T_TAB

    set TAB.C_OLD = TAB.C_NEW;
close c_code;

end loop;

错误讯息: ORA-06512:第8行 01779. 00000 - “无法修改映射到非密钥保留表的列”

所以我的主要问题是:我应该在循环中插入什么语句? 我的问题:是否有任何其他解决方案可以产生相同的结果(无需创建更多表格或修改现有表格的结构)?

提前致谢。

2 个答案:

答案 0 :(得分:2)

这里需要一个循环吗?您必须将更新语句重写为以下内容:

UPDATE t_numbers tn
   SET tn.country = (SELECT ic.country
                       FROM int_codes ic
                      WHERE ic.int_code = substr(tn.phone_number, 1, 4))
 WHERE tn.country is null
   AND EXISTS (SELECT 1
                 FROM int_codes ic
                WHERE ic.int_code = substr(tn.phone_number, 1, 4));

然后重复3,2和1,如下(3):

UPDATE t_numbers tn
   SET tn.country = (SELECT ic.country
                       FROM int_codes ic
                      WHERE ic.int_code = substr(tn.phone_number, 1, 3))
 WHERE tn.country is null
   AND EXISTS (SELECT 1
                 FROM int_codes ic
                WHERE ic.int_code = substr(tn.phone_number, 1, 3));

<强>更新

您也可以循环4到1来完成任务

  begin
    for i in 1..4 loop
      UPDATE t_numbers tn
       SET tn.country = (SELECT ic.country
                           FROM int_codes ic
                          WHERE ic.int_code = substr(tn.phone_number, 1, (5-i)))
     WHERE tn.country is null
       AND EXISTS (SELECT 1
                     FROM int_codes ic
                    WHERE ic.int_code = substr(tn.phone_number, 1, (5-i)));
    end loop;
  END;

答案 1 :(得分:1)

我会说很难找到另一个sql-engine比oracle更丰富的功能。 我建议你设置sqlfiddle这样的问题。

UPDATE t_numbers tn SET
  tn.country = (
    SELECT ic.country 
    FROM int_codes ic 
    WHERE ic.int_code = substr(tn.phone_number, 1, 4)
  )
WHERE tn.country IS NULL;

如果你将它作为pl / sql脚本运行,你可以用循环包装它,以避免复制/粘贴。

BEGIN
  FOR i IN REVERSE 1..4
  LOOP
    UPDATE t_numbers tn SET
      tn.country = (
        SELECT ic.country 
        FROM int_codes ic 
        WHERE ic.int_code = substr(tn.phone_number, 1, i)
      )
    WHERE tn.country IS NULL;
  END LOOP;
END;

此代码依赖于int_code表中的列int_codes为英国的事实。