今天要講的是撰寫SQL的好習慣,要先破除一些迷思,不是寫越多行越厲害,也不是越精簡越好,而是要確定三個關鍵:效能
、防呆
& 可讀性
。效能差
的code會隨著時間資料量變多而出現 timeout
問題,防呆
沒寫好導致code可執行但輸出卻是錯誤的(見下方圖1),可讀性
則是為了後續維護著想,註解不寫好、縮排亂七八糟都是下任sponsor閱讀時的痛苦。
EXCEPTION
處理異常,提高程序的穩定性EXPLAIN PLAN
逐行分析 SQL 執行耗費的時間 (下一篇介紹)資料型別
(日期時間用 DATE
或 TIMESTAMP
類型,非 VARCHAR
)COMMIT
和 ROLLBACK
控制事務,確保資料一致性NVL
、upper
、lower
、to_number
& rownum
作為防呆 -- 1. NVL 防呆數字
-- oracle
select NVL(AVG(score), 0)
from student
;
-- mysql
select ifnull(AVG(score), 0)
from student
;
-- 2. upper/lower防呆大小寫導致的比對錯誤
-- oracle
select *
from student
where upper(subject) = 'ENG'
;
-- mysql
select *
from student
where upper(subject) = "ENG"
-- 3. to_number防止數字比對錯誤(可參考*圖1)
-- oracle
select *
from student
order by to_number(score) desc
;
-- mysql
select *
from student
order by cast(score as number) desc
【圖1】防止數字比對錯誤
-- 4. rownum 防止子查詢太多資料 ERROR(可參考*圖2)
-- oracle
CREATE TABLE Student (
ID NUMBER PRIMARY KEY,
name VARCHAR2(15) NOT NULL,
Subject VARCHAR2(10) NOT NULL,
Score VARCHAR2(10) NOT NULL
);
INSERT INTO Student VALUES (1, 'Amy', 'Eng', 74);
INSERT INTO Student VALUES (2, 'Peter', 'Eng', 50);
CREATE TABLE PHONE (
name VARCHAR2(15) NOT NULL,
phone VARCHAR2(15) NOT NULL
);
INSERT INTO PHONE VALUES ('Amy', '0956258956');
INSERT INTO PHONE VALUES ('Peter', '0974859359');
INSERT INTO PHONE VALUES ('Amy', '02-5689574');
select s.*
, (select phone from Phone P where P.name = S.name and rownum<=1) phone
from student s
where s.subject = 'Eng'
;
-- mysql 無 rownum 隱形欄位
【圖2】防止子查詢太多資料 ERROR