如何在SQL Server中创建接受IN子句输入参数的表值用户定义函数?

我正在try 编写这个非常简单的函数:

CREATE FUNCTION dbo.MyTableValuedFunction (@myList VARCHAR(MAX))
RETURNS @myTable TABLE (
    [ID] INT,
    [Name] VARCHAR(MAX)
)
AS
BEGIN
    INSERT INTO @myTable
    SELECT ID, Name FROM MyTable WHERE ID IN (@myList)
    RETURN
END

一种流行的生成式人工智能建议构建一个SQL字符串并使用‘exec’

CREATE FUNCTION dbo.MyTableValuedFunction (@myList VARCHAR(MAX))
RETURNS @myTable TABLE (
    [ID] INT,
    [Name] VARCHAR(MAX)
)
AS
BEGIN
    DECLARE @sql NVARCHAR(MAX)
    SET @sql = 'SELECT ID, Name FROM MyTable WHERE ID IN (' + @myList + ')'

    INSERT INTO @myTable
    EXEC sp_executesql @sql
    RETURN
END

但当我try 运行它时,收到以下错误:在函数中无效使用副作用运算符‘INSERT EXEC’.

在表值用户定义函数中,有没有办法使用带有列表的IN子句作为输入参数?

推荐答案

IN需要标量值的list或返回单列的SELECT语句.您不能将变量传递给它,然后期望SQL Server将其视为元组.IN (@ScalarVariable)等同于= @ScalarVariable,而IN (@TableVariable)将生成有关未定义标量变量的错误.

取而代之的是用STRING_SPLIT来拆分变量.另外,切换到内联表值函数;它们的性能比多行表值函数要好得多(正如您前面所写的):

CREATE FUNCTION dbo.MyTableValuedFunction (@MyList VARCHAR(MAX))
RETURNS table AS
RETURN SELECT ID,
              Name
       FROM dbo.MyTable
       WHERE ID IN (SELECT value
                    FROM STRING_SPLIT(@MyList,',')); --Comma (,) is assumed delimiter
GO
--Alternatively, use an `EXISTS`:
CREATE FUNCTION dbo.MyTableValuedFunction (@MyList VARCHAR(MAX))
RETURNS table AS
RETURN SELECT ID,
              Name
       FROM dbo.MyTable MT
       WHERE EXISTS (SELECT 1
                     FROM STRING_SPLIT(@MyList,',') SS --Comma (,) is assumed delimiter
                     WHERE SS.value = MT.ID); 

如果一个ID只能在您的变量中出现一次(@MyList),那么您也可以使用JOIN:

CREATE FUNCTION dbo.MyTableValuedFunction (@MyList VARCHAR(MAX))
RETURNS table AS
RETURN SELECT ID,
              Name
       FROM dbo.MyTable MT
            JOIN STRING_SPLIT(@MyList,',') SS ON MT.ID = SS.value;

Sql相关问答推荐

如何查询未命名对象的SON数组

如何实现一个广泛的多级自连接PostgreSQL查询?

有没有办法在每次计算每一行的数据时更新2个值?

每组显示一行(表1中的分组值),表2中的不同列表用逗号分隔

编写一个SQL查询来返回收视率较高的类型,并取这些收视率的平均值,我该如何做呢?

在SQL中返回缺省值,即使查询不返回任何结果

使用列表作为参数进行 Select ,如果为空,则在PostgreSQL中不使用参数进行 Select

Oracle中的时间戳

如何简化此PostgreSQL查询以计算平均值?

使用多个WITH子查询的替代方法

如何使用聚合连接两个表

从另一个没有公共键的表中获取值来加入

Postgresql - 如何根据阈值计算累积和

给定 3 个键列,从一个表中 Select 另一表中不存在的所有数据

清理 XML 数据

BigQuery导航函数计算ID

PostgreSQL中如何提取以特定字符开头的字符串中的所有单词?

Set vs let vs 在snowflake中声明变量

忽略与给定列匹配的行的 LAG 函数

在 PostgreSQL 中,如何将数组中的每个元素用作另一个表中的键?