HAVING針對GROUP BY分組結果過濾,條件中僅允許:常數、聚合函數、GROUP BY欄位。不可直接引用非分組欄位。
Oracle專有(+)語法實現外部連接,左連接t1.col = t2.col(+)、右連接t1.col(+) = t2.col。
-- 低效:NOT IN無法使用索引,NULL值導致語意陷阱
SELECT a.empno FROM emp a
WHERE a.empno NOT IN (SELECT empno FROM emp1 WHERE job = 'SALE');
-- 高效:可使用索引,邏輯清晰
SELECT a.empno
FROM emp a, emp1 b
WHERE a.empno = b.empno(+)
AND b.empno IS NULL
AND b.job = 'SALE';
實測效能提升: 大表場景下常達10x-100x速度提升。
DELETE FROM table_name a
WHERE ROWID < (
SELECT MAX(ROWID)
FROM table_name
WHERE col1 = a.col1 AND col2 = a.col2 AND col3 = a.col3 ...);
保留每組重複資料中ROWID最大的一筆。
標準方案全表掃描+相關子查詢,效能不可接受。進階策略:
CREATE TABLE new_table AS
SELECT DISTINCT * FROM old_table; -- 或用ROW_NUMBER()保留特定行
DROP TABLE old_table;
RENAME new_table TO old_table;
-- 重建索引、約束、授權
大事務觸發ORA-01555: snapshot too old,原因是隨機分配的回滾段過小。
SET TRANSACTION USE ROLLBACK SEGMENT roll_abc;
DELETE FROM large_table WHERE ...;
COMMIT; -- 自動釋放指定回滾段
前置條件: 預先建立足夠大小的回滾段(建議≥最大表50%)。Oracle 9i+建議改用UNDO TABLESPACE自動管理。
查詢返回行數超過總行數20%時,全表掃描通常優於索引掃描。強制使用索引反而降低效能。
ALTER INDEX ... REBUILDTRUNCATE TABLE同步清除表與索引碎片(不可回滾)匯入時視圖依賴基礎表,順序錯誤導致建立失敗。
-- 階段1:僅匯入結構(無資料)
IMP userid=jfcl/hfjf@ora1 FILE=empdata.dmp ROWS=N
-- 階段2:匯入結構+資料,忽略已存在物件
IMP userid=jfcl/hfjf@ora1 FILE=empdata.dmp FULL=Y BUFFER=64000 COMMIT=Y IGNORE=Y
關鍵參數: IGNORE=Y允許物件已存在時繼續匯入資料;COMMIT=Y每64KB提交一次,防止長事務。
| 法則 | 核心口訣 | 適用場景 |
|---|---|---|
| HAVING | 只聚合、只分組、只常數 | 群組過濾 |
| 外部連接 | (+)代替NOT IN,速度飛升 | 反向關聯查詢 |
| 去重 | 小表ROWID,大表CTAS | 重複資料清理 |
| 大事務 | 指定大回滾段,防ORA-01555 | 批量刪除/更新 |
| 索引 | 選擇性<20%才用,碎片定期重建 | 查詢調優 |
| 重建 | 先結構後資料,IGNORE=Y保平安 | 匯入遷移 |
將這六大法則整合入團隊開發規範與DBA操作手冊,定期Code Review檢查合規性。特別注意:Oracle 12c+已棄用(+)語法,新系統應全面遷移至ANSI SQL標準LEFT/RIGHT/FULL OUTER JOIN語法。