Menu

SQLite 字符串函数:SUBSTR、REPLACE、INSTR 等

SQLite 中实用的字符串函数:拼接、SUBSTR、INSTR、REPLACE、TRIM,以及在查询中清洗和改造文本的常用写法。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

真实的查询大多在和字符串打交道

数字很好处理,字符串才是让查询变乱的地方:名字带着多余的空格,邮箱大小写混杂,ID 用连字符拼在一起,自由文本字段差一点点就能匹配上。SQLite 自带一小组专注的字符串函数,大部分这类问题不用写应用代码就能解决。

这一页介绍你最先会用到的几类:拼接、截取、查找、替换、去空白和格式化。

拼接用 ||,不是 CONCAT

SQLite 没有 CONCAT 函数,字符串用 || 运算符连接:

数字和其他类型会自动转换成文本。需要注意的是:只要有一个操作数是 NULL,整个表达式就变成 NULL。这是标准 SQL 的行为,但常常让人意外:

如果不想让一个缺失值毁掉整个字符串,就用 COALESCE(col, '') 或 COALESCE(col, 'default') 包住可能为空的列。

LENGTH、UPPER、LOWER

这三个你会一直用到:

对文本来说,LENGTH 返回的是字符数,不是字节数。如果你确实需要字节数(不常见,但分析存储占用时有用),用 OCTET_LENGTH。UPPER 和 LOWER 默认只转换 ASCII 字母,带重音的字符会原样保留,除非你加载了 ICU 扩展。

SUBSTR:截取字符串

SUBSTR(text, start, length) 从字符串中取出一段。下标从 1 开始,1 是第一个字符,而不是 0:

有几点要记住:

  • 第三个参数可以省略。不传时,会取从 start 到末尾的全部内容。
  • start 为负数时,从字符串末尾倒数。
  • 如果 start 超出了末尾,得到的是空字符串,不会报错。

SUBSTRING 是它的同义写法,方便习惯了其他数据库的你。

INSTR:查找子字符串

INSTR(haystack, needle) 返回 needle 在 haystack 中第一次出现的位置(从 1 开始),找不到时返回 0:

最后那个表达式是 SQLite 里取“@ 之前所有内容”的惯用写法:先用 INSTR 找到分隔符,再用 SUBSTR 截取。这个组合你会经常写。注意,INSTR 在没有匹配时返回 0,所以截取之前要先检查,把 0 传给 SUBSTR 会悄无声息地得到奇怪的结果。

REPLACE:把一个子字符串换成另一个

REPLACE(text, old, new) 会把每一处 old 都替换成 new:

它区分大小写,也不支持正则,只匹配字面上的子字符串。更复杂的转换可以把多个 REPLACE 嵌套起来,但嵌套超过两三层时,就该把这部分工作交给应用代码了。

TRIM、LTRIM、RTRIM

用户输入的数据两端常常带着空白。TRIM 会把它去掉:

默认去掉的是空格。传入第二个参数可以指定要去掉哪些字符:第二个参数里的每个字符都被当作“要删除的字符集合”中的一员,而不是一个字面子字符串。所以 TRIM('xxxhelloxx', 'x') 得到 'hello'。

printf:格式化数字和字符串

需要格式化的字符串时,比如固定小数位、补零的数字、十六进制输出,用 printf(也可以写成 format):

格式说明符遵循 C 语言的约定,也就是 %d、%s、%f、%x,用 0 或空格补位等等。这比用 || 加一堆 CAST 拼字符串清晰得多。

LIKE 和 GLOB:模式匹配

两个运算符,两套完全不同的规则。

LIKE 使用 SQL 经典的通配符,% 匹配任意长度的字符序列,_ 匹配单个字符,并且对 ASCII 字母不区分大小写:

GLOB 使用 Unix shell 通配符,* 匹配任意序列,? 匹配单个字符,[abc] 表示字符类,并且区分大小写:

两者怎么选:做“以……开头”“包含”“以……结尾”这类贴近日常的匹配时用 LIKE;需要区分大小写或用到字符类时用 GLOB。两者都能使用索引,但前提是模式锚定在开头('foo%',而不是 '%foo'),以通配符开头会导致全表扫描。

拆分字符串:没有 SPLIT

SQLite 没有 SPLIT_STRING 函数。两种实用的替代方案:

如果要按分隔符拆成多行,最简洁的做法是对 JSON 数组使用 json_each,或者用递归 CTE。这两种方法后面的章节都会讲到,现在只要知道:“把每个单词都拆出来”在 SQLite 里不是一行就能搞定的。

完整示例:清洗姓名

把前面的内容组合起来。假设有一张 users 表,显示名很乱:多余的空白、大小写混杂,还有你想去掉的 "Dr. " 或 "Mr. " 这类称谓:

这个表达式要从里往外读:去掉两端空白,转成小写,删掉称谓,再 trim 一次,以防删掉称谓后开头留下空格。每一步都只是一个函数,复杂度来自层层叠加。当嵌套超过三四层时,就说明该用生成列(见“高级特性”一章),或者在导入数据时就完成清洗。

要点回顾

  • 用 || 拼接;NULL 会污染整个结果,所以要用 COALESCE。
  • SUBSTR 和 INSTR 搭配,能满足大多数“查找并截取”的需求。
  • REPLACE 会替换字面子字符串的每一处出现。
  • TRIM 系列函数可以接收自定义字符集合,不只是空白。
  • 格式化输出用 printf。
  • LIKE 用于不区分大小写的 SQL 通配符匹配,GLOB 用于区分大小写的 shell 风格模式。

下一步:数值函数

字符串处理完了,自然该轮到数字:四舍五入、绝对值、除法的怪癖,以及 SQLite 在较新版本中加入的数学函数。这些就是下一页的内容。

常见问题

SQLite 中如何拼接字符串?

用 || 运算符,而不是 CONCAT。SQLite 默认没有 CONCAT 函数,'Hello, ' || name 会把两个字符串连成一个。只要有一个操作数是 NULL,整个结果就是 NULL,所以如果你不想要这种结果,就用 COALESCE 包住可能为空的列。

SQLite 中如何截取子字符串?

用 SUBSTR(text, start, length),也可以写成 SUBSTRING。下标从 1 开始:SUBSTR('hello', 1, 3) 返回 'hel'。start 为负数时从末尾倒数,length 参数可以省略,省略时一直取到字符串末尾。

SQLite 有 SPLIT_STRING 函数吗?

没有,SQLite 没有内置的分割函数。大多数情况下,你可以组合 INSTR 和 SUBSTR 取出想要的部分,或者用递归 CTE 按分隔符拆分。如果经常需要拆分,对 JSON 数组使用 json_each 函数通常比自己写一个拆分逻辑更简洁。

SQLite 中 LIKE 和 GLOB 有什么区别?

LIKE 默认对 ASCII 字母不区分大小写,用 % 和 _ 作通配符。GLOB 区分大小写,使用 Unix shell 通配符(*、?、[abc])。需要区分大小写或用到字符类时选 GLOB;想要更熟悉的 SQL 风格匹配时选 LIKE。

Coddy 编程语言插图

和 Coddy 一起学编程

开始