DuckDB 文本函数(字符函数)用于字符类型数据的处理,例如字符串拼接、大小写转换、子串查找和替换、编码转换、路径解析、哈希计算、相似度测量等功能。
《DuckDB 教程》使用的示例表和数据:
字符串长度
字符串的长度可以按照两种方式进行计算:字符数量和字节数量。在多字节编码中,一个字符可能占用多个字节。
length(string) 函数用于计算字符串的字符数量,strlen(string) 函数用于计算字符串的字节数量。例如:
sql
SELECT length('数据库'), strlen('数据库');
┌──────────────────┬──────────────────┐
│ length('数据库') │ strlen('数据库') │
│ int64 │ int64 │
├──────────────────┼──────────────────┤
│ 3 │ 9 │
└──────────────────┴──────────────────┘
字符串"数据库"包含 3 个字符,在 UTF-8 编码中占用 9 个字节。
另外,len(string)、char_length(string)、character_length(string) 函数都等价于 length(string) 函数。
大小写转换
lower(string)、lcase(string) 函数将字符串转换为小写,upper(string)、ucase(string) 函数将字符串转换为大写。例如:
sql
SELECT lower('DuckDB'), upper('DuckDB');
┌─────────────────┬─────────────────┐
│ lower('DuckDB') │ upper('DuckDB') │
│ varchar │ varchar │
├─────────────────┼─────────────────┤
│ duckdb │ DUCKDB │
└─────────────────┴─────────────────┘
字符串拼接
连接运算符(||)可以将两个字符串拼接到一起,concat(s1, s2, ...) 函数将两个或者多个字符串连接到一起。例如:
sql
SELECT 'Duck' || 'DB', 'Duck' || NULL, concat('Duck', NULL, 'DB');
┌──────────────────┬──────────────────┬────────────────────────────┐
│ ('Duck' || 'DB') │ ('Duck' || NULL) │ concat('Duck', NULL, 'DB') │
│ varchar │ int32 │ varchar │
├──────────────────┼──────────────────┼────────────────────────────┤
│ DuckDB │ NULL │ DuckDB │
└──────────────────┴──────────────────┴────────────────────────────┘
如果参数中出现空值(NULL),连接运算符(||)将会返回 NULL,concat(s1, s2, ...) 函数则会忽略空值。
如果想要使用特定的分隔符连接多个字符串,可以使用 concat_ws(separator, s1, s2 , ... )函数。例如:
sql
SELECT concat_ws('*', 'S', 'Q', 'L');
┌───────────────────────────────┐
│ concat_ws('*', 'S', 'Q', 'L') │
│ varchar │
├───────────────────────────────┤
│ S*Q*L │
└───────────────────────────────┘
获取子串
DuckDB 支持通过下标索引获取子串,例如:
sql
SELECT 'DuckDB'[1], 'DuckDB'[1:4], 'DuckDB'[-1];
┌─────────────┬───────────────┬──────────────┐
│ 'DuckDB'[1] │ 'DuckDB'[1:4] │ 'DuckDB'[-1] │
│ varchar │ varchar │ varchar │
├─────────────┼───────────────┼──────────────┤
│ D │ Duck │ B │
└─────────────┴───────────────┴──────────────┘
索引位置从 1 开始,负数代表从字符串右侧开始计算索引位置。
DuckDB 支持将字符串当作字符组成的数值或者列表进行处理,因此也可以使用 array_extract(string, index)、array_slice(list, begin, end)、list_slice(list, begin, end) 函数获取子串。
substr(string, start, length)、substring(string, start, length) 函数可以返回字符串 string 中从位置 start 开始的 length 个字符。例如:
sql
SELECT substr('DuckDB', 1, 4), substr('DuckDB', -2, 2);
┌────────────────────────┬─────────────────────────┐
│ substr('DuckDB', 1, 4) │ substr('DuckDB', -2, 2) │
│ varchar │ varchar │
├────────────────────────┼─────────────────────────┤
│ Duck │ DB │
└────────────────────────┴─────────────────────────┘
另外,left(string, count)、right(string, count) 函数分别用于返回字符串开头和结尾的 count 个字符。例如:
sql
SELECT left('DuckDB', 4), right('DuckDB', 2);
┌─────────────────────┬──────────────────────┐
│ "left"('DuckDB', 4) │ "right"('DuckDB', 2) │
│ varchar │ varchar │
├─────────────────────┼──────────────────────┤
│ Duck │ DB │
└─────────────────────┴──────────────────────┘
查找与替换
instr(string, search_string) 函数查找并返回字符串 string 中第一次出现 search_string 的位置,如果没有找到子串则会返回 0。例如:
sql
SELECT instr('DuckDB', 'DB'), instr('DuckDB', 'd');
┌───────────────────────┬──────────────────────┐
│ instr('DuckDB', 'DB') │ instr('DuckDB', 'd') │
│ int64 │ int64 │
├───────────────────────┼──────────────────────┤
│ 5 │ 0 │
└───────────────────────┴──────────────────────┘
另外,position(string, search_string)、strpos(string, search_string) 函数等价于 instr(string, search_string)。
contains(string, search_string) 函数判断字符串 string 是否包含子串 search_string,starts_with(string, search_string) 函数判断字符串 string 是否以子串 search_string 开头,ends_with(string, search_string) 函数判断字符串 string 是否以子串 search_string 结束。例如:
sql
SELECT contains('DuckDB', 'u'), starts_with('DuckDB', 'Duck'), ends_with('DuckDB', 'Duck');
┌─────────────────────────┬───────────────────────────────┬─────────────────────────────┐
│ contains('DuckDB', 'u') │ starts_with('DuckDB', 'Duck') │ ends_with('DuckDB', 'Duck') │
│ boolean │ boolean │ boolean │
├─────────────────────────┼───────────────────────────────┼─────────────────────────────┤
│ true │ true │ false │
└─────────────────────────┴───────────────────────────────┴─────────────────────────────┘
另外,prefix(string, search_string)、string ^@ search_string 等价于 starts_with(string, search_string) 函数,suffix(string, search_string) 等价于 ends_with(string, search_string) 函数。
replace(string, source, target) 函数将字符串 string 中的子串source 替换为 target。例如:
sql
SELECT replace('DuckDB', 'D', '*');
┌───────────────────────────────┐
│ "replace"('DuckDB', 'D', '*') │
│ varchar │
├───────────────────────────────┤
│ *uck*B │
└───────────────────────────────┘
translate(string, from, to) 函数将字符串 string 中属于 from 集合的字符,逐个替换为 to 集合中对应位置的字符。如果 from 长度大于 to,那么在 to 中没有对应值的字符将被删除。
例如:
sql
SELECT translate('DuckDB', 'ABCcD', '12334');
┌───────────────────────────────────────┐
│ translate('DuckDB', 'ABCcD', '12334') │
│ varchar │
├───────────────────────────────────────┤
│ 4u3k42 │
└───────────────────────────────────────┘
截断与填充
trim(string, characters) 函数删除字符串 string 开头和结尾处出现在字符集合 characters 中的字符,默认删除空格。例如:
sql
SELECT trim('DuckDB', 'DB');
┌─────────────────────────────┐
│ main."trim"('DuckDB', 'DB') │
│ varchar │
├─────────────────────────────┤
│ uck │
└─────────────────────────────┘
另外,ltrim(string, characters) 函数表示从字符串左侧进行截断,rtrim(string, characters) 函数表示从字符串右侧进行截断,这两个函数是 trim 函数的简化版。
lpad(string, count, characters) 函数使用 characters 中的字符从左侧对字符串 string 进行填充,直到填充后的长度到达 count;如果 string 原始长度超过了 count,从右侧开始截断。
rpad(string, count, characters) 函数使用 characters 中的字符从右侧对字符串 string 进行填充,直到填充后的长度到达 count;如果 string 原始长度超过了 count,同样从右侧开始截断。
例如:
sql
SELECT lpad('DuckDB', 10, '*-'), rpad('DuckDB', 4, '*-');
┌──────────────────────────┬─────────────────────────┐
│ lpad('DuckDB', 10, '*-') │ rpad('DuckDB', 4, '*-') │
│ varchar │ varchar │
├──────────────────────────┼─────────────────────────┤
│ *-*-DuckDB │ Duck │
└──────────────────────────┴─────────────────────────┘
另外,repeat(string, count) 函数用于返回字符串 string 重复 count 次之后的结果。例如:
sql
SELECT repeat('A', 3) as tripple;
┌─────────┐
│ tripple │
│ varchar │
├─────────┤
│ AAA │
└─────────┘
分割字符串
string_split(string, separator) 函数基于分隔符 separator 对字符串 string 进行拆分,返回一个字符串数组。例如:
sql
SELECT string_split('张三,李四,王五', ',');
┌─────────────────────────────────────┐
│ string_split('张三,李四,王五', ',') │
│ varchar[] │
├─────────────────────────────────────┤
│ [张三, 李四, 王五] │
└─────────────────────────────────────┘
另外,split()、str_split()、string_to_array() 函数都等价于 string_split() 函数。
split_part(string, separator, index) 函数基于分隔符 separator 对字符串 string 进行拆分,返回第 index 个子串。例如:
sql
SELECT split_part('张三,李四,王五', ',', 2);
┌──────────────────────────────────────┐
│ split_part('张三,李四,王五', ',', 2) │
│ varchar │
├──────────────────────────────────────┤
│ 李四 │
└──────────────────────────────────────┘
字符串反转
reverse(string) 函数用于反转字符串,例如:
sql
SELECT reverse('DuckDB');
┌───────────────────┐
│ reverse('DuckDB') │
│ varchar │
├───────────────────┤
│ BDkcuD │
└───────────────────┘
编码转换
to_binary(string)、bin(string) 函数用于将字符串转换为二进制形式,from_binary(value)、unbin(value) 函数用于将二进制字符串转换为 blob。例如:
sql
SELECT bin('a'), unbin('01100001');
┌──────────┬───────────────────┐
│ bin('a') │ unbin('01100001') │
│ varchar │ blob │
├──────────┼───────────────────┤
│ 01100001 │ a │
└──────────┴───────────────────┘
to_base64(blob)、base64(blob) 函数用于将 blob 数据转换为 base64 编码字符串,from_base64(string) 函数用于将 base64 编码字符串转换为 blob。例如:
sql
SELECT to_base64('a'), from_base64('YQ==');
┌────────────────┬─────────────────────┐
│ to_base64('a') │ from_base64('YQ==') │
│ varchar │ blob │
├────────────────┼─────────────────────┤
│ YQ== │ a │
└────────────────┴─────────────────────┘
to_hex(string)、hex(string) 函数用于将字符串转换为十六进制形式,from_hex(value)、unhex(value) 函数用于将十六进制字符串转换为 blob。例如:
sql
SELECT hex('a'), unhex('61');
┌──────────┬─────────────┐
│ hex('a') │ unhex('61') │
│ varchar │ blob │
├──────────┼─────────────┤
│ 61 │ a │
└──────────┴─────────────┘
url_encode(string) 函数用于将 URL 字符串转换为百分号编码格式,url_decode(string) 函数用于将百分号编码格式的 URL 字符串进行解码。例如:
sql
SELECT url_encode('https://duckdb.org/why_duckdb#portable');
┌──────────────────────────────────────────────────────┐
│ url_encode('https://duckdb.org/why_duckdb#portable') │
│ varchar │
├──────────────────────────────────────────────────────┤
│ https%3A%2F%2Fduckdb.org%2Fwhy_duckdb%23portable │
└──────────────────────────────────────────────────────┘
SELECT url_decode('https%3A%2F%2Fduckdb.org%2Fwhy_duckdb%23portable');
┌────────────────────────────────────────────────────────────────┐
│ url_decode('https%3A%2F%2Fduckdb.org%2Fwhy_duckdb%23portable') │
│ varchar │
├────────────────────────────────────────────────────────────────┤
│ https://duckdb.org/why_duckdb#portable │
└────────────────────────────────────────────────────────────────┘
哈希计算
DuckDB 提供多种哈希计算函数,包括非加密哈希函数 hash(value, ...),加密哈希函数 md5(string)、sha1(value)、sha256(value) 等。例如:
sql
SELECT hash('DuckDB'), md5('DuckDB');
┌─────────────────────┬──────────────────────────────────┐
│ hash('DuckDB') │ md5('DuckDB') │
│ uint64 │ varchar │
├─────────────────────┼──────────────────────────────────┤
│ 9220287917019107744 │ 8a47bfd3da416301bc8a0dee487c2e7c │
└─────────────────────┴──────────────────────────────────┘
路径解析
DuckDB 提供了一组非常实用的文件路径解析函数,特别适合日志分析、数据湖、文件管理等场景。
其中,parse_filename(string, trim_extension, separator) 函数用于获取路径中的文件名;trim_extension 设置为 true 表示返回结果不包含文件后缀,默认值为 false;separator 指定路径中的分隔符,取值包括 system、both_slash (默认)forward_slash(斜线)以及 backslash(反斜线)。例如:
sql
SELECT parse_filename('/usr/tmp/duck.db', 'forward_slash');
┌─────────────────────────────────────────────────────┐
│ parse_filename('/usr/tmp/duck.db', 'forward_slash') │
│ varchar │
├─────────────────────────────────────────────────────┤
│ duck.db │
└─────────────────────────────────────────────────────┘
parse_dirname(path, separator) 函数用于获取顶层目录名;separator 指定路径中的分隔符,取值包括 system、both_slash (默认)、forward_slash(斜线)以及 backslash(反斜线)。例如:
sql
SELECT parse_dirname('/usr/tmp/duck.db');
┌───────────────────────────────────┐
│ parse_dirname('/usr/tmp/duck.db') │
│ varchar │
├───────────────────────────────────┤
│ / │
└───────────────────────────────────┘
parse_dirpath(path, separator) 函数用于获取目录路径(不包含文件名);separator 指定路径中的分隔符,取值包括 system、both_slash (默认)forward_slash(斜线)以及 backslash(反斜线)。例如:
sql
SELECT parse_dirpath('/usr/tmp/duck.db');
┌───────────────────────────────────┐
│ parse_dirpath('/usr/tmp/duck.db') │
│ varchar │
├───────────────────────────────────┤
│ /usr/tmp │
└───────────────────────────────────┘
parse_path(path, separator) 函数用于返回将路径(包括文件名)拆分后组成的数组;trim_extension 设置为 true 表示返回结果不包含文件后缀,默认值为 false;separator 指定路径中的分隔符,取值包括 system、both_slash (默认)forward_slash(斜线)以及 backslash(反斜线)。例如:
sql
SELECT parse_path('/usr/tmp/duck.db');
┌────────────────────────────────┐
│ parse_path('/usr/tmp/duck.db') │
│ varchar[] │
├────────────────────────────────┤
│ [/, usr, tmp, duck.db] │
└────────────────────────────────┘
文本进度条
bar(x, min, max, width) 是一个特殊的文本函数,它会根据 x 位于 (min, max) 中的位置生成一个最大宽度 width 为文本进度条,width 默认为 80。例如:
sql
SELECT emp_name, salary, bar(salary, 0, 30000, 20)
FROM employee
ORDER BY salary DESC
LIMIT 5;
┌──────────┬──────────────┬───────────────────────────┐
│ emp_name │ salary │ bar(salary, 0, 30000, 20) │
│ varchar │ decimal(8,2) │ varchar │
├──────────┼──────────────┼───────────────────────────┤
│ 刘备 │ 30000.00 │ ████████████████████ │
│ 关羽 │ 26000.00 │ █████████████████▎ │
│ 张飞 │ 24000.00 │ ████████████████ │
│ 诸葛亮 │ 24000.00 │ ████████████████ │
│ 赵云 │ 15000.00 │ ██████████ │
└──────────┴──────────────┴───────────────────────────┘