CHARINDEX() / INSTR() / LOCATE() 函數 (SQL String Position Functions)

這些函數用來尋找子字串在字串中第一次出現的位置。不同資料庫有不同的函數名稱。

各資料庫語法

資料庫函數語法
SQL ServerCHARINDEX()CHARINDEX(substring, string, start)
MySQLLOCATE() / INSTR()LOCATE(substring, string, start)
INSTR(string, substring)
OracleINSTR()INSTR(string, substring, start, occurrence)
PostgreSQLPOSITION() / STRPOS()POSITION(substring IN string)
STRPOS(string, substring)
如果找不到子字串,所有函數都會回傳 0。

SQL Server - CHARINDEX()

-- 基本用法
SELECT CHARINDEX('World', 'Hello World');
-- 結果: 7

-- 指定搜尋起始位置
SELECT CHARINDEX('o', 'Hello World', 6);
-- 結果: 8(從第 6 個字元開始找,找到第二個 'o')

-- 找不到時回傳 0
SELECT CHARINDEX('xyz', 'Hello World');
-- 結果: 0

MySQL - LOCATE() / INSTR()

-- LOCATE 用法
SELECT LOCATE('World', 'Hello World');
-- 結果: 7

-- 指定搜尋起始位置
SELECT LOCATE('o', 'Hello World', 6);
-- 結果: 8

-- INSTR 用法(注意參數順序不同)
SELECT INSTR('Hello World', 'World');
-- 結果: 7

Oracle - INSTR()

-- 基本用法
SELECT INSTR('Hello World', 'World') FROM dual;
-- 結果: 7

-- 指定起始位置和出現次數
SELECT INSTR('Hello World', 'o', 1, 2) FROM dual;
-- 結果: 8(從第 1 個字元開始,找第 2 次出現的 'o')

-- 從後面往前找(負數起始位置)
SELECT INSTR('Hello World', 'o', -1, 1) FROM dual;
-- 結果: 8(從後面找第 1 次出現的 'o')

PostgreSQL - POSITION() / STRPOS()

-- POSITION 用法
SELECT POSITION('World' IN 'Hello World');
-- 結果: 7

-- STRPOS 用法
SELECT STRPOS('Hello World', 'World');
-- 結果: 7

實際應用範例

取得 email 的網域

-- SQL Server
SELECT 
    email,
    SUBSTRING(email, CHARINDEX('@', email) + 1, LEN(email)) AS domain
FROM users;

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

取得檔案名稱(不含路徑)

-- SQL Server:假設路徑使用 \ 分隔
SELECT 
    file_path,
    RIGHT(file_path, CHARINDEX('\', REVERSE(file_path)) - 1) AS filename
FROM files;

-- MySQL:假設路徑使用 / 分隔
SELECT 
    file_path,
    SUBSTRING_INDEX(file_path, '/', -1) AS filename
FROM files;

判斷字串是否包含特定內容

-- SQL Server
SELECT * FROM products
WHERE CHARINDEX('特價', description) > 0;

-- MySQL
SELECT * FROM products
WHERE LOCATE('特價', description) > 0;

-- 或使用 LIKE
SELECT * FROM products
WHERE description LIKE '%特價%';