SQL Server 2017表值函数:如何实现多值参数筛选?
解决SQL Server多值筛选表值函数的问题
我来帮你搞定这个问题——在SQL Server 2017里实现支持日期范围+多产品筛选的表值函数,你之前的写法不对,核心原因是不能直接在函数参数中定义表结构,必须先创建用户定义表类型(UDTT),下面是具体的实现步骤:
1. 先创建用户定义表类型
SQL Server要求表值参数必须基于预先定义的用户定义表类型,我们先创建一个用于接收产品列表的类型:
CREATE TYPE ProductListType AS TABLE (Product varchar(10));
这个类型定义了一个只有Product列的表结构,后续函数的表参数就会基于它来声明。
2. 创建正确的表值函数
接下来用这个UDTT作为参数创建函数,注意表值参数必须标记为READONLY(函数内部无法修改表值参数的数据):
CREATE FUNCTION func_2 ( @StartDate date, @EndDate date, @Product ProductListType READONLY -- 使用UDTT并标记为只读 ) RETURNS TABLE AS RETURN ( SELECT Date, Product, Quantity FROM Table_Name WHERE Date BETWEEN @StartDate AND @EndDate -- 关联表值参数进行筛选 AND Table_Name.Product IN (SELECT Product FROM @Product) );
3. 正确调用函数
SQL Server不支持直接像('value_1','value_2')这样传入值列表作为表参数,你需要先声明符合ProductListType类型的表变量,填充数据后再传入函数:
-- 声明表变量并填充产品值 DECLARE @ProductParam ProductListType; INSERT INTO @ProductParam (Product) VALUES ('value_1'), ('value_2'), ('value_3'); -- 调用函数获取结果 SELECT * FROM func_2('20190101', '20191231', @ProductParam);
如果你的SQL Server版本是2016及以上,还可以用更简洁的方式初始化表变量:
DECLARE @ProductParam ProductListType = (VALUES ('value_1'), ('value_2'), ('value_3')); SELECT * FROM func_2('20190101', '20191231', @ProductParam);
备选方案:用字符串拆分实现类似的简化调用
如果希望调用时不用预先声明表变量,你可以改用逗号分隔的字符串参数,结合STRING_SPLIT函数(SQL Server 2016+支持)来拆分筛选值:
CREATE FUNCTION func_2_Alternative ( @StartDate date, @EndDate date, @ProductList varchar(1000) -- 逗号分隔的产品字符串 ) RETURNS TABLE AS RETURN ( SELECT Date, Product, Quantity FROM Table_Name WHERE Date BETWEEN @StartDate AND @EndDate AND Table_Name.Product IN ( SELECT value FROM STRING_SPLIT(@ProductList, ',') ) );
调用方式就和你最初期望的更接近了:
SELECT * FROM func_2_Alternative('20190101', '20191231', 'value_1,value_2,value_3');
不过要注意:如果你的产品值本身包含逗号,这种方式会出错;而且表值参数的性能和安全性比字符串拆分更好,适合数据量较大或值有特殊字符的场景。
内容的提问来源于stack exchange,提问作者yongsheng
相关产品推荐
相关产品推荐

