天天看點

.Net程式增删改查

<code>INSERT</code> 語句用來向表、分區或視圖中添加行。可以向單個表或者多個表中添加資料行。單表插入将會向一個表中插入一行資料,這行資料可以顯示地列出插入值也可以通過一個子查詢來擷取。多表插入将會向一個或多個表中插入行,并且會通過子查詢擷取值來計算所插入行的值。

<a></a>

如果你要插入表中所定義的所有字段的值,那麼字段的清單是可選的。但是如果你隻想提供部分字段的值,則必須在字段的清單中指明所需的字段名。建議即便要插入所有字段的值,也明确給出字段清單。文法:

示例:

文法:

同步插入:有時候我們需要把一張表中的資料分别插入到另外兩張表中,如果不加事物僅寫兩條 <code>INSERT</code> 語句分别添加是有問題的,因為表中資料完全有可能在第一條語句執行之後第二條語句執行之前發生了變化。如要将 <code>t_staff</code> 表中月薪達到 8000 的 90 員工分别添加到 <code>t_staff_high</code> 和 <code>t_staff_young</code> 兩個表中,示例:

有條件的插入:使用 <code>INSERT ALL</code> 語句還可以根據條件将資料插入到不同的表中。示例:

在上面的語句中,如果 <code>test_value=6</code>,崗位工資達到 5000 的員工會被插入到 <code>t_staff_high</code> 和 <code>t_staff_low</code> 兩張表中;如果 <code>test_value=7</code>,崗位工資達到 5000 的員工會被插入到 <code>t_staff_low</code> 表中;如果 <code>test_value=8</code>,崗位工資達到 5000 的員工會被插入到 <code>t_staff_copy</code> 表中。

假如 <code>test_value=6</code>,也就是前兩個條件都滿足時,優先執行第一個插入,當第一個條件不滿足時,再來判斷是否要執行第二個條件的插入,這種情況隻需把 <code>ALL</code> 換成 <code>FIRST</code> 即可實作。

<code>DELETE</code> 語句用來從表中移除資料行。該語句的文法結構由 3 部分組成:DELETE、FROM 和 WHERE。DELETE 關鍵字是單獨列出的,沒有其它選項與 DELETE 關鍵字相結合(hint除外)。FROM 子句用來指定要從那個表中删除資料行。WHERE 子句提供篩選條件有助于确定那些行是要删除的。文法:

<code>TRUNCATE</code> 語句是用來清空表中資料的。從表面上看它的效果與不帶 <code>WHERE</code> 條件的 <code>DELETE</code> 語句效果是一樣的。它有 4 個特點,分别是:

1、删除表全部内容,但保留表結構;

2、速度快,但不可復原,這意味着資料删除後無法再恢複;

3、觸發器中不能使用,因為 <code>TRUNCATE</code> 語句不會觸發任何操作;

4、<code>DELETE</code> 語句每删除一行資料都是一個事務,會産生若幹“日志”。但 <code>TRUNCATE</code> 語句是釋放整個資料頁(一個頁 8K)。

TRUNCATE TABLE target_table

[ PRESERVE MATERIALIZED VIEW LOG | PURGE MATERIALIZED VIEW LOG ][ DROP STORAGE | REUSE STORAGE ];

如要把 <code>t_staff_high</code> 表中所有資料全部删除,示例:

<code>UPDATE</code> 語句的作用是改變表中原有行的字段值。這個語句的文法由3部分組成:UPDATE、SET 和 WHERE。UPDATE 子句用來指定要更新的表,SET 子句用來指明那些字段要被改變以及改變後的值,WHERE 子句用來指定要更新的行。文法:

從文法的角度來說,<code>UPDATE</code> 語句完全可以不帶條件,但實際需求中基本上都有條件。我曾維護過某醫院的 EMR 系統,有一天醫生回報說,他們科室所有患者的年齡顯示都一樣,我仔細檢查之後發現是因為修改患者資訊的 SQL 語句沒有 <code>WHERE</code> 條件。後來我問一個老員工相關代碼怎麼會那麼爛,他說當初這塊功能是讓一幫還沒畢業的研究所學生做的,可能他們不太懂 SQL 語句。我隻想說,這種低級錯誤即便是專科實習生也不應該犯,因為會犯這種錯誤至少能說明3個問題,首先這人根本沒搞明白需求或業務邏輯太差,需求是要改某一個患者的資訊;其次 SQL 基礎也很差;再次他可能太過自信或不負責任,釋出後的代碼中還有這麼嚴重的 Bug 說明他自己沒有認真測試過。當然了,那個公司也沒有測試人員,不過這是另一個層面的問題了。

盡管這個文法看起來很簡單,但初次接觸 Oracle 的開發人員極易寫錯,本人在工作中發現不少工齡超過 5 年的開發人員依然會用錯這個文法(沒寫最後那個可選的 <code>WHERE</code> 條件,結果導緻表中不符合查詢條件的資料全都被改成了 NULL),當我口頭指出這個問題的時候他們往往還不以為然,直到我把測試結果亮出來他們才恍然大悟。

我分析之是以會這樣主要有兩方面原因,一方面很多人會習慣性的認為,查詢語句的 <code>WHERE</code> 條件裡已經和要更新的目标表關聯過了,那更新的時候自然就會隻更新 <code>WHERE</code> 條件限定的這部分資料呀!其實這隻是一廂情願的想法,因為他們忽略了這個查詢其實是個行間查詢。另一方面,實際開發中必須用這個文法的情況很少,而低頻應用開發中偶爾用一次,即便有問題隻要當時沒發現,被坑的也是下一個人(我就是那個被坑了 N 多次的人)。是以會有很多工作多年的開發人員依然不太了解這個文法。

假如發現 <code>t_staff_salary</code> 表中研發一部的員工固定工資計算錯了,需要重新計算一下,示例:

如果把上述語句中最後一個 <code>WHERE</code> 條件去掉,再次執行就會把除研發一部以外的其它部門員工固定工資都改成 NULL。

一次更新多個字段,這個說法看上去沒有什麼稀奇之處,最普通的 <code>UPDATE</code> 語句的 <code>SET</code> 子句後面本身就可以寫多個字段。如果特殊點,其中一個字段的值來自另一張表的某個字段呢?上一節已經說過,寫個子查詢就能搞定。但如果再特殊一點,其中兩個甚至多個字段來自另一張甚至多張表呢?文法:

舉個例子,假如公司人員異動和調薪後,員工表 <code>t_staff</code> 中的資料已經更新,但 <code>t_staff_salary</code> 表中的部門和工資字段尚未同步更新,示例:

當然,有些朋友可能會想到下面這種更新方式,我在不知道上述文法時也經常用下面這種方式,示例:

這種方式一般也是行的,但畢竟要更新整張表,某些時候表中部分字段裡的資料其實是不能删的,那就不能用這種方式了。

<code>SELECT</code> 語句用來從一個或多個表中或者其它資料庫對象中提取資料。要想寫出符合文法規則的高效 SQL 語句,需要了解 SQL 語句是如何執行的。一個查詢語句在邏輯上的處理方式可能會與實際實體處理過程大相徑庭。Oracle 基于查詢成本的優化器(cost-based optimizer,CBO)用來産生實際的執行計劃。

示例一:

示例二:

WHERE 子句帶子查詢:如要查詢開發部所有員工的姓名和生日。示例:

FROM 子句帶子查詢:如要查詢所有部門的崗位工資之和。示例:

SELECT 子句帶子查詢:如要查詢所有部門的人數。示例:

查詢語句完整文法:

1&gt;、FROM 子句列出了所查詢資料的源對象。這個子句可以包含表、視圖、物化視圖、分區或子分區,或者你可以建立一個子查詢來生成子對象。如果使用了多個源對象,其邏輯處理階段也将會應用到每一個聯結類型以及謂語 ON。

2&gt;、WHERE 子句提供了一種方法,可以按照條件來限制查詢最終傳回結果集的行數。每個條件或者謂語都是以兩個值或表達式相比較的形式出現的。比較的結果要麼是比對(值為TRUE)要麼是不比對(值為FALSE)。如果比較的結果是 FALSE,那麼相應的行不會被包含在最終結果集中。WHERE 子句的目的是限制或者減少結果集。你所使用的限制條件越少,最終傳回結果集中包含的資料就會越多。你需要傳回的資料越多,執行查詢的時間也就越長。事實上,SQL 中邏輯比較的可能結果是 TRUE、FALSE 以及未知。當其中包含空值(NULL)的時候比較的結果就會是未知。空值與任何值比較或者用在表達式中都會得到空值,或者是未知。一個空值代表一個相應值的缺失,并且可能因為 SQL 語言中的不同部分對空值的處理不同而令人費解。

3&gt;、GROUP BY 子句将執行 FROM 和 WHERE 子句後得到的經過篩選後的結果集進行聚合。查詢出來的結果按照 GROUP BY 子句中列出的表達式進行分組,來為每一個分組得出一行彙總結果。你可以按照 FROM 子句中所列出對象的任意字段進行分組,即使你并不想在輸出結果中顯示該列。相反,SELECT 清單中任何非聚合字段都必須包括在 GROUP BY 表達式中。GROUP BY 子句中還可以包含兩個附加的運算:ROLLUP和 CUBE。ROLLUP 運算用來産生部分求和值,CUBE 運算用來求得互動分類值。

4&gt;、HAVING 子句将分組彙總後的查詢結果限定為隻有該子句中的條件為真的資料行。事實上,GROUP BY 子句和 HAVING 子句的位置是可以互換的。從本質上來說,HAVING 子句是在 GROUP BY 子句執行後用來篩選彙總值的第二個 WHERE 子句。

5&gt;、SELECT 清單列出查詢的傳回最終結果集中需要顯示那些列。這些列可以是資料表中的一個實際的列、一個表達式,或者甚至是一個 SELECT 語句的結果。當使用另外一個 SELECT 語句來産生結果中的一列的值的時候,這個查詢必須隻能傳回一行一列的值。這種類型的子查詢被稱為标量子查詢。盡管這可能是一個非常有用的文法,但需要牢記于心的是标量查詢在結果集中的每一行結果産生時都要執行一遍。在某些情況下可以進行優化以減少标量子查詢的重複執行,但更糟糕的場景是每一行都需要标量子查詢執行。你可以想象如果你的結果集中有幾千行甚至上百萬行資料的時候所需要付出的查詢代價!

6&gt;、DISTINCT 子句用于從結果集中删除重複項。DISTINCT 子句隻能與 SELECT 語句一起使用。

7&gt;、ORDER BY 子句用來對查詢最終傳回的結果集進行排序。當輸出結果需要排序的時候,Oracle 必須在其他所有子句都執行完之後按照指定的順序對最終結果集進行排序。需要排序的資料量大小是非常重要的。這裡所說的大小是指結果集中所包含的總位元組數。可以通過用行數乘以每一行的位元組數來估計資料集的大小。每行所包含的位元組數通過将選擇清單中包含的每一列的平均長度相加來确定。較小的排序會完全在記憶體中來實作,而較大的排序将不得不使用臨時磁盤空間來完成。如你可能推斷的那樣,在記憶體中完成排序比使用磁盤的排序要快。是以,當優化器估算排序資料的影響時,它必須要考慮排序資料集的大小,以此來調整如何能夠以有效的方法來獲得查詢的結果。一般來說,排序是查詢過程中開銷相當大的一個處理步驟,尤其是當傳回結果集很大的時候。

本文轉自帥氣的頭頭部落格51CTO部落格,原文連結http://blog.51cto.com/12902932/1926166如需轉載請自行聯系原作者

sshpp