SQL是否存在非表函数类型、可返回多列的自定义函数?
对应实现方案
PostgreSQL 实现
PostgreSQL原生支持返回复合类型的函数,可以直接满足你要的单函数调用返回多列的需求,无额外计算或关联开销:
- 先定义返回用的复合类型
CREATE TYPE split_name_result AS (first text, last text);
- 定义返回该复合类型的函数
CREATE OR REPLACE FUNCTION split_name(full_name text, delimiter text) RETURNS split_name_result AS $$ SELECT split_part(full_name, delimiter, 1) AS first, split_part(full_name, delimiter, 2) AS last; $$ LANGUAGE sql STABLE;
- 直接调用展开多列即可
SELECT id, (split_name(name, ' ')).* FROM your_table;
PostgreSQL 12及以上版本的优化器会自动识别同参数的函数调用,只会执行一次,不会产生重复计算开销,标记为STABLE/IMMUTABLE的函数还可以参与执行计划优化,性能和原生内置函数一致,完全适配十亿级数据量场景。
SQL Server 实现
SQL Server没有原生的多输出标量函数,但可以通过内联表值函数(iTVF)实现同等低开销的效果:
注意不要使用多语句表值函数,内联表值函数会被查询优化器直接展开到主查询执行计划中,不会产生实际的关联开销,性能和直接写逻辑没有差异。
- 定义内联表值函数
CREATE OR ALTER FUNCTION split_name(@full_name NVARCHAR(1000), @delimiter NCHAR(1)) RETURNS TABLE AS RETURN ( SELECT LEFT(@full_name, CHARINDEX(@delimiter, @full_name) - 1) AS first, STUFF(@full_name, 1, CHARINDEX(@delimiter, @full_name), '') AS last )
- 用CROSS APPLY调用即可
SELECT t.id, s.first, s.last FROM your_table t CROSS APPLY split_name(t.name, ' ') s
这种写法的执行计划和你直接在SELECT里写拆分逻辑完全一致,不会有额外的JOIN开销,可支撑十亿级数据量的计算需求。
内容的提问来源于stack exchange,提问作者David542
相关产品推荐
相关产品推荐

