SQL如何截取字符串的一部分?SUBSTRING函數(shù)的實操技巧

SUBSTRING函數(shù)不報錯的關鍵是適配數(shù)據(jù)庫的起始位置(MySQL/PG/SQL Server從1開始)并避免越界;測試用SELECT SUBSTRING('hello',1,2)驗證,結合POSITION/CHARINDEX動態(tài)計算位置,NULL值需COALESCE處理。

SQL里SUBSTRING函數(shù)怎么寫才不報錯?

不同數(shù)據(jù)庫對 SUBSTRING 的參數(shù)順序和起始位置約定不一致,直接照搬語法大概率出錯。MySQL 和 PostgreSQL 從 1 開始計數(shù),SQL Server 也是;但 SQLite 默認從 1 開始,而某些舊版本或兼容模式下可能表現(xiàn)異常。

實操建議:

  • 永遠顯式寫出參數(shù)名(如果數(shù)據(jù)庫支持),比如 PostgreSQL 可用 SUBSTRING(str FROM start FOR length) 提高可讀性
  • 在不確定環(huán)境時,先用 SELECT SUBSTRING('hello', 1, 2) 測試——結果是 he 才說明從 1 開始;如果是空或報錯,可能需要改成 0
  • 避免硬寫負數(shù)起始位,除非明確知道當前數(shù)據(jù)庫是否支持(PostgreSQL 支持,MySQL 不支持)

截取文件擴展名、域名、手機號中間四位的典型場景

真實業(yè)務中不是單純“取第3到第5個字符”,而是有語義的切分,得結合 POSITION、CHARINDEXLENGTH 動態(tài)算位置。

例如提取郵箱域名部分(user@domain.comdomain.com):

SELECT SUBSTRING(email FROM POSITION(``'@' IN email) + 1)

再比如取文件擴展名(假設路徑為 /path/to/file.txt):

SELECT SUBSTRING(filename FROM LENGTH(filename) - POSITION(``'.' IN REVERSE(filename)) + 2)

注意點:

  • MySQL 沒有 REVERSE 配合 POSITION 的簡潔寫法,得用 LOCATE('.', REVERSE(filename)) 替代
  • SQL Server 要用 CHARINDEX 而非 POSITION,且索引從 1 開始,邏輯一致但函數(shù)名不同
  • 如果字段可能為 NULL 或不含分隔符,SUBSTRING 會返回 NULL 或空字符串,別漏掉 COALESCECASE 處理

SUBSTRING配合WHERE做模糊前綴匹配比LIKE更高效?

不是更高效,反而通常更慢——因為 SUBSTRING(col, 1, 3) = 'abc' 無法走索引,而 col LIKE 'abc%' 在有索引時可以范圍掃描。

只有當必須匹配非前綴位置時(比如“第4~6位是xyz”),才被迫用 SUBSTRING,此時性能天然受限。

能用 LIKE 就別繞路,尤其注意:

  • SUBSTRING(col, 1, n) 等價于 LEFT(col, n)(多數(shù)數(shù)據(jù)庫支持),但 LEFT 更直觀,且部分引擎對它有額外優(yōu)化
  • 想查“以某串結尾”,用 RIGHT(col, n)col LIKE '%abc',別用 SUBSTRING(col, LENGTH(col)-n+1),易錯且難維護
  • 正則雖靈活(如 PostgreSQL 的 REGEXP_REPLACE),但跨庫兼容性差,簡單截取別過早引入

為什么SUBSTRING('abc', 5, 1)不報錯卻返回空?

omegafw.sepis.com.cn
rolexfw.sepis.com.cn
patekfw.sepis.com.cn
omega1.gmcwatch.cn
rolex1.gmcwatch.cn
patek1.gmcwatch.cn
omega1.swatchsh.com
rolex1.swatchsh.com
patek1.swatchsh.com
omegawx.paydyj.com
rolexwx.paydyj.com
patekwx.paydyj.com
omegawx.watchku.com
rolexwx.watchku.com
patekwx.watchku.com
這是設計行為,不是 bug。所有主流 SQL 引擎都定義:當起始位置超出字符串長度,或截取長度為負/零,SUBSTRING 安靜返回空字符串(''),而不是拋異常。

這意味著你不能靠報錯來發(fā)現(xiàn)邏輯錯誤,得主動校驗:

  • CASE WHEN LENGTH(str) 顯式兜底
  • 在 ETL 或應用層做數(shù)據(jù)探查時,記得檢查目標字段的長度分布,避免大量 SUBSTRING 返回空卻誤以為成功
  • PostgreSQL 還提供 SUBSTRING(str FROM pattern) 的正則變體,但它在 pattern 不匹配時也返回 NULL,行為不統(tǒng)一,混用時格外小心

最麻煩的從來不是函數(shù)怎么寫,而是不同數(shù)據(jù)庫對“位置從幾開始”“越界怎么處理”“空輸入怎么響應”的隱式約定——寫之前,先 SELECT SUBSTRING('test', 0, 1), SUBSTRING('test', 1, 1), SUBSTRING('test', 5, 1) 三連查,比看文檔快。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容