本文側重於程式碼編寫過程中SQL語句的編寫規範問題,內容涉及書寫風格、效能優化、多資料適配等方面。
文件中用★標示的內容為必須遵守的條例,其餘的可視為建議。
工具/原料
資料庫sql
方法/步驟
書寫風格
1. SQL語句全部使用小寫。★
2. 引用字元時用單引號。如:update testable set idcol=’abcd’。 ★
3. 連線符或運算子or、in、and、=、<=、>=, +,- 等前後加上一個空格。
4. 嚴禁使用select * …….形式的語句,必須指出select的具體欄位,即select col1, col2,… from tablea where ….★
5. 嚴禁使用 insert into table values(?,?,?),必須指出具體要賦值的欄位,即 insert into tablea (col1, col2,…) values(?,?,…)★
6. SQL語句包含多表連線時,建議對每個表命名別名,對每個欄位的使用都要帶上表別名,即 select a.col1, a.col2, b.col3 from tablea a, tableb b where a.col4=b.col5
7. 避免隱含的型別轉換。例如在where子句中numeric 型和int型的列的比較或相加。★
8. 讀取是指通過JDBC讀到的資料格式,儲存是指儲存在VO中的資料格式,插入或者更新是指insert或者update語句中的資料格式。
a) 整型欄位:讀取時根據欄位設定儲存為Integer或者Long。
b) 數字型欄位:讀取為BigDecimal,並儲存為UFDouble,插入或者更新時為BigDecimal。
c) 字元型欄位:讀取為String,並儲存為String,插入或者更新為String。
d) 布林型欄位:讀取為String(‘Y’ OR ‘N’),並儲存為UFBoolean,插入或者更新時為String(‘Y’ OR ‘N’)。
e) 時間欄位:讀取為String,並儲存為UFDateTime,插入或者更新時的時間格式由中介軟體統一處理,有單獨需求的要申請後才能決定。
9. 在子查詢中前後必須加上括號, select col1, col2 from tablea where col3 in ( select col4 from tableb where col4>0)★
10. 避免在where使用'1=1','1=2'這種表示式作為部分條件,如 select col1, col2 from tablea where 1=1 and col1 >0。
11. 禁止使用檢視。★
效能優化
1. 儘量使用prepareStatement,利用預處理功能。
2. 在進行多條記錄的增加、修改、刪除時,建議使用批處理功能,批處理的次數以整個SQL語句不超過相應資料庫的SQL語句大小的限制為準。
3. 建議每條SQL 語句中in中的元素個數在500以下,如果個數超過時,應拆分為多條SQL語句。禁止使用xx in(‘’,’’….) or xx in(‘’,’’,’’)。★
4. 禁止使用or 超過 500,如 xx =’123’ or xx=’456’。 ★
5. 儘量不使用外連線。
6. 禁止使用not in 語句,建議用not exist。★
7. 禁止使用Union, 如果有業務需要,請拆分為兩個查詢。★
8. 禁止在一條SQL語句中使用3層以上的巢狀查詢,如果有,請考慮使用臨時表或中間結果集。★
9. 儘量避免在一條SQL語句中從>= 4個表中同時取數,對於僅是作為過濾條件關聯,但不涉及取數的表,不參與表個數計算;如果必須關聯4個或4個以上表,儘量採用子查詢的方式。
10. 儘量避免使用order by和group by排序操作,因為大量的排序操作影響系統性能。如必須使用排序操作,儘量建立在有索引的列上。
11. 對索引列的比較,儘量避免使用NOT 或 !=,可以考慮拆分為幾個條件。如col1 是索引列,條件col1 !=0 可以拆分為col1 >0 or col2 <0
12. 任何對列的操作都將導致表掃描,所以應儘量將資料庫函式、計算表示式寫在邏輯操作符右邊。
13. 在對char型別比較時,建議不要使用rtrim()函式,應該在程式中將不足的長度補齊。
14. 用多表連線代替EXISTS子句。
15. 如果有多表連線時,應該有主從之分,並儘量從一個表取數, 如select a.col1, a.col2 from a join b on a.col3=b.col4 where b.col5 = ‘a’。
16. 在where子句中,如果有多個過濾條件,應將索引列或過濾記錄數最多的條件應該放在前面。
17. 在使用Like時,建議Like 的一邊是字串,表列在一邊出現。
多資料庫的考慮
1. 字串連線必須用“ ”符號,不使用“+”。注意:在Oracle中一個null值與非null值連線,結果為非null值,在DB2和SqlServer中相反。使用isnull()對null轉換為’’ 。★
2. 萬用字元不能使用‘[a-c]%’這種形式,應寫成如:select col1, col2 from table_name where col1 like ‘[a]%’ OR col1 like ‘[b]%’ OR col1 like ‘[c]%’ 。★
3. 在Case when語句中只能出現 =、>=、<= 以及is null運算子,不能出現 <、>、<>、!=、以及is not null運算子。 否則在Oracle的decode函式無法表達。★
當必須使用 <, >, != ,is not null時,建議採用如下變通方法:
1)使用 !=時:例如 case when A!=B then e,
可改為 : case A=b then e1 else e (間接實現 A!=B)
2)使用 < 時:例如 case when A
可改為 : case A<=b then case A=B then e1 else e (間接實現 A
或 case A>=b then e1 else e (間接實現 A
3)使用 > 時:例如 case when A>B then e,
可改為 : case A>=b then case A=B then e1 else e (間接實現 A>B)
或 case A<=b then e1 else e (間接實現 A>B)
4)使用 is not null 時:例如 case when A is not null then e,
可改為: case A is null then e1 else e (間接實現 A is not null)
特別說明:當執行大資料量的操作時,sql Server 對 case when 的執行效率極低,甚至可能會宕機,因此希望大家儘量不要使用case when。
4. 左連線的寫法必須帶“outer”關鍵字。例如: select f1 from t1 left outer t2 on t1.f1 = t2.f1;而不是: select f1 from t1 left t2 on t1.f1 = t2.f1。★
5. 只能使用以下函式,如要使用新的函式必須申報,審批後才能使用。函式:coalesce, cast, len, left, replace, right, substring, lower, upper, ltrim, rtrim, abs, acos, asin, atan, cos, ceiling, exp, floor, log, power, round, sign,sin, square, sqrt, tan, count, max, min, sum, avg。★
6. substring函式中起始位置為1,表示從頭開始。★
7. 對於一些char/varchar的欄位的值,即使是0,1,2…等值,也必須表達為’0’,’1’,’2’… ★
8. 在cast和convert語句中只支援到字元型、日期型和數字型的轉換,且日期型只支援UFDate的格式,即’YYYY’-‘MM’-‘DD’ ★
9. 不能通過來percent n 限制查詢結果集的記錄數,也不能使用 select top n 的語句★
10. join 與on 必須嚴格匹配,不允許出現沒有on的join。★
11. join…on 後面慎用 or,如果用到,請把or的範圍用( )括起來
12. 不能使用select into 的格式★
13. 給某個字元型的列賦值時,如果其值含有單引號,例如:set col=’fsdf’fdsfdsf’sdf’…, 有兩種解決方案:
1) 使用轉意字元,將單引號寫成’’,即 set col=’fsdf’’fdsfdsf’’sdf’…
2) 通過set的方式賦值,即:set col= ? …
然後:setString(8,” ’fsdf’fdsfdsf’sdf’”)