首页 > 解决方案 > 在 SQL Server 中,我可以手动实现 avg 函数吗?传递要使用的列名的问题

问题描述

在 SQL Server 中,我想创建一个类似于 avg 的函数,其中我接收列名作为参数并查询表以获取指定列的值。

也许这是不可能的,因为我看到我不能将 exec 用于连接查询字符串并执行它的函数之外的常见解决方案。

create function myAvg(@columnName varchar(255))
returns float
as
begin
    declare @queryStr varchar(255) = '(select AVG(cast(' + @columnName + ' as float)) from functionTest)';
    return execute( @queryStr);
end

我收到此错误:

标量值函数中的 RETURN 语句必须包含参数

使用游标的另一种解决方案:

create function myAvg (@columnName varchar(255))
returns float
as
begin
    declare @MyCursor as cursor;
    declare @value float;
    declare @total float = 0.0;
    declare @nElems int = 0;

    set @MyCursor = cursor for
                       select @columnName from functionTest;

    open @MyCursor;

    fetch next from @MyCursor into @value;

    while @@FETCH_STATUS = 0
    begin
        set @total = @total + @value;
        set @nElems = @nElems + 1;

        fetch next from @MyCursor into @value;
    end

    close @MyCursor;
    deallocate @MyCursor;

    return @total /@nElems
end

调用游标解决方案会引发此错误:

将数据类型 varchar 转换为 float 时出错

我猜函数不可能是动态列参数化的多功能。

有替代方案吗?

编辑:我知道我可以在存储过程中做到这一点,但我不能从查询中调用它。

谢谢

标签: sqlsql-server

解决方案


你不能做你想做的事。

首先,您不能用参数替换标识符(例如列名)。这根本不是参数的工作方式。它们只替换常量值。

其次,函数不能执行动态 SQL。您可以使用动态 SQL 解决第一个问题,但这在函数中是不允许的。

因此,您不能有一个将列名作为参数并返回平均值的函数。

相反,您可以在外部查询中使用窗口函数:

select . . . ,
       avg(column_name) over ()
from . . .;

注意:实际上有一种方法可以使用非常复杂的方法在 SQL Server 中重新调用查询,但这并不值得。


推荐阅读