我想更新一个包含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 - “无法修改映射到非密钥保留表的列”
所以我的主要问题是:我应该在循环中插入什么语句? 我的问题:是否有任何其他解决方案可以产生相同的结果(无需创建更多表格或修改现有表格的结构)?
提前致谢。
答案 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
为英国的事实。