当字段为空时,SQl更新列

时间:2014-08-08 14:41:44

标签: sql oracle decoding

我有一个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语句?

3 个答案:

答案 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:

中讨论过