-- 設置中文拼音排序為默認
ALTER SESSION SET NLS_SORT = SCHINESE_PINYIN_M;
ALTER SESSION SET NLS_COMP = LINGUISTIC;
-- 驗證
SELECT * FROM nls_session_parameters WHERE parameter IN ('NLS_SORT','NLS_COMP');
-- 後續無需 NLSSORT 函數
SELECT * FROM perexl ORDER BY danwei; -- 自動按拼音排序
NLS_COMP=LINGUISTIC 讓比較操作(ORDER BY、WHERE col > '值'、BETWEEN、DISTINCT、GROUP BY)全部遵循 NLS_SORT 規則。LOGON 觸發器自動應用。| 場景 | 優化手段 | 原理 |
|---|---|---|
| 大表中文排序 | 建立語言學索引 | CREATE INDEX idx_nls ON t(NLSSORT(col, 'NLS_SORT=SCHINESE_PINYIN_M')); 索引鍵值為排序權重,ORDER BY 可直接走索引全掃描避免排序操作 |
| 分頁查詢 | 中層 ROWNUM 截斷 + FIRST_ROWS Hint | 優化器選擇 Index Range Scan + Stopkey,僅訪問所需行數 |
| 混合排序 | 虛擬列 + 普通索引 | ALTER TABLE t ADD (col_sort VARCHAR2(200) GENERATED ALWAYS AS (NLSSORT(col, 'NLS_SORT=SCHINESE_PINYIN_M'))); CREATE INDEX idx_col_sort ON t(col_sort); |
-- 舊寫法 (三層 ROWNUM)
SELECT * FROM (
SELECT ROWNUM rn, t.* FROM (
SELECT * FROM personnel ORDER BY birth_date DESC
) t WHERE ROWNUM <= :offset + :limit
) WHERE rn > :offset;
-- 新寫法 (標準、可移植)
SELECT * FROM personnel
ORDER BY birth_date DESC
OFFSET :offset ROWS FETCH NEXT :limit ROWS ONLY;
OFFSET 0 ROWS 等同於無 OFFSET;FETCH FIRST n ROWS WITH TIES 返回並列值(12.2+)。-- 升序 NULL 最後(業務常見:未填寫排最後)
SELECT * FROM t ORDER BY col ASC NULLS LAST;
-- 降序 NULL 最後(業務常見:最高值優先,未填寫不干擾)
SELECT * FROM t ORDER BY col DESC NULLS LAST;
-- 避免舊寫法
-- ORDER BY NVL(col, '~') -- 依賴字符集排序規則,不可移植
-- ORDER BY DECODE(col, NULL, 1, 0), col -- 雙鍵排序,成本高
-- 需求:按相關度降序、銷量降序、價格升序、上架時間降序
-- 中文商品名拼音排序作為輔助維度
SELECT p.*, NLSSORT(p.name, 'NLS_SORT=SCHINESE_PINYIN_M') AS name_sort_key
FROM product p
WHERE p.status = 'ONLINE'
ORDER BY p.relevance_score DESC,
p.sales_count DESC,
p.price ASC,
p.created_at DESC,
name_sort_key
OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY;
Oracle 排序能力極強:會話級 NLS 設置簡化代碼、語言學索引消除排序操作、標準 OFFSET/FETCH 替代 ROWNUM 嵌套、NULLS FIRST/LAST 精確控制空值位置。建議團隊制定 SORTING_GUIDELINE:新表涉及中文排序必建語言學索引、分頁統一 OFFSET/FETCH、NULL 排序顯式聲明、遷移舊代碼納入技術債清理計劃。掌握這套體系,排序不再是性能瓶頸,而是業務邏輯的精確表達。