SQL程式設計徹底研究
書號:F8216
定價:680 元
邱芳信 譯
我要線上購買 | |
本期書摘:SQL 程式的應用 ─「LIKE 與 SIMI LAR 述語」
本文摘錄自旗標 F8216「SQL程式設計徹底研究」一書
LIKE (相似) 述語會對字串進行 "樣版比對" (pattern
-matching) 測試, 語法如下:
================================================
::=
[NOT] LIKE
[ESCAPE ]
::=
::=
::=
================================================
M NOT LIKE P 運算式相當於 NOT (M LIKE P), 符合
SQL 的語法常規。 字串可接受 2 種萬用字
元:'%' 與 '_'。'_' 字元代表一個任意字元, '%'
字元則代表任意子字串 (長度還可為 0)。請注意並無
方法可以表示 0 或 1 個任意字元, 這在許多文字搜
尋語言裡並不是這樣, 但在 SQL 下則可能會導致問題
發生 (或非常複雜的述語)。
在 裡的其他字元則代表該字元本身。這表
示 SQL 的樣版分大小寫 (case-sensitive), 但許多
廠商則允許您在資料庫系統層級上啟動或關閉大小寫
辨識選項。
其中 【 逸離字元】是 SQL-92 標
準的一部份, 但尚未全面普及。逸離字元用在 上, 以表示逸離字元後面緊接的是一般文字字元,
而非萬用字元。這表示逸離字元後可能會緊接著逸離字
元、一個 '_'、或一個 '%'。C 程式設計師習於這種應
用慣例, 該語言將 '\' 定義為逸離字元, 因此這個字
元也是 SQL 程式設計師對於逸離字元的好選擇。
樣版技巧
'_' 字元的測試速度比 '%' 字元快多了。理由很明顯
:透過樣版比對字串的解析器在跳到下一個字元前只須
一個步驟就可以完成一個 '_' 字元的比對工作, 要完
成一個 '%' 字元的比對工作則須進行某些 "往下繼續
搜索比對" 的解析比對動作。萬用字元可以插至樣版的
開頭或中間。因此 'B%K' 會符合 'BOOK'、'BLOCK'、
與 'BK', 但不符合 'BLOCKS'。
解析器會掃描各字元, 判斷該字元為萬用字元還是一般
文字字元。
以上述的 'BLOCKS' 為例, 開頭的 'B' 會進行一般文字
字元的明確比對, 接著解析器繼續往下找到 'L'、'O'、
與 'C', 由於這些字元沒出現在樣版字串上, 所以都算
在萬用字元內, 接著找到 'K', 但還不能確定這段萬用
字元比對是否符合, 直到讀入最後字元後, 發現最後字
元為 'S', 於是比對宣告失敗。
舉例來說, 已知某欄位宣告為 7 個字元長, 要以 LIKE
述語找尋 "Mac" 起頭的名字, 您通常可以寫出如下的
敘述:
================================================
SELECT *
FROM People
WHERE (name LIKE 'Mac%');
================================================
但改寫成下面這樣的執行速度更快:
================================================
SELECT *
FROM People
WHERE (name LIKE 'Mac_ ')
OR (name LIKE 'Mac__ ')
OR (name LIKE 'Mac___ ')
OR (name LIKE 'Mac____');
================================================
末端空白也是字元, 因此也會進行明確比對。
在樣版前面放上 '%' 非常耗時。舉例來說, 您可能試
圖透過查詢找出所有以 "son" 結尾的名字:
================================================
SELECT *
FROM People
WHERE (name LIKE '%son');
================================================
在大多數 SQL 實作產品下改使用 '_' 將造成執行速度
上明顯的差異, 因為大多數的 SQL 產品都由左至右進
行解析:
================================================
SELECT *
FROM People
WHERE (name LIKE '_son ')
OR (name LIKE '__son ')
OR (name LIKE '___son ')
OR (name LIKE '____son');
================================================
請記住 '_' 會比對掉一個字元, 但 '%' 並不需要。因
此下列查詢敘述:
================================================
SELECT *
FROM People
WHERE (name LIKE 'John_%');
================================================
與下列查詢敘述:
================================================
SELECT *
FROM People
WHERE (name LIKE 'John%');
================================================
兩者間有著些微的不同。兩者都符合 'Johnson' 與 '
Johns', 但第 1 個敘述不接受 'John'。這也是在 SQL
底下進行 "一或多字元" 樣版比對的方法。
記住, 要建立 與 , 可以透
過連接運算子、SUBSTRING()、與其他字串函數。舉例
來說, 讓我們透過查詢敘述找出 "姓" (lastname) 中
有 "名" (firstname) 的姓名:
================================================
SELECT *
FROM People
WHERE (lastname LIKE '%' || firstname || '%');
================================================
這個查詢敘述會找出 'John Johnson'、'Anders Ander
sen'、與 'Bob McBoblin'... 之類的姓名。這個查詢
敘述也會執行得非常慢。然而由於系統分大小寫, 所以
它不會找出 'Jon Anjon' 之類的姓名, 所以您可能會
想將敘述改寫如下:
================================================
SELECT *
FROM People
WHERE (UPPER (lastname) LIKE '%' || UPPER(first
name) || '%');
================================================
NULL 值與空字串的結果
如您所預見, 述語遇上 NULL 就會傳回 UNKNOWN 結果
。NULL 可以是逸離字元、樣版、或比對值。若 M 與 P
都是長度為 0 的字元字串, M LIKE P 預設為 TRUE。
若其中一個 (或兩者) 的長度大於 0, 則您可以依據常
規測試該述語。
LIKE 並非 "相等"
有一點很重要, 而這點也常為人所忽略 -- 在 SQL 內
兩字串可能相等但並不 LIKE (相似)。在進行相等比
較前, 系統會先在兩字串中較短字串的末端附加空白
字元, 然後再進行逐字元比對。因此 'Smith' 與 'Sm
ith ' (末端有 3 個空白) 是相等的。但 LIKE 不會
補空白, 所以 'Smith' LIKE 'Smith ' 的測試結果
為 FALSE, 因為其中一個字串末端的空白字元沒有辦法
對比到另外一個字串上去。
要避開這類問題有個訣竅, 那就是使用 TRIM() 函數來
移除字串上不想要的空白,
--- 本篇完
|