我有一个SQL问题,我对SQL比较陌生,所以请不要介意,如果这太天真了。我正在努力在ORACLE中将值从一个表更新到另一个表。
表Person
PersonID BirthPlace
---------------------------
1 Madison,WI,USA
2 Chicago,IL
3 Houston,TX,USA
4 Madison,WI,USA
5 Madison,WI,USA
6 Houston,TX,USA
7 NULL
表PersonProfile
PersonID CITY STATE COUNTRY
-------------------------------------------------
1 Madison WI USA
2 Chicago IL NULL
3 NULL NULL NULL
4 NULL WI NULL
5 NULL NULL USA
6 HOUSTON NULL NULL
7 NULL NULL NULL
我需要使用Table Person中的值更新Table Person Profile,并且只需要更新Table Person Profile中具有空值的列,并且如果两个表都具有null值,那么我需要输入' Unknown&# 39;
我可以编写单独的更新语句来更新每列中的值,例如更新城市:
Update PersonProfile PF
SET PF.CITY= (SELECT
CASE
WHEN PP.CITY LIKE '%MADISON%'
THEN 'MADISON'
WHEN PP.CITY LIKE '% Houston%'
THEN 'HOUSTON'
WHEN PP.CITY LIKE '% CHICAGO%'
THEN 'CHICAGO'
ELSE
'UNKNOWN'
END AS CITY
FROM PERSON PP
WHERE PF.PERSONID=PP.PERSON.ID
AND PF.CITY IS NULL)
以及用于更新州和国家/地区的类似查询。
我的问题是,有什么方法可以编写单个更新语句来更新所有三列而不是逐个更新它们?如果我可以在解码函数中使用like运算符,而不是使用CASE语句?
答案 0 :(得分:1)
是的,要么更新像:
这样的元组set (city, state, country) = (select case when pp.city like ... end as city
, case when ... end as state
, case ... end as country)
我怀疑最好创建一个表函数(我假设这些存在于Oracle中),它将字符串拆分为三列,使用,作为分隔符然后使用merge(假设这在Oracle中存在)来更新。类似的东西:
merge into t2
using t1 (
select personid, table(split(birthplace))
from t1
) x (PersonID, CITY, STATE, COUNTRY)
on t2.person_id = x.personid
when matched
set t2.city = case when t2.city is null then x.city else t2.city end
, t2.state = ...
, ...
答案 1 :(得分:1)
使用多列更新和正则表达式来解析逗号上的出生地数据。
update PERSONPROFILE pp
set (city, state, country) = (
select nvl(REGEXP_SUBSTR (BIRTHPLACE, '[^,]+', 1, 1), 'UNKNOWN'), -- city
nvl(REGEXP_SUBSTR (BIRTHPLACE, '[^,]+', 1, 2), 'UNKNOWN'), -- state
nvl(REGEXP_SUBSTR (BIRTHPLACE, '[^,]+', 1, 3), 'UNKNOWN') -- country
from PERSON p
where p.id = pp.id);
正则表达式匹配0个或多个与逗号不匹配的字符,第一次出现在城市,第二次出现在州等等。将其包裹在NVL中以设置为" UNKNOWN"如果出现是NULL。
UPDATE :我已经知道应该避免使用正则表达式'[^,]+'
,因为当列表中有NULL元素并且您选择该元素或其后的元素时它会失败。改为使用它,因为它允许NULL:
update PERSONPROFILE pp
set (city, state, country) = (
select nvl(REGEXP_SUBSTR (BIRTHPLACE, '([^,]*)(,|$)', 1, 1, NULL, 1)), 'UNKNOWN'), -- city
nvl(REGEXP_SUBSTR (BIRTHPLACE, '([^,]*)(,|$)', 1, 2, NULL, 1)), 'UNKNOWN'), -- state
nvl(REGEXP_SUBSTR (BIRTHPLACE, '([^,]*)(,|$)', 1, 3, NULL, 1)), 'UNKNOWN') -- country
from PERSON p
where p.id = pp.id);
有关详细信息,请参阅此帖子:Split comma seperated values to columns
答案 2 :(得分:0)
您需要检查您的设计 - 当您处理邮政地址并策划用户输入的值时(我假设您正在做),有几个极端情况。
这已在SO:
中讨论过SQL数据库设计最佳实践(地址) SQL Database Design Best Practice (Addresses)
如何在任何SQL数据库中最佳地设计地址位置? How to best design address locations in any SQL Database?
将邮政地址存储在数据库(RDBMS)中的最佳做法? Best practices for storing postal addresses in a database (RDBMS)?
在SQL数据库中存储地址的最佳实践/标准 Best Practice / Standard for storing an Address in a SQL Database