用正規表達式匹配模式
小提示
有關更多詳細信息,請參閱 文本和圖像 選項卡!
資料庫中的文字處理通常需要超出操作員 LIKE 能力範圍的模式匹配。 正則表達式提供標準化的語法,用於複雜的模式匹配、驗證與文字轉換。 SQL Server 2025 與 Microsoft Fabric 中的 SQL 資料庫透過新的 T-SQL 函式支援正則表達式。
考慮 LIKE 可能無法處理的情境:當有人驗證電子郵件地址格式是否正確、擷取格式多變的電話號碼、尋找遵循特定命名規則的產品代碼,或偵測連續重複字元等模式。 該 LIKE 運算子僅支援簡單的萬用字元(% 對任意字元, _ 單一字元),無法表達這些複雜模式。
正則表達式透過豐富的模式語言解決了這些限制。 使用正則表達式,你可以匹配特定字元範圍、要求精確重複次數、使用交替(匹配這個或那個),並擷取匹配後的部分文字進行擷取或替換。 一旦你學會正則表達式語法,就能應用於多種程式語言和工具——你為 SQL Server 寫的模式在 Python、JavaScript 和命令列工具中運作類似。
了解正規表達式的基礎
正則表達式(regex)使用一種模式語法來描述文字模式。 在你學習 SQL Server 的函式之前,讓我們先複習這些常見的正則表達式元件:
| 樣式 | Description | 範例比賽 |
|---|---|---|
. |
任何單一字元 |
a.c匹配「ABC」、「A1C」 |
* |
前一個字元出現零次或多次 |
ab*c匹配「AC」、「ABC」、「ABC」 |
+ |
一個或多個前述項目 |
ab+c匹配「ABC」、「ABC」但不匹配「AC」 |
? |
前一個字元出現零次或一次 |
colou?r 匹配 「顏色」, 「顏色」 |
^ |
字串起始 |
^Hello配對以「Hello」開頭的字串 |
$ |
字串的結尾 |
world$匹配字串以「world」結尾 |
[abc] |
字元類 |
[aeiou] 匹配任何母音字母 |
[^abc] |
否定類別 |
[^0-9] 匹配非數字字元 |
\d |
數字(0-9) |
\d{3} 匹配三位數 |
\w |
Word 字元 |
\w+ 匹配字元字母 |
{n} |
恰好 n 次出現 |
\d{4} 完全匹配四位數 |
{n,m} |
介於 n 到 m 次出現之間 |
\d{2,4} 匹配 2 到 4 位數 |
備註
SQL Server 的正則表達式函式使用 ECMAScript 標準正則表達式語法。 此腳本與 JavaScript 及許多其他程式語言相同的語法,使模式能跨技術移植。
使用 REGEXP_LIKE 匹配模式
REGEXP_LIKE 若字串符合正則表達式模式,則回傳 1(真),若不符合則回傳 0(假)。 在子句中使用此函式 WHERE ,根據複雜模式篩選資料列:
-- Find customers with email addresses from specific domains
SELECT CustomerID, FirstName, LastName, EmailAddress
FROM SalesLT.Customer
WHERE REGEXP_LIKE(EmailAddress, '@(contoso|adventure-works|fabrikam)\.com$') = 1;
驗證資料格式:
-- Find valid US phone numbers (various formats)
SELECT CustomerID, Phone
FROM SalesLT.Customer
WHERE REGEXP_LIKE(Phone, '^\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}$') = 1;
-- Validate product numbers match expected format (XX-XXXX)
SELECT ProductID, ProductNumber, Name
FROM SalesLT.Product
WHERE REGEXP_LIKE(ProductNumber, '^[A-Z]{2}-[A-Z0-9]{4,6}$') = 1;
使用「旗標」參數來進行不區分大小寫的匹配:
-- 'i' flag enables case-insensitive matching
SELECT Name
FROM SalesLT.Product
WHERE REGEXP_LIKE(Name, 'frame', 'i') = 1;
小提示
用於 REGEXP_LIKE 驗證與過濾。 當你只需要知道某個模式是否存在時,這比提取子字串更有效率。
將文字替換為 REGEXP_REPLACE
REGEXP_REPLACE 找出所有模式的出現,並將它們替換為指定的字串。 此功能對資料清理與標準化非常有用:
-- Standardize phone numbers to (XXX) XXX-XXXX format
SELECT
Phone AS OriginalPhone,
REGEXP_REPLACE(
REGEXP_REPLACE(Phone, '[^\d]', ''), -- First remove all non-digits
'^(\d{3})(\d{3})(\d{4})$',
'($1) $2-$3'
) AS StandardizedPhone
FROM SalesLT.Customer
WHERE Phone IS NOT NULL;
以下範例展示了如何使用帶有回溯參照的捕捉群組:
-- Swap first and last name
DECLARE @name NVARCHAR(100) = 'Smith, John';
SELECT REGEXP_REPLACE(@name, '^(\w+),\s*(\w+)$', '$2 $1') AS SwappedName;
-- Returns: John Smith
-- Mask credit card numbers (show last 4 digits only)
DECLARE @card NVARCHAR(20) = '4532-1234-5678-9012';
SELECT REGEXP_REPLACE(@card, '\d(?=[\d-]{4,})', '*') AS MaskedCard;
-- Returns: ****-****-****-9012
以下範例示範如何清理與正規化資料:
-- Remove extra whitespace (multiple spaces to single space)
SELECT REGEXP_REPLACE(Description, '\s+', ' ') AS CleanedDescription
FROM Products;
-- Remove HTML tags
SELECT REGEXP_REPLACE(HtmlContent, '<[^>]+>', '') AS PlainText
FROM WebPages;
用 REGEXP_SUBSTR 提取子串
REGEXP_SUBSTR 提取字串中與正則表達式模式相符的部分。 利用它從非結構化文字中擷取特定資料元素,如以下範例:
-- Extract domain from email address
SELECT
EmailAddress,
REGEXP_SUBSTR(EmailAddress, '@(.+)$', 1, 1, '', 1) AS Domain
FROM SalesLT.Customer
WHERE EmailAddress IS NOT NULL;
-- Extract the first number from a string
SELECT
ProductNumber,
REGEXP_SUBSTR(ProductNumber, '\d+') AS FirstNumber
FROM SalesLT.Product;
以下範例展示了函數簽名,其中包含出現群與捕獲群的參數:
REGEXP_SUBSTR(source, pattern, start_position, occurrence, flags, capture_group)
使用REGEXP_INSTR尋找圖案位置
REGEXP_INSTR 回傳字串中模式匹配的起始位置。 若未找到匹配,則回傳 0,如下範例:
-- Find position of first digit in product number
SELECT
ProductNumber,
REGEXP_INSTR(ProductNumber, '\d') AS FirstDigitPosition
FROM SalesLT.Product;
-- Find position of email domain
SELECT
EmailAddress,
REGEXP_INSTR(EmailAddress, '@') AS AtPosition,
REGEXP_INSTR(EmailAddress, '\.[a-z]+$', 1, 1, 0, 'i') AS TldPosition
FROM SalesLT.Customer
WHERE EmailAddress IS NOT NULL;
使用 REGEXP_COUNT 計算模式出現次數
REGEXP_COUNT 回傳一個模式在字串中出現的次數。 以下範例說明其使用:
-- Count words in a description
SELECT
Name,
REGEXP_COUNT(Name, '\w+') AS WordCount
FROM SalesLT.Product;
-- Count vowels in product names
SELECT
Name,
REGEXP_COUNT(Name, '[aeiou]', 1, 'i') AS VowelCount
FROM SalesLT.Product;
-- Find products with multiple numbers in their name
SELECT Name
FROM SalesLT.Product
WHERE REGEXP_COUNT(Name, '\d+') > 1;
使用REGEXP_SPLIT_TO_TABLE分割字串
REGEXP_SPLIT_TO_TABLE 是一個表值函數,根據分隔符模式將字串分割成數列:
-- Split comma-separated values
DECLARE @tags NVARCHAR(200) = 'sql,database,azure,analytics';
SELECT value AS Tag
FROM REGEXP_SPLIT_TO_TABLE(@tags, ',');
-- Split on multiple delimiters (comma, semicolon, or pipe)
DECLARE @data NVARCHAR(200) = 'apple,banana;cherry|date';
SELECT value AS Fruit
FROM REGEXP_SPLIT_TO_TABLE(@data, '[,;|]');
你可以將REGEXP_SPLIT_TO_TABLE與其他查詢使用CROSS APPLY結合在一起。
-- Assuming Products table has a Tags column with comma-separated values
SELECT
p.ProductID,
p.Name,
t.value AS Tag
FROM Products AS p
CROSS APPLY REGEXP_SPLIT_TO_TABLE(p.Tags, ',\s*') AS t;
回傳所有與REGEXP_MATCHES符合的結果
REGEXP_MATCHES 是一個表格值函數,會將所有模式匹配作為獨立的行回傳:
-- Find all numbers in a string
DECLARE @text NVARCHAR(200) = 'Order 12345 contains 3 items totaling $99.99';
SELECT match_value, match_id
FROM REGEXP_MATCHES(@text, '\d+\.?\d*');
-- Returns: 12345, 3, 99.99
這很重要
正則表達式函式可在 SQL Server 2025 中使用,SQL 資料庫則可在 Microsoft Fabric 中使用。 對於較早期的 SQL Server 版本,建議使用通用語言執行時(CLR)函式或應用層處理來處理複雜的正則表達式運算。
欲了解更多關於正則表達式函數的資訊,請參見 正則表達式。