从多列返回值的 SQL 函数

Posted

技术标签:

【中文标题】从多列返回值的 SQL 函数【英文标题】:SQL Function to return value from multiple columns 【发布时间】:2020-07-13 10:03:42 【问题描述】:

我一直在开发一些存储过程,并且我一直在重复部分代码,这些代码基于其他一些列派生列。因此,我没有将这段代码从一个存储过程复制到另一个存储过程,而是考虑使用一个函数来获取输入列并生成输出列。

基本上,函数如下:

SELECT columnA, columnB, columnC, myFunction(columnA, columnB) as columnD FROM myTable

我们可以看到,这个函数将A列和B列作为输入,然后返回D列。

但是,根据一些研究,使用这样的 UDF(用户定义)函数时似乎存在一些性能问题。真的吗?处理这种情况的最佳方法是什么?

谢谢你们。

【问题讨论】:

信息如此之少,无法给出建议。这将取决于你真正需要什么。即使是最小的函数也会自然地产生一些性能问题(即:upper(myColumnA)),但值得对其进行优化以获得可能以纳秒为单位的时间是值得商榷的。如果您非常担心,请将其留给前端。 我最初在下面发布了我的答案,但没有明确说明用内联表值函数替换 scalar 用户定义函数(形式为 create function foo() returns int as ... 以提高性能。同样的论点仍然适用不过,所以我编辑了答案以使其更加明确。您可以使用内联 TVF 返回“标量”值,交叉应用它,而不会遇到在选择中使用真正的标量 UDF 的性能问题。跨度> 【参考方案1】:

标量函数和多语句表值用户定义函数可能会导致性能问题,因为它们会将基于集合的操作隐式转换为基于游标的操作。

但是,内联表值用户定义函数不会遇到此问题。他们很快。

不同之处在于您如何声明函数,以及代码在其中的样子。多语句函数按照它在锡上所说的做 - 它允许您拥有多个语句。像这样:

create function slow() returns @t table(j int, k int) as 
begin
    declare @j int = 1; -- statement 1
    declare @k int = 2; -- statement 2
    insert @t values (@j, @k); -- statement 3
    return; -- statement 4
end

内联表值函数不返回填充在函数内部的命名表。它返回一个选择语句:

create function quick() returns table as
return
(
    select j = 1, k = 2
);

内联表值函数可以“内联”到外部选择语句中,方式与视图大致相同。当然,区别在于 UDF 可以接受参数,而视图不能。

您还必须以不同的方式使用它们。使用交叉应用:

select       t.columnA, t.columnB, u.j, u.k
from         MyTable t
cross apply  quick(t.columnA, t.columnB) u

如果不清楚 - 是的,在您的情况下,您只想要一个“标量”值,但这只是一个返回单列和单行的表值函数。因此,与其编写标量函数,不如编写一个内联表值函数来完成相同的工作,然后cross apply 它。

【讨论】:

正是我想澄清的!非常感谢@allmhuran @Kelvin 另一个注意事项 - 在最近 (2019) 版本的 SQL 中,标量函数也可以内联 - 在某些条件下。不过,它现在看起来确实有点马车。 Documentation

以上是关于从多列返回值的 SQL 函数的主要内容,如果未能解决你的问题,请参考以下文章

从标量 SQL 函数返回两个值

JDBC 代码调用返回值的存储函数时出错

具有布尔返回值的 pl/sql 函数的 OracleType?

如何访问从sql函数获取的java中的多个返回值

检查后从表中返回值的 PL/SQL 函数

如何检索 sql server 内联表值函数的返回值的元数据?