用正規表達式匹配模式

已完成

小提示

有關更多詳細信息,請參閱 文本和圖像 選項卡!

資料庫中的文字處理通常需要超出操作員 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)函式或應用層處理來處理複雜的正則表達式運算。

欲了解更多關於正則表達式函數的資訊,請參見 正則表達式。