久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

如何使用update 子查詢

162次閱讀
沒有評論

共計 4333 個字符,預計需要花費 11 分鐘才能閱讀完成。

本篇文章給大家分享的是有關如何使用 update 子查詢,丸趣 TV 小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著丸趣 TV 小編一起來看看吧。

1,關聯子查詢和非關聯子查詢

在非關聯子查詢中,內部查詢只執行一次并返回它的值給外部查詢,然后外部查詢在它的處理中使用內部查詢返回給它的值。而在關聯子查詢中,對于外部查詢返回的每一行數據,內部查詢都要執行一次。另外,在關聯子查詢中是信息流是雙向的。外部查詢的每行數據傳遞一個值給子查詢,然后子查詢為每一行數據執行一次并返回它的記錄。然后,外部查詢根據返回的記錄做出決策。

如:

SELECT o1.CustomerID, o1.OrderID, o1.OrderDate
FROM Orders o1
WHERE o1.OrderDate = (SELECT Max(OrderDate)
FROM Orders o2
WHERE o2.CustomerID = o1.CustomerID)

是一個關聯子查詢

SELECT o1.CustomerID, o1.OrderID, o1.OrderDate
FROM Orders o1
WHERE o1.OrderDate IN
(SELECT TOP 2 o2.OrderDate
FROM Orders o2
WHERE o2.CustomerID = o1.CustomerID)
ORDER BY CustomerID

是一個非關聯子查詢

2,提示(HINT)

一般在優化時,無論采用基于規則的或是基于代價的方法,由 Oracle 系統的優化器來決定語句的執行路徑。這樣的選擇的路徑不要見得是最好的。所以,Oracle 提供了一種方法叫提示的方法。它可以讓編程人員按照自己的要求來選擇執行路徑,即提示優化器該按照什么樣的執行規則來執行當前的語句。這樣可以在性能上比起 Oracle 優化自主決定要好些。

通常情況下,編程人員可以利用提示來進行優化決策。通過運用提示可以對下面內容進行指定:

l SQL 語句的優化方法;

l 對于某條 SQL 語句,基于開銷優化程序的目標;

l SQL 語句訪問的訪問路徑;
l 連接語句的連接次序;
l 連接語句中的連接操作。

如果希望優化器按照編程人員的要求執行,則要在語句中給出提示。提示的有效范圍有限制,即有提示的語句塊才能按照提示要求執行。下面語句可以指定提示:

l 簡單的 SELECT ,UPDATE ,DELETE 語句;
l 復合的主語句或子查詢語句;
l 組成查詢(UNION)的一部分。

提示的指定有原來的注釋語句在加“+”構成。語法如下:

[SELECT | DELETE|UPDATE] /*+ [hint | text] */

[SELECT | DELETE|UPDATE] –+ [hint | text]

注意在“/*”后不要空就直接加“+”,同樣“–+”也是連著寫。

警告:如果該提示語句書寫不正確,則 Oracle 就忽略掉該語句。

常見的提示有:

Ordered 強制按照 from 子句中指定的表的順序進行連接
Use_NL 強制指定兩個表間的連接方式為嵌套循環(Nested Loops)
Use_Hash 強制指定兩個表間的連接方式為哈希連接(Hash Join)
Use_Merge 強制指定兩個表間的連接方式為合并排序連接(Merge Join)
Push_Subq 讓非關聯子查詢提前執行
Index 強制使用某個索引

3,執行計劃

在 PL/SQL Developer 的 SQL WINDOWS 中用鼠標或鍵盤選中 SQL 語句,然后按 F5,就會出現執行計劃解析的界面:

4,Update 的特點

Update 的系統內部執行情況可以參照附文:對 update 事務的內部分析.doc

使用 Update 的基本要點就是,

1)盡量使用更新表上的索引,減少不必要的更新
2)更新的數據來源花費時間盡可能短,如果無法做到就把更新內容插入到中間表中,然后給中間表建上索引,再來更新
3)如果更新的是主鍵,建議刪除再插入。
5,示例用表

后面的闡述將圍繞以下兩張表展開:

Create table tab1 (workdate varchar2(8), cino varchar2(15), val1 number, val2 number);
Create table tab2 (workdate varchar2(8), cino varchar2(15), val1 number, val2 number);
Create table tab3 (workdate varchar2(8), cino varchar2(15), val1 number, val2 number);
Create table tab4 (workdate varchar2(8), cino varchar2(15), val1 number, val2 number);

workdate, cino 為兩張表的關鍵字,默認情況沒有建主鍵索引。

二,Update 兩種情況

用 Update 更新某個表,無外乎是兩種情況:根據關聯子查詢,更新字段;通過非關聯子查詢,限定更新范圍。如果還有第三種情況,那就是前兩種情況的疊加。

1,根據關聯子查詢,更新字段

Update tab1 t
Set (val1, val2) = (select val1, val2
from tab2
where workdate = t.workdate
and cino = t.cino);

通過 tab2 來更新 tab1 的相應字段。執行 SQL 語句時,系統會從 tab1 中一行一行讀記錄,然后再通過關聯子查詢,找到相應的字段來更新。關聯子查詢能否通過 tab1 的條件快速的查找到對應記錄,是優化能否實現的必要條件。所以一般都要求在 tab2 上建有 Unique 或者排重性較高的 Normal 索引。執行所用時間大概為(查詢 tab1 中一條記錄所用的時間 + 在 tab2 中查詢一條記錄所用的時間)* tab1 中的記錄條數。

如果子查詢條件比較復雜,如以下語句:

Update tab1 t
Set (val1, val2) = (select val1, val2
from tab2 tt
where exists (select 1
from tab3
where workdate = tt.workdate
and cino = tt.cino)
and workdate = t.workdate
and cino = t.cino);

這時更新 tab1 中的每條記錄花費在子查詢上的時間將成倍增加,如果 tab1 中的記錄數較多,這種更新語句幾乎是不可完成。

解決方式是,把子查詢提取出來,做到中間表中,然后給中間表建上索引,用中間表來代替子查詢,這樣速度就能大大提高:

Insert into tab4
select workdate, cino, val1, val2
from tab2 tt
where exists (select 1
from tab3
where workdate = tt.workdate
and cino = tt.cino);
create index tab4_ind01 on tab4(workdate, cino);
Update tab1 t
Set (val1, val2) = (select val1, val2
from tab4 tt
where workdate = t.workdate
and cino = t.cino);

2,通過非關聯子查詢,限定更新范圍

Update tab1 t
set val1 = 1
where (workdate, cino) in (select workdate, cino from tab2)

根據 tab2 提供的數據范圍,來更新 tab1 中的相應記錄的 val1 字段。

在這種情況下,系統默認執行方式往往是先執行 select workdate, cino from tab2 子查詢,在系統中形成系統視圖,然后在 tab1 中選取一條記錄,查詢系統視圖中是否存在相應的 workdate, cino 組合,如果存在,則更新 tab1,如果不存在,則選取下一條記錄。這種方式的查詢時間大致等于:子查詢查詢時間 +(在 tab1 中選取一條記錄的時間 + 在系統視圖中全表掃描尋找一條記錄時間)* tab1 的記錄條數。其中“在系統視圖中全表掃描尋找一條記錄時間”會根據 tab2 的大小而有所不同。若 tab2 記錄數較小,系統可以直接把表讀到系統區中;若 tab2 記錄數多,系統無法形成系統視圖,這時會每一次更新動作,就把子查詢做一次,速度會非常的慢。

針對這種情況的優化有兩種

1)在 tab1 上的 workdate, cino 字段上加入索引,同時增加提示。

修改以后的 SQL 語句如下:

Update /*+ordered use_nl(sys, t)*/ tab1 t
set val1 = 1
where (workdate, cino) in (select workdate, cino from tab2)

其中 sys 表示系統視圖。如果不加入 ordered 提示,系統將會默認以 tab1 表作為驅動表,這時就要對 tab1 作全表掃描。加入提示后,使用系統視圖,即 select workdate, cino from tab2,作為驅動表,在正常情況下,速度能提高很多。

2)在 tab2 表上的 workdate, cino 字段加入索引,同時改寫 SQL 語句:

Update tab1 t
set val1 = 1
where exists (select 1
from tab2
where workdate = t.workdate
and cino = t.cino)

三,索引問題

update 索引的使用比較特殊,有時看起來能用全索引,但實際上卻只用到一部分,所以建議把復合索引的各字段寫在一起。

例如:

Update /*+ordered use_nl(sys, t)*/ tab1 t
set val1 = 1
where cino in (select cino from tab2)
and workdate =  200506

這條 SQL 語句是不能完全用到 tab1 上的復合索引 workdate + cino 的。能用到的只是 workdate= 200506 的約束。

如果寫成這樣,就沒問題:

Update /*+ordered use_nl(sys, t)*/ tab1 t
set val1 = 1
where (workdate, cino) in (select workdate, cino from tab2)

以上就是如何使用 update 子查詢,丸趣 TV 小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注丸趣 TV 行業資訊頻道。

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-08-03發表,共計4333字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 渭南市| 昭苏县| 东乌珠穆沁旗| 老河口市| 敦煌市| 沂南县| 石渠县| 外汇| 花莲县| 那曲县| 玉山县| 安图县| 凯里市| 肥东县| 昆山市| 达州市| 沅陵县| 涞水县| 内黄县| 屯门区| 巴林左旗| 垫江县| 罗城| 溧水县| 桂平市| 清水县| 沙湾县| 玉龙| 长子县| 赤峰市| 璧山县| 金阳县| 黄平县| 平原县| 东台市| 华坪县| 沂源县| 泊头市| 南郑县| 大兴区| 兴隆县|