CLR具有数组参数的表值函数

Vác*_*ych 9 sql-server sqlclr user-defined-functions table-valued-parameters

我有一个像这样的SQL CLR函数:

public partial class UserDefinedFunctions {
    [Microsoft.SqlServer.Server.SqlFunction(TableDefinition = "number int", FillRowMethodName = "FillRow")]
    public static IEnumerable MyClrFunction(object obj) {
        // read obj array input and then
        var result = new ArrayList();
        result.Add((SqlInt32)1);
        result.Add((SqlInt32)2);
        result.Add((SqlInt32)3);
        return result;
    }

    public static void FillRow(object obj, out SqlInt32 number) {
        number = (SqlInt32)obj;
    }

}
Run Code Online (Sandbox Code Playgroud)

我想用这种方式使用它:

DECLARE @x arrayOfInt

INSERT INTO @x VALUES (10)
INSERT INTO @x VALUES (20)
INSERT INTO @x VALUES (30)

SELECT * FROM dbo.MyClrFunction(@x)
Run Code Online (Sandbox Code Playgroud)

arrayOfInt是:

CREATE TYPE [dbo].[arrayOfInt] AS TABLE(
[item] [int] NOT NULL,
PRIMARY KEY CLUSTERED 
    (
    [item] ASC
    ) WITH (IGNORE_DUP_KEY = OFF)
)
Run Code Online (Sandbox Code Playgroud)

遇到的问题是arrayOfInt与sql_variant不兼容.是否可以编写具有数组(表)参数的CLR表值函数?

Sol*_*zky 11

SQLCLR不支持表值参数(TVP):

  • 创建程序

    [type_schema_name.] data_type
    ...
    CLR程序指南:

    • 表值或游标数据类型不能用作参数.
  • 创造功能

    [type_schema_name.] parameter_data_type
    ...对于CLR函数,除text,ntext,image,用户定义的表类型和时间戳数据类型外,允许使用所有数据类型,包括CLR用户定义的类型.

但是,您有几个选择:

  1. 如果数组是一个简单的数字和/或字符串列表,您可以始终以分隔的值列表(通过SqlString/NVARCHAR(MAX))发送并使用String.Split()来解压缩它.

  2. 如果数组更复杂(即多个字段),那么您可以用XML包装数据并将其作为SqlXml传递.

  3. 或者,如果您有一个复杂的数组,那么您可以创建一个CLR UDT,使其成为您喜欢的任何结构并将其传递给Function.但这需要更多的努力.

  4. 另外,请记住,表值参数只是表(表变量),而不是内存数据结构,如数组和集合.TVP的主要优点和用例是在从应用程序向SQL Server发送数据时降低复杂性并提高性能.如果您已经在SQL Server中,那么您正在创建一个表变量,然后想要将它传递给CLR存储过程(或者可能是函数),那么您需要做的就是以稍微不同的方式查看问题而您可以完成同样的基本事情:

    • 使用临时表而不是表变量
    • 将临时表名称传递给CLR存储过程
    • 使用进程内连接(即连接字符串= "Context Connection = true;"),因为它可以访问本地临时对象
    • 您可以使用传入的表名在您执行的任何SQL中使用临时表
    • 您可以通过对传入的SELECT *表名执行简单操作,将该表中的数据导入.NET上下文,然后通过SqlCommand.ExecuteReader()和读取每一行SqlDataReader.Read()

  • 这很有趣:"你总是可以发送一个分隔的值列表",因为我在寻找传递字符串表的方法时发现自己在这里,这样我就可以使用CLR将它们连接成一个单独的分隔字符串: ) (4认同)