A表customers和B表tmp_cust_city有3个相同字段, customer_id,city_name,customer_type 现要根据b表更新a表
更新一个字段情况:
update customers a
set city_name=(select b.city_name from tmp_cust_city b where b.customer_id=a.customer_id)
where exists (select 1 from tmp_cust_city b where b.customer_id=a.customer_id)
//最后的where exists条件不可省,因为如果省去,就会更新a表中所有记录,但是a表中存在的b表中无法匹配的记录。这些记录的city_name就会被设成null,产生重大数据事故。
除非使用nvl(exp1,exp2)函数:当一个表达式为null时,采用第二个表达式
update customers a
set city_name=nvl((select b.city_name from tmp_cust_city b where b.customer_id=a.customer_id),a.city_name) //这样可保持未匹配b表的a中的city_name保持a. city_name原值而不被null掉。
此外还有NVL2函数的格式如下:NVL2(expr1,expr2, expr3),exp1不为null,则采用exp2, 为null则采用exp3。(2016.4.21更正,验证)
更新多个字段情况:
update customers a
set (city_name,customer_type)=(select b.city_name,b.customer_type from tmp_cust_city b where b.customer_id=a.customer_id)
where exists (select 1 from tmp_cust_city b where b.customer_id=a.customer_id )
where exists功能与上面单字段相同。
还可以用视图的形式update更新
update (select a.city_name,b.city_name new_name
from customers a,
tmp_cust_city b
where b.customer_id=a.customer_id
)
set city_name=new_name
但前提是 A(customer_id) b(customer_id)必需是unique index或primary key。否则会报错:
ORA-01779, "cannot modify a column which maps to a non key-preserved table" 无法修改与非键值保存表对应的列
以上无论单字段还是多字段更新,都有个前提就是b表中的b.customer_id必须是唯一的,否则出错
例子:
//以下更新两张表的sql语句有内外两层where语句,但作用不一样,内层的where用于限定f2表中哪些(条)记录来更新f1,外层where条件用于限定f1中哪些记录需要更新
string sql = string.Format(@"update {0}.airway_point f1
set (airway_point_type_id,txt_name,code_id,geo_lat,geo_long,val_mag_var,code_fir,code_icaocode,code_fir_eag,code_icaocode_eag,code_icao,val_freq,val_elev,code_channel,code_type_waypoint,name_eng,txt_rmk,val_force_report,isvalid,modify_reason_id,modify_reason_add,uom_freq,code_sx,modified,date_lastmodify,val_current_state)
=
(
select f2.airway_point_type_id,f2.txt_name,f2.code_id,f2.geo_lat,f2.geo_long,f2.val_mag_var,f2.code_fir,f2.code_icaocode,f2.code_fir_eag,f2.code_icaocode_eag,f2.code_icao,f2.val_freq,f2.val_elev,f2.code_channel,f2.code_type_waypoint,f2.name_eng,f2.txt_rmk,f2.val_force_report,f2.isvalid,f2.modify_reason_id,f2.modify_reason_add,f2.uom_freq,f2.code_sx,1,sysdate,0
from {0}.airway_point_double f2
where
f2.significant_point_id=f1.significant_point_id and
f2.significant_point_id={1} and
f2.val_current_state=1
)
where f1.significant_point_id ={1}
", AisLogical.dbuser, pid);