最近研究sql優化,以下文章**網際網路:
1. 語法
單錶:update 表名稱
set 列名稱
= 新值
where 列名稱
= 某值
如:update t_join_situation set join_state='1'whereyear='2011'
更新年度為「2011」的資料的join_state欄位為「1」。如果更新的字段加了索引,更新時會重建索引,更新效率會慢。
多表關聯,並把乙個表的字段值更新到另乙個表中的字段去:
update 表a set a.欄位1 = (select b.欄位1 from 表b where a.欄位2=b.欄位2) where exists(select 1 from 表b where a.欄位2=b.欄位2)
oracle的更新語句不通mssql那麼簡單易寫,就算寫出來了,但執行時可能會報
這是由於
set**的子查詢查出了多行資料值,
oracle規定一對一更新資料,所以提示出錯。要解決這樣必須保證查出來的值一一對應。
2. 原理
update語句的原理是先根據
where條件查到資料後,如果
set中有子查詢,則執行子查詢把值查出來賦給更新的字段,執行更新。
如:update 表a set a.欄位1 = (select b.欄位1 from 表b where a.欄位2=b.欄位2) where exists(select 1 from 表b where a.欄位2=b.欄位2)。查表a的所有資料,迴圈每條資料,驗證該條資料是否符合exists(select 1 from 表b where a.欄位2=b.欄位2)條件,如果是則執行(select b.欄位1 from 表b where a.欄位2=b.欄位2)查詢,查到對應的值更新a.欄位1中。關聯表更新時一定要有exists(select 1 from 表b where a.欄位2=b.欄位2)這樣的條件,否則將表a的其他資料的字段1更新為null值。
二、 提高
oracle更新效率的各種解決方案
1. 標準
update語法
當你需要更新的表是單個或者被更新的字段不需要關聯其他錶帶過來,則最後選擇標準的
update語句,速度最快,穩定性最好,並返回影響條數。如果
where條件中的字段加上索引,那麼更新效率就更高。但對需要關聯表更新欄位時,
update的效率就非常差。 2.
inline view更新法
inline view更新法就是更新乙個臨時建立的檢視。如:update (select a.join_state asjoin_state_a,b.join_state as join_state_b
from t_join_situation a, t_people_info b where a.people_number=b.people_number
and a.year='2011'and a.city_number='m00000'and a.town_number='m51000') setjoin_state_a=join_state_b
括號裡通過關聯兩表建立乙個檢視,set中設定好更新的字段。這個解決方法比寫法較直觀且執行速度快。但表b的主鍵一定要在where條件中,並且是以「=」來關聯被更新表,否則報一下錯誤:
3.merge更新法
merge是oracle特有的語句,語法如下:
merge into table_name alias1
using (table|view|sub_query) alias2
on (join condition)
when matched then
update table_name
set col1 = col_val1,
col2 = col2_val
when not matched then
insert (column_list) values (column_values);
它的原理是在alias2中select出來的資料,每一條都跟alias1進行 on (join condition)的比較,如果匹配,就進行更新的操作(update),如果不匹配,就進行插入操作(insert)。執行merge不會返回影響的行數。merge語句的寫法比較繁瑣,並且最多只能兩個表關聯,複雜的語句用merge更新法將力不從心且效率差。
4.快速游標更新法
語法如:
begin
for cr in (查詢語句) loop –-迴圈
--更新語句(根據查詢出來的結果集合)
endloop; --結束迴圈
end;
oracle支援快速游標,不需要定義直接把游標寫到for迴圈中,這樣就方便了我們批量更新資料。再加上oracle的rowid物理字段(oracle預設給每個表都有rowid這個字段,並且是唯一索引),可以快速定位到要更新的記錄上。
例子如下:
begin
for cr in (select a.rowid,b.join_state from t_join_situation a,t_people_info b
where a.people_number=b.people_number
and a.year='2011'and a.city_number='m00000'and a.town_number='m51000') loop
update t_join_situation set join_state=cr.join_state where
rowid = cr.rowid;
endloop;
end;
使用快速游標的好處很多,可以支援複雜的查詢語句,更新準確,無論資料多大更新效率仍然高,但執行後不返回影響行數。
三、結論
方案
建議標準
update語法
單錶更新或較簡單的語句採用使用此方案更優。
inline view更新法
兩表關聯且被更新表通過關聯表主鍵關聯的,採用此方案更優。
merge更新法
兩表關聯且被更新表不是通過關聯表主鍵關聯的,採用此方案更優。
快速游標更新法
多表關聯且邏輯複雜的,採用此方案更優。
實時測試的速度:
--48466
條資料
--1.297
update (select a.join_state as join_state_a,b.join_state as join_state_b
from t_join_situation a, t_people_info b where a.people_number=b.people_number
and a.year='2011'and a.city_number='m00000'and a.town_number='m51000'
) set join_state_a=join_state_b
--7.156
update t_join_situation a set a.join_state=(select b.join_state from t_people_info b
where a.people_number=b.people_number
and a.year='2011'and a.city_number='m00000'and a.town_number='m51000')
whereexists (select1from t_people_info b
where a.people_number=b.people_number
and a.year='2011'and a.city_number='m00000'and a.town_number='m51000')
--3.281
begin
for cr in (select a.rowid,b.join_state from t_join_situation a,t_people_info b
where a.people_number=b.people_number
and a.year='2011'and a.city_number='m00000'and a.town_number='m51000') loop
update t_join_situation set join_state=cr.join_state where
rowid = cr.rowid;
endloop;
end;
--1.641
mergeinto t_join_situation a
using t_people_info b
on (a.people_number=b.people_number
and a.year='2011'and a.city_number='m00000'and a.town_number='m51000')
whenmatchedthenupdateset a.join_state=b.join_state
ORACLE 多表關聯 UPDATE 語句
oracle 多表關聯 update 語句 兩表 多表 關聯update 僅在 where 字句中的連線 直接賦值 update customers a 使用別名 set customer type 01 where exists select 1 from tmp cust city b wher...
Oracle幾種update語句分析
1.單條語句更新 語法 update 表名稱 set 列名稱 新值 where 列名稱 某值 說明 如果更新的字段加了索引,更新時會重建索引,更新效率會慢。單錶更新或較簡單的語句採用使用此方案更優。2.批量資料更新 語法 update 表a set a.欄位1 select b.欄位1 from 表...
ORACLE多表關聯UPDATE 語句
1 最簡單的形式 sql 經確認customers表中所有customer id小於1000均為 北京 1000以內的均是公司走向全國之前的本城市的老客戶 update customers set city name 北京 where customer id 1000 2 兩表 多表 關聯updat...