无法对“FunctionName”执行更改,因为它是不兼容的对象类型

Evi*_*lDr 3 sql-server t-sql sql-server-2016

我知道之前已经问过同样的问题,但情况略有不同,我想更多地解释为什么它在我的上下文中失败,当(AFAIK)返回类型相同时。

过去,在我的数据库中,我使用基于 CLR 的表值函数将逗号分隔值拆分为包含整数列的表。

因为 SQL2016 引入了STRING_SPLIT,我需要换掉这个函数的 CLR 部分,并替换为原生的 TSQL 函数(因为我有数百个依赖这个函数的存储过程)。

如果我在 SSMS 中修改这个函数,我会看到:

ALTER FUNCTION [dbo].[e4fn_CreateIdTable](
     @Ids [nvarchar](max), 
     @separator [nchar](1))
RETURNS TABLE (
    [IdVal] [int] NULL
) WITH EXECUTE AS CALLER
AS 
EXTERNAL NAME [ValueSplitter].[MyCompany.ValueSplitter].[SplitToIntegers]
Run Code Online (Sandbox Code Playgroud)

我希望我能够像这样改变它:

ALTER FUNCTION [dbo].[e4fn_CreateIdTable] (
    @Ids [nvarchar](max), 
    @separator [nchar](1)
)
RETURNS TABLE 
AS RETURN
(
    SELECT
        CAST(NULLIF(LTRIM(RTRIM(value)), '') AS int) AS IdVal
    FROM
        STRING_SPLIT(@Ids, @separator)
)
GO
Run Code Online (Sandbox Code Playgroud)

这返回了错误:

无法对“dbo.e4fn_CreateIdTable”执行更改,因为它是不兼容的对象类型。

我认为这是因为没有明确定义输出参数的表定义。所以,我这样重试:

ALTER FUNCTION [dbo].[e4fn_CreateIdTable] (
    @Ids [nvarchar](max), 
    @separator [nchar](1)
)
RETURNS @tbl TABLE  (
    IdVal int
)
AS 
BEGIN
    INSERT INTO @tbl (
        Idval
    )
    SELECT
        CAST(NULLIF(LTRIM(RTRIM(value)), '') AS int)
    FROM
        STRING_SPLIT(@Ids, @separator);

    RETURN;
END
GO
Run Code Online (Sandbox Code Playgroud)

再次出现相同的错误。

  1. 当返回类型似乎相同时,为什么会出现错误?
  2. 如果我删除/重新创建函数,是否需要重新编译所有存储过程?

Dan*_*man 7

CLR TVF 是一种与 SQL TVF 根本不同的数据库对象类型,因此必须使用“DROP/CREATE”而不是ALTER更改定义。

CLR TVF 的sys.objects 中的类型是“FT”,而 SQL TVF(非内联)是“TF”。