【问题标题】:User-defined function with arbitrary parameter list具有任意参数列表的用户定义函数
【发布时间】:2018-07-10 15:49:53
【问题描述】:

Coalesce() 内置函数接受任意数量的参数。

是否可以在 SQL Server 2012 中使用相同的语法编写一个用户定义的函数来执行此操作?我不想使用表格变量或逗号分隔列表。

我想实现一个 Coalesce() 函数,它返回传入的 LOWEST 非空元素,而不是传入的第一个非空元素。这是为了满足新的用户需求。 Coalesce() 不需要创建表变量,并且由于我正在用新逻辑替换现有的 Coalesce() 调用,因此我想编写我的新函数以使其行为方式相同,包括接受任意数量的元素。

我知道我可以在这里采取其他方法 - 我想尽量减少我必须做的重写。

【问题讨论】:

  • 它的用途,特别是表变量参数。我会远离逗号分隔的列表,因为之后你只需要将它变成一个表格。但是表值参数是这里的最佳选择。但是,这可能是一个 XY 问题,您能告诉我们您要完成什么吗?
  • 您可以创建一个带有可选参数和默认值的函数。 (带有可选参数的 SP 的示例是 here。)这与拥有不可预测数量的 sql_variant 参数不同,但它可能很有用。
  • 我已经更新了我最初的问题并提供了更多详细信息。
  • 你能定义最低吗
  • 就我而言,“最早日期”。但同样,这与问题的重点无关,即“可以像 Coalesce() 函数那样在 SQL Server 中编写一个接受任意数量参数的 UDF 吗?”

标签: sql-server tsql sql-server-2012 parameter-passing user-defined-functions


【解决方案1】:

是的,这是可能的。只是不在 T-SQL 中。你需要写一个CLR函数

【讨论】:

  • 实际上,@ALollz,这正好回答了我的问题。
【解决方案2】:

如果可以避免的话,我不想使用表格变量或逗号分隔列表。

TVP 是要走的路。但是如果你不想定义表类型,你可以使用老式的 XML:

CREATE TABLE tab(id INT, a INT, b INT, c INT, d INT);
INSERT INTO tab(id,a,b,c,d) VALUES(1,1,NULL,NULL,NULL);
INSERT INTO tab(id,a,b,c,d) VALUES(2,2,2,NULL,NULL);
INSERT INTO tab(id,a,b,c,d) VALUES(3,3,3,3,NULL);
INSERT INTO tab(id,a,b,c,d) VALUES(4,4,4,4,4);

功能:

CREATE FUNCTION dbo.my_func(@input XML)
RETURNS INT
AS
BEGIN
RETURN
(
  SELECT SUM(a.b.value('.', 'INT'))   --any logic here, for simplicity's sake SUM
  FROM @input.nodes('/*') AS sub(c)
  CROSS APPLY sub.c.nodes('@*') a(b)
);
END;

然后调用:

SELECT t1.*, sub.*, dbo.my_func(sub.x) AS result
FROM tab t1
CROSS APPLY (SELECT a,b,c,d
             FROM (SELECT 1) t2(q) FOR XML AUTO) sub(x);

DBFiddle Demo

输出:

┌────┬───┬──────┬──────┬──────┬───────────────────────────────┬────────┐
│ id │ a │  b   │  c   │  d   │               x               │ result │
├────┼───┼──────┼──────┼──────┼───────────────────────────────┼────────┤
│  1 │ 1 │ null │ null │ null │ <t2 a="1"/>                   │      1 │
│  2 │ 2 │ 2    │ null │ null │ <t2 a="2" b="2"/>             │      4 │
│  3 │ 3 │ 3    │ 3    │ null │ <t2 a="3" b="3" c="3"/>       │      9 │
│  4 │ 4 │ 4    │ 4    │ 4    │ <t2 a="4" b="4" c="4" d="4"/> │     16 │
└────┴───┴──────┴──────┴──────┴───────────────────────────────┴────────┘

编辑:

不,不能使用 COLAESCE 之类的变量 args 定义 UDF。你能得到的最好的结果是:

LOWEST2(a1, a2)
LOWEST3(a1, a2, a3)
LOWEST4(a1, a2, a3, a4)
...
LOWESTn(a1, a2, a3, a4, ..., an)

请注意函数名称不同。另外,您需要使用能够满足大多数情况甚至sqlvariant 的数据类型。

【讨论】:

  • 这不是用户定义的函数,它像 Coalesce() 那样接受任意数量的参数。
  • @Brian 不,在纯 T-SQL 中你不能做你想做的事。我回答了你的第二部分。正确的方法是 TVP。
  • 不,你没有,因为传入 XML 字符串与 Coalesce() 函数的“语法不同”。
  • 虽然您的 cmets 是真实的 @Brian,但这是一种本机方式,无需更改服务器默认设置,也无需引入像 CLR 一样庞大的东西,而这些东西并不容易实现、便携等。
  • 也许,@scsimon,但这并不能改变 Lukasz 的回复不符合我的需求这一事实。我问“有可能做 X 吗?这就是我想做 X 的原因”,而这个回复是冗长的“这就是如何做 Y,这是相似的,也是我认为你应该做的。”
猜你喜欢
  • 2012-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-15
  • 1970-01-01
相关资源
最近更新 更多