注: 轉載NC技術部文檔, 並做部分修改
一、概述
本手冊側重於代碼編寫過程中SQL語句的編寫規範問題,內容涉及書寫風格、性能優化、多數據適配等方面。
文檔中用★標示的內容爲必須遵守的條例,其餘的可視爲建議。
二、書寫風格
- SQL語句全部使用小寫。★
- 引用字符時用單引號。如:update testable set idcol=’abcd’。 ★
- 連接符或運算符or、in、and、=、<=、>=, +,- 等前後加上一個空格。
- 嚴禁使用select * …….形式的語句,必須指出select的具體字段,即select col1, col2,… from tablea where ….★
- 嚴禁使用 insert into table values(?,?,?),必須指出具體要賦值的字段,即 insert into tablea (col1, col2,…) values(?,?,…)★
- SQL語句包含多表連接時,建議對每個表命名別名,對每個字段的使用都要帶上表別名,即 select a.col1, a.col2, b.col3 from tablea a, tableb b where a.col4=b.col5
- 避免隱含的類型轉換。例如在where子句中numeric 型和int型的列的比較或相加。★
- 讀取是指通過JDBC讀到的數據格式,保存是指保存在VO中的數據格式,插入或者更新是指insert或者update語句中的數據格式。
- 整型字段:讀取時根據字段設置保存爲Integer或者Long。
- 數字型字段:讀取爲BigDecimal,並保存爲UFDouble,插入或者更新時爲BigDecimal。
- 字符型字段:讀取爲String,並保存爲String,插入或者更新爲String。
- 布爾型字段:讀取爲String(‘Y’ OR ‘N’),並保存爲UFBoolean,插入或者更新時爲String(‘Y’ OR ‘N’)。
- 時間字段:讀取爲String,並保存爲UFDateTime,插入或者更新時的時間格式由中間件統一處理,有單獨需求的要申請後才能決定。
- 在子查詢中前後必須加上括號, select col1, col2 from tablea where col3 in ( select col4 from tableb where col4>0)★
- 避免在where使用'1=1','1=2'這種表達式作爲部分條件,如 select col1, col2 from tablea where 1=1 and col1 >0。
- 禁止使用視圖。★
三、性能優化
- 儘量使用prepareStatement,利用預處理功能。
- 在進行多條記錄的增加、修改、刪除時,建議使用批處理功能,批處理的次數以整個SQL語句不超過相應數據庫的SQL語句大小的限制爲準。
- 建議每條SQL 語句中in中的元素個數在500以下,如果個數超過時,應拆分爲多條SQL語句。禁止使用xx in(‘’,’’….) or xx in(‘’,’’,’’)。★
- 禁止使用or 超過 500,如 xx =’123’ or xx=’456’。 ★
- 儘量不使用外連接。
- 禁止使用not in 語句,建議用not exists。★
- 禁止使用Union, 如果有業務需要,請拆分爲兩個查詢。★
- 禁止在一條SQL語句中使用3層以上的嵌套查詢,如果有,請考慮使用臨時表或中間結果集。★
- 儘量避免在一條SQL語句中從>= 4個表中同時取數,對於僅是作爲過濾條件關聯,但不涉及取數的表,不參與表個數計算;如果必須關聯4個或4個以上表,儘量採用子查詢的方式。
- 儘量避免使用order by和group by排序操作,因爲大量的排序操作影響系統性能。如必須使用排序操作,儘量建立在有索引的列上。
- 對索引列的比較,儘量避免使用NOT 或 !=,可以考慮拆分爲幾個條件。如col1 是索引列,條件col1 !=0 可以拆分爲col1 >0 or col2 <0
- 任何對列的操作都將導致表掃描,所以應儘量將數據庫函數、計算表達式寫在邏輯操作符右邊。
- 在對char類型比較時,建議不要使用rtrim()函數,應該在程序中將不足的長度補齊。
- 用多表連接代替EXISTS子句。
- 如果有多表連接時,應該有主從之分,並儘量從一個表取數, 如select a.col1, a.col2 from a join b on a.col3=b.col4 where b.col5 = ‘a’。
- 在where子句中,如果有多個過濾條件,應將索引列或過濾記錄數最多的條件應該放在前面。
- 在使用Like時,建議Like 的一邊是字符串,表列在一邊出現。
四、多數據庫的考慮
- 字符串連接必須用“||”符號,不使用“+”。注意:在Oracle中一個null值與非null值連接,結果爲非null值,在DB2和SqlServer中相反。使用isnull()對null轉換爲’’ 。★
- 通配符不能使用‘[a-c]%’這種形式,應寫成如:select col1, col2 from table_name where col1 like ‘[a]%’ OR col1 like ‘[b]%’ OR col1 like ‘[c]%’ 。★
- 在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<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)
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。
- 左連接的寫法必須帶“outer”關鍵字。例如: select f1 from t1 left outer t2 on t1.f1 = t2.f1;而不是: select f1 from t1 left t2 on t1.f1 = t2.f1。★
- 只能使用以下函數,如要使用新的函數必須申報,審批後才能使用。函數: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。★
- substring函數中起始位置爲1,表示從頭開始。★
- 對於一些char/varchar的字段的值,即使是0,1,2…等值,也必須表達爲’0’,’1’,’2’… ★
- 在cast和convert語句中只支持到字符型、日期型和數字型的轉換,且日期型只支持UFDate的格式,即’YYYY’-‘MM’-‘DD’ ★
- 不能通過來percent n 限制查詢結果集的記錄數,也不能使用 select top n 的語句★
- join 與on 必須嚴格匹配,不允許出現沒有on的join。★
- join…on 後面慎用 or,如果用到,請把or的範圍用( )括起來
- 不能使用select into 的格式★
- 給某個字符型的列賦值時,如果其值含有單引號,例如:set col=’fsdf’fdsfdsf’sdf’…, 有兩種解決方案:
- 使用轉意字符,將單引號寫成’’,即 set col=’fsdf’’fdsfdsf’’sdf’…
- 通過set的方式賦值,即:set col= ? …
然後:setString(8,” ’fsdf’fdsfdsf’sdf’”)