如何更新现有记录

时间:2018-06-09 21:50:27

标签: sql oracle sql-update

我有一个层次结构的位置表:

  

国家>状态>城市>站点

位置名称是唯一的。 LOCATION2PARENTLOCATION列具有层次关系。

CREATE TABLE "LOCATION" 
   ("LOCATIONID" NUMBER, 
    "NAME" VARCHAR2(50 CHAR), 
    "ALIAS1" VARCHAR2(50 CHAR), 
    "TOWNCITY" VARCHAR2(50 CHAR), 
    "STATE" VARCHAR2(50 CHAR), 
    "COUNTRY" VARCHAR2(50 CHAR), 
    "LOCATION2PARENTLOCATION" NUMBER,
    "LOCATION2LOCATIONTYPE" VARCHAR2(50 CHAR), 
    CONSTRAINT location_id_pk   PRIMARY KEY (LOCATIONID),
    CONSTRAINT location_name_uq UNIQUE(NAME)
   );
INSERT INTO LOCATION VALUES (1,'India',null,null,null,null,null,'COUNTRY');
INSERT INTO LOCATION VALUES (2,'Bihar','BH',null,null,null,1,'STATE');
INSERT INTO LOCATION VALUES (3,'Maharashtra','MH',null,null,null,1,'STATE');
INSERT INTO LOCATION VALUES (4,'Aurangabad',null,null,null,null,2,'CITY');
INSERT INTO LOCATION VALUES (5,'Patna',null,null,null,null,2,'CITY');
INSERT INTO LOCATION VALUES (6,'Pune',null,null,null,null,3,'CITY');
INSERT INTO LOCATION VALUES (8,'Aurangabad,BH',null,null,null,null,2,'CITY');
INSERT INTO LOCATION VALUES (9,'Aurangabad,MH',null,null,null,null,3,'CITY');
INSERT INTO LOCATION VALUES (10,'Deo',null,'Aurangabad','Bihar','India',4,'SITE');
INSERT INTO LOCATION VALUES (11,'Obra',null,'Aurangabad','Bihar','India',4,'SITE');
INSERT INTO LOCATION VALUES (12,'Kutumba',null,'Aurangabad,BH','Bihar','India',8,'SITE');
INSERT INTO LOCATION VALUES (13,'Dura',null,'Aurangabad,BH','Bihar','India',8,'SITE');
INSERT INTO LOCATION VALUES (14,'Dhanpura',null,'Patna','Bihar','India',5,'SITE');
INSERT INTO LOCATION VALUES (15,'Shekhpura',null,'Patna','Bihar','India',5,'SITE');
INSERT INTO LOCATION VALUES (16,'Hadapsar',null,'Pune','Maharashtra','India',6,'SITE');
INSERT INTO LOCATION VALUES (17,'Baner',null,'Pune','Maharashtra','India',6,'SITE');
INSERT INTO LOCATION VALUES (18,'Cidco',null,'Aurangabad,MH','Maharashtra','India',9,'SITE');
INSERT INTO LOCATION VALUES (19,'Mukundwadi',null,'Aurangabad,MH','Maharashtra','India',9,'SITE');
  

问题陈述:

有些城市名称在多个州之间很常见。

例如。奥兰加巴德是马哈拉施特拉邦和比哈尔邦的一座城市,就像其他许多例子一样。 由于Name是唯一的,因此table不允许我在带有层次结构的位置表中插入重复的城市名称。

  

解决问题:

为了维护位置之间的层次结构,我决定在城市名称中附加州代码(State的Alias1列)。 这将是一个独特的名称。

有关。例如。

  • 巴特那市将更新'Patna,BH'
  • 用'Pune,MH'点赞
  • 比哈尔邦的奥兰加巴德将更新'Aurangabad,BH'
  • 马哈拉施特拉邦的奥兰加巴德将更新'Aurangabad,MH'
  

SQL问题:

我想在旧的现有记录中使用“City,StateCode”更新所有城市名称。 但是有些城市已经在'Aurangabad'和'Aurangabad,BH'创建了两个城市。 这是不允许我更新旧的现有记录。

UPDATE LOCATION L1
SET L1.NAME= L1.NAME ||','||(SELECT L2.ALIAS1 FROM LOCATION L2 WHERE L1.location2parentlocation = L2.LOCATIONID AND L2.location2LOCATIONTYPE='STATE')
WHERE L1.location2locationtype='CITY'
and L1.name not like '%,%';

UPDATE LOCATION L10
SET TOWNCITY= (SELECT NAME FROM LOCATION L11  WHERE L11.LOCATIONID=L10.location2parentlocation AND L11.location2LOCATIONTYPE='CITY')
WHERE L10.LOCATION2LOCATIONTYPE='SITE';


Oracle Error:
SQL Error: ORA-00001: unique constraint (LOCATION_NAME_UQ) violated
00001. 00000 -  "unique constraint (%s.%s) violated"
*Cause:    An UPDATE or INSERT statement attempted to insert a duplicate key.
           For Trusted Oracle configured in DBMS MAC mode, you may see
           this message if a duplicate entry exists at a different level.
*Action:   Either remove the unique restriction or do not insert the key.

如果我删除带有'City,StateCode'的记录,则上述更新语句将起作用,但我不想删除任何记录。

delete from location where locationid in (8,9,12,13,18,19);
Question:

如何更新旧的现有记录并维护层次关系。

1 个答案:

答案 0 :(得分:2)

  

但我不想删除任何记录。

在我看来,你真的有重复的数据。 LOCATIONID 4和LOCATIONID 8真正代表同一个城市,其中一个应该去。

如果这是正确的,首先需要在一个ID下合并城市4和8的SITE记录。然后我们可以删除另一个。

这是一个MERGE语句(带有注释),可以完成所有这些操作。

它基本上确定了我们如何重命名和重新编号城市,确定具有给定名称和最低城市ID的城市ID。陈述我们将保持的状态。它将整合将要保留的城市下的站点记录,并删除重复且不再需要的城市。

MERGE INTO location t
USING (
-- This query will list each location along with (for cities and sites) the new city name and city ID to use
WITH city_rename AS (
SELECT city.locationid, 
       city.name city_name, 
       state.name state_name, 
       state.alias1 state_alias1, 
       case when city.name like '%,' || state.alias1 THEN city.name ELSE city.name || ',' || state.alias1 END new_city_name,
       row_number() over ( partition by case when city.name like '%,' || state.alias1 THEN city.name ELSE city.name || ',' || state.alias1 END order by city.locationid ) rn,
       min(city.locationid) over ( partition by case when city.name like '%,' || state.alias1 THEN city.name ELSE city.name || ',' || state.alias1 END order by city.locationid ) new_city_id
FROM   location city
INNER JOIN location state ON state.locationid = city.location2parentlocation
WHERE  city.location2locationtype = 'CITY' )
SELECT l.*, cr.new_city_name, cr.new_city_id FROM location l
LEFT JOIN city_rename cr ON cr.locationid IN (l.locationid, l.location2parentlocation) ) u
ON ( t.locationid = u.locationid )
WHEN MATCHED THEN 
-- Update each CITY and SITE record according to the city renaming results above
UPDATE SET
   -- Rename the city
   t.name = CASE WHEN t.location2locationtype = 'CITY' THEN u.new_city_name ELSE t.name END,
   -- Redirect the sites to the unique city ID for the new city name
   t.location2parentlocation = CASE WHEN t.location2locationtype = 'SITE' THEN u.new_city_id ELSE t.location2parentlocation END,
   -- Rename the towncity for the sites
   t.towncity = CASE WHEN t.location2locationtype = 'SITE' THEN u.new_city_name ELSE t.towncity END
-- Finally, as part of the MERGE, delete any cities that are not unique for the new city name.  Any SITE records 
-- previously tied to this city will have been redirect to the main ID for the new city name by the above logic
DELETE WHERE t.location2locationtype = 'CITY' and u.new_city_id != t.locationid;

在上述MERGE之后,您的LOCATION表格如下:

+------------+---------------+--------+---------------+-------------+---------+-------------------------+-----------------------+
| LOCATIONID |     NAME      | ALIAS1 |   TOWNCITY    |    STATE    | COUNTRY | LOCATION2PARENTLOCATION | LOCATION2LOCATIONTYPE |
+------------+---------------+--------+---------------+-------------+---------+-------------------------+-----------------------+
|          1 | India         |  -     |  -            |  -          |  -      |                      -  | COUNTRY               |
|          2 | Bihar         | BH     |  -            |  -          |  -      |                       1 | STATE                 |
|          3 | Maharashtra   | MH     |  -            |  -          |  -      |                       1 | STATE                 |
|          4 | Aurangabad,BH |  -     |  -            |  -          |  -      |                       2 | CITY                  |
|          5 | Patna,BH      |  -     |  -            |  -          |  -      |                       2 | CITY                  |
|          6 | Pune,MH       |  -     |  -            |  -          |  -      |                       3 | CITY                  |
|          9 | Aurangabad,MH |  -     |  -            |  -          |  -      |                       3 | CITY                  |
|         10 | Deo           |  -     | Aurangabad,BH | Bihar       | India   |                       4 | SITE                  |
|         11 | Obra          |  -     | Aurangabad,BH | Bihar       | India   |                       4 | SITE                  |
|         12 | Kutumba       |  -     | Aurangabad,BH | Bihar       | India   |                       4 | SITE                  |
|         13 | Dura          |  -     | Aurangabad,BH | Bihar       | India   |                       4 | SITE                  |
|         14 | Dhanpura      |  -     | Patna,BH      | Bihar       | India   |                       5 | SITE                  |
|         15 | Shekhpura     |  -     | Patna,BH      | Bihar       | India   |                       5 | SITE                  |
|         16 | Hadapsar      |  -     | Pune,MH       | Maharashtra | India   |                       6 | SITE                 |
|         17 | Baner         |  -     | Pune,MH       | Maharashtra | India   |                       6 | SITE                 |
|         18 | Cidco         |  -     | Aurangabad,MH | Maharashtra | India   |                       9 | SITE                 |
|         19 | Mukundwadi    |  -     | Aurangabad,MH | Maharashtra | India   |                       9 | SITE                 |
+------------+---------------+--------+---------------+-------------+---------+-------------------------+-----------------------+

注意LOCATIONID 8如何消失,以前引用它的所有记录现在都引用LOCATIONID 4.