SUBSTRING() / SUBSTR() 函數 (SQL Substring Function)

SUBSTRING() (或 SUBSTR()) 函數用於從字串中擷取指定位置、指定長度的子字串。這是 SQL 中最常用的字串處理函數之一。

各資料庫的函數名稱

資料庫函數名稱負數起始位置
MySQLSUBSTRING(), SUBSTR(), MID()✅ 支援
SQL ServerSUBSTRING()❌ 不支援
PostgreSQLSUBSTRING(), SUBSTR()❌ 不支援
OracleSUBSTR()✅ 支援
SQLiteSUBSTR()✅ 支援

語法 (Syntax)

-- 標準語法
SUBSTRING(string, start, length)
SUBSTRING(string FROM start FOR length)

-- MySQL / Oracle / SQLite
SUBSTR(string, start, length)
  • string:原始字串或欄位名稱
  • start:起始位置 (從 1 開始計算)
  • length:要擷取的字元數 (可選,省略則擷取到結尾)

基本範例

SELECT SUBSTRING('Hello World', 1, 5) AS Result;
-- 結果:'Hello'

SELECT SUBSTRING('Hello World', 7, 5) AS Result;
-- 結果:'World'

SELECT SUBSTRING('Hello World', 7) AS Result;
-- 結果:'World' (擷取到結尾)

從資料表欄位擷取

products 資料表:

product_codename
PRD-001-TW筆記型電腦
PRD-002-US智慧手機

擷取產品代碼前綴

SELECT SUBSTRING(product_code, 1, 3) AS prefix, name
FROM products;

結果:

prefixname
PRD筆記型電腦
PRD智慧手機

擷取流水號

SELECT SUBSTRING(product_code, 5, 3) AS serial_number
FROM products;

結果:

serial_number
001
002

負數起始位置 (MySQL / Oracle / SQLite)

負數表示從字串結尾開始計算位置:

-- MySQL / Oracle
SELECT SUBSTR(product_code, -2) AS country_code
FROM products;

結果:

country_code
TW
US

SQL Server 替代方案

SQL Server 不支援負數,需搭配 LEN() 函數:

-- SQL Server:取得最後 2 個字元
SELECT SUBSTRING(product_code, LEN(product_code) - 1, 2) AS country_code
FROM products;

搭配其他函數使用

1. 搭配 CHARINDEX / LOCATE / INSTR

擷取特定字元之後的內容:

-- SQL Server:取得 email 的網域
SELECT SUBSTRING(email, CHARINDEX('@', email) + 1, 100) AS domain
FROM users;

-- MySQL
SELECT SUBSTRING(email, LOCATE('@', email) + 1) AS domain
FROM users;

-- Oracle
SELECT SUBSTR(email, INSTR(email, '@') + 1) AS domain
FROM users;

2. 搭配 LENGTH / LEN

-- 取得除了最後 3 個字元以外的內容
-- MySQL
SELECT SUBSTRING(name, 1, LENGTH(name) - 3) AS trimmed
FROM products;

-- SQL Server
SELECT SUBSTRING(name, 1, LEN(name) - 3) AS trimmed
FROM products;

3. 搭配 CONCAT

-- 隱藏部分電話號碼
SELECT CONCAT(
    SUBSTRING(phone, 1, 4),
    '****',
    SUBSTRING(phone, 9)
) AS masked_phone
FROM customers;
-- 結果:0912****890

實際應用範例

1. 擷取日期部分

-- 從 'YYYY-MM-DD' 格式擷取年月日
SELECT
    SUBSTRING(date_string, 1, 4) AS Year,
    SUBSTRING(date_string, 6, 2) AS Month,
    SUBSTRING(date_string, 9, 2) AS Day
FROM orders;

2. 解析固定格式資料

-- 身分證字號解析 (台灣格式)
SELECT
    SUBSTRING(id_number, 1, 1) AS area_code,
    SUBSTRING(id_number, 2, 1) AS gender
FROM citizens;

3. 資料脫敏

-- 隱藏 email 中間部分
SELECT
    CONCAT(
        LEFT(email, 2),
        '***',
        SUBSTRING(email, LOCATE('@', email))
    ) AS masked_email
FROM users;
-- 結果:jo***@example.com

4. 產生縮寫

-- 取得名字的首字母
SELECT
    CONCAT(
        SUBSTRING(first_name, 1, 1), '.',
        SUBSTRING(last_name, 1, 1), '.'
    ) AS initials
FROM employees;
-- 結果:J.D.

注意事項

  1. 索引從 1 開始:SQL 的字串索引從 1 開始,不是 0。

  2. 超出範圍:如果 start + length 超出字串長度,只會返回實際存在的字元。

  3. NULL 處理:如果輸入字串為 NULL,結果也是 NULL。

相關主題