【问题标题】:SQL Server User Defined Function taking arguments of any type like ISNULLSQL Server 用户定义函数采用任何类型的参数,如 ISNULL
【发布时间】:2015-10-09 20:03:09
【问题描述】:

我需要创建一个用户定义的函数,该函数的操作类似于 ISNULL 系统函数,因为它可以接受任何类型的参数并返回相同类型的值。 这是怎么做到的?

使用 SQL_VARIANT 作为数据类型将不起作用,因为 SQL_VARIANT 值需要显式转换。 ISNULL 隐式进行数据类型转换。

如何声明不需要显式转换的泛型类型?

让我说清楚。我不想复制 ISNULL 函数的功能。我使用 ISNULL 函数作为函数模式,它接受 SQL Server 支持的任何数据类型的两个参数,并返回与参数相同数据类型的值。

还有其他实现相同模式的 SQL Server 函数:接受未显式声明的数据类型的参数并返回某些其他数据类型的值,该值也未在函数定义中显式声明。例如:NULLIF、CAST、CONVERT。

我想知道如何实现这种模式,因为任何 UDF 都需要显式定义参数和返回值数据类型。

【问题讨论】:

  • 每种类型的替换值应该是多少?用空字符串替换 NULL 字符串是相当明显的,但 datetime 的非值是什么?零真的是数字类型的非值吗?你想达到什么目标?
  • T-SQL 没有泛型,并且用户定义的函数返回类型是静态的(并且是必需的),因此您真正要求的是不可能的。我可以想到有几件事可以实现您想要的(例如生成表的存储过程或动态 SQL),但也是您不想在生产代码中使用这些的充分理由。既然ISNULL 已经存在并且工作得很好,那么您到底想要什么与ISNULL“相似”,又是为了什么?
  • Shnugo,关键是要有一个与参数类型无关并且能够接受任何参数类型的函数,就像 ISNULL 或 NULLIF 这样的函数所做的那样。重点不是实现另一个版本的 ISNULL,而是能够创建一个新函数,它能够处理任何时间的参数,更重要的是返回与参数相同类型的值。
  • Jeroen Mostert,我很困惑,我原来的问题不清楚。我明确指出我不需要创建另一个 ISNULL 函数。我解释说我正在寻找的相似性是严格意义上的模式。

标签: sql-server generics types user-defined-functions isnull


【解决方案1】:

我刚刚回答了一个有点相关的问题:https://stackoverflow.com/a/32985478/5089204

没有安全的方法来处理空值。 ISNULL 在大多数情况下非常好,但如果您没有隐式可转换类型的两个参数,则不会编译。

看看这在 XML 中是如何处理的。只需将其粘贴到一个空的查询窗口中并执行:

--The NULL-element is not there at all
SELECT 'text' AS filled
      ,'' AS empty
      ,NULL AS NotThere
FOR XML PATH('row');   

--The NULL-element is rendered using "nil"
SELECT 'text' AS filled
      ,'' AS empty
      ,NULL AS NotThere
FOR XML PATH('row'),ELEMENTS XSINIL    

--Look at this: Both columns are called "TheName". They are implicitly concatenated
SELECT 'a' AS TheName
      ,'b' AS TheName
FOR XML PATH('row')

--That leads to: Concatenate nothing with an empty string will at least return the empty string.
--this is other/better than ISNULL, because it will work with any type...
SELECT NULL AS TheName
      ,'' AS TheName
FOR XML PATH('row')

--now an example with table data
DECLARE @tbl TABLE(int1 INT, int2 INT);
INSERT INTO @tbl VALUES(NULL,1); --first value is null

--int1 is swallowed
SELECT *
FROM @tbl
FOR XML PATH('row')

--both elements are there
SELECT int1, '' AS int1 --ISNULL(int1,'') would not compile here...
      ,int2, '' AS int2
FROM @tbl
FOR XML PATH('row')

--This is the result of the last example: Look what happens to the empty int element, its Zero! 
--This is the way this is handled in XML conversions. Try it with other types (like 'date' [result is 1900-01-01] or any other type)...
DECLARE @a XML='<row><int1></int1><int2>1</int2></row>';
SELECT a.b.value('int1[1]','int') AS int1
      ,a.b.value('int2[1]','int') AS int2
FROM @a.nodes('/row') a(b)

【讨论】:

  • 这真的很吸引人,而且信息量很大。感谢您分享这些信息。我相信我会找到一个很好的用途。但是,它让我离我的问题的答案更近了:SQL Server 如何在没有显式定义参数和返回值数据类型的情况下实现 ISNULL、CONVERT、CAST、NULLIF 等函数?
猜你喜欢
  • 2016-11-25
  • 1970-01-01
  • 2018-06-30
  • 1970-01-01
  • 2013-08-07
  • 1970-01-01
  • 2011-03-06
  • 2019-04-11
相关资源
最近更新 更多