CLR Table-Valued函数

这几天来,努力学习了CLR的存储过程,创建与部署。从普通的存储过程,带参数,以及Output返回值等。

Insus.NET今天学习一个例子,怎样实现CLR Table-Valued函数。在数据库中,我们可以看到很多种函数类型,Table-falued function,Scalar-valued function 等等。

这篇练习的CLR中编写的函数就是table-valued function。

在VS开发SQL的 CLR程序,有简单有复杂,看开发时的衡量了。有些在SQL中无法实现的,可以写成CLR,然后再部署至SQL中。此篇并没有看出两者之间的优势,仅是一个例子作为参考。

比如我们想创建一个多表查询LEFT JOIN。把SQL语句写成一个table-valued函数。这个多表查询,所返回的字段,定义成一个类别:

上面代码示例,可复制代码:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlTypes;
using System.Text;

namespace Insus.NET
{
    class Fruit
    {
        public byte Fruit_nbr { get; set; }
        public byte  FruitCategory_nbr { get; set; }
        public string CategoryName { get; set; }
        public byte FruitKind_nbr { get; set; }
        public string  KindName { get; set; }
        public string  FruitName { get; set; }
    }
}

创建一个新Item:

按下面的步骤,在标记5中选择SQL CLR C# User Defined Function。

标记6,给一个名字,标记7"Add"之后:

删除#14至#19行代码,添加下面代码:

上面代码示例,可复杂代码:

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Collections;
using Insus.NET;
using System.Collections.Generic;

public partial class UserDefinedFunctions
{
    [SqlFunction(DataAccess = DataAccessKind.Read,
                 FillRowMethodName = "Item_FillRow",
                 TableDefinition = "Fruit_nbr TINYINT,FruitCategory_nbr TINYINT, " +
                                  "CategoryName NVARCHAR(30),FruitKind_nbr TINYINT," +
                                  "KindName NVARCHAR(30),FruitName NVARCHAR(30)"
                 )
    ]
    public static IEnumerable Tvf_Fruit()
    {
        List<Fruit> fruitConnections = new List<Fruit>();
        using (SqlConnection connection = new SqlConnection("context connection=true"))
        {
            connection.Open();
            string sql = "SELECT [Fruit_nbr],[FruitCategory_nbr],[CategoryName]," +
                "u_fk.[FruitKind_nbr],[KindName],[FruitName] FROM [dbo].[Fruit] AS f " +
                "LEFT JOIN [dbo].[udf_FruitKind]() AS u_fk ON (f.[FruitKind_nbr] = u_fk.[FruitKind_nbr])";
            using (SqlCommand command = new SqlCommand(sql, connection))
            {
                using (SqlDataReader objDr = command.ExecuteReader())
                {
                    while (objDr.Read())
                    {
                        Fruit oFruit = new Insus.NET.Fruit();
                        oFruit.Fruit_nbr = (byte)objDr["Fruit_nbr"];
                        oFruit.FruitCategory_nbr = (byte)objDr["FruitCategory_nbr"];
                        oFruit.CategoryName = objDr["CategoryName"].ToString();
                        oFruit.FruitKind_nbr = (byte)objDr["FruitKind_nbr"];
                        oFruit.KindName = objDr["KindName"].ToString();
                        oFruit.FruitName = objDr["FruitName"].ToString();
                        fruitConnections.Add(oFruit);
                    }
                }
            }
        }
        return fruitConnections;
    }

    private static void Item_FillRow(object source, out SqlByte fruit_nbr,
        out SqlByte fruitCategory_nbr, out SqlChars categoryName,
        out SqlByte fruitKind_nbr, out SqlChars kindName, out SqlChars fruitName)
    {
        Fruit fruit = (Fruit)source;
        fruit_nbr = new SqlByte(fruit.Fruit_nbr);
        fruitCategory_nbr = new SqlByte(fruit.FruitCategory_nbr);
        categoryName = new SqlChars(fruit.CategoryName);
        fruitKind_nbr = new SqlByte(fruit.FruitKind_nbr);
        kindName = new SqlChars(fruit.KindName);
        fruitName = new SqlChars(fruit.FruitName);
    }
}

接下来,Build,然后可以部署至SQL中去。

上面可复制代码:

IF EXISTS (SELECT * FROM sys.objects WHERE name = ‘Tvf_Fruit‘)
    DROP FUNCTION Tvf_Fruit;
GO

IF EXISTS (SELECT * FROM sys.assemblies WHERE name = ‘FruitClr‘)
    DROP ASSEMBLY FruitClr;
GO

CREATE ASSEMBLY FruitClr
FROM ‘E:\FruitClr.dll‘
WITH PERMISSION_SET = SAFE;
GO

CREATE FUNCTION Tvf_Fruit()
RETURNS TABLE (
    Fruit_nbr TINYINT,
    FruitCategory_nbr TINYINT,
    CategoryName NVARCHAR(30),
    FruitKind_nbr TINYINT,
    KindName NVARCHAR(30),
    FruitName NVARCHAR(30)
)
AS
EXTERNAL NAME [FruitClr].UserDefinedFunctions.Tvf_Fruit;
GO

执行成功之后,你肯定会发现SQL发生变化的两个位置:

此时table-valued function创建成功了,在查询分析器执行一下Tvf_Fruit()函数。

时间: 2024-10-05 05:02:06

CLR Table-Valued函数的相关文章

lua中的数据结构-table常用函数库

table.concat(table, sep,  start, end) concat是concatenate(连锁, 连接)的缩写. table.concat()函数列出参数中指定table的数组部分从start位置到end位置的所有元素, 元素间以指定的分隔符(sep)隔开.除了table外, 其他的参数都不是必须的, 分隔符的默认值是空字符, start的默认值是1, end的默认值是数组部分的总长. sep, start, end这三个参数是顺序读入的, 所以虽然它们都不是必须参数,

LUA table中函数的调用

1 lua中函数作为表中元素时有三种定义方式 采用':'来定义,实际上隐藏了一个形参的声明,这个形参会截获调用函数时的第一个实参并把它赋值给self 2 调用方式,点号和冒号 functb:hello1()functb.hello2() 总结起来就是带:号调用表的函数时,会把表赋值给self,这样函数体里面可以直接使用self访问表的数据

转载——CLR标量函数、表值函数和聚合函数(UDA)

本节主要介绍使用CLR创建标量函数,表值函数和聚合函数. 所谓标量函数指的就是此函数只返回一个值.表值函数返回值是一个表.聚合函数是在select语句中使用的,用来聚合一个结果集,类似于Sum()或是Count()等内置的函数,而且真正的自定义聚合函数目前只能用CLR来实现. 下面的例子使用了SQLServer自带的pubs数据库. 1.CLR标量函数 1.1无参函数     ///     /// 标量函数,不带参数     ///     ///     [Microsoft.SqlServ

SQL Server CLR 使用 C# 自定义函数

原文:SQL Server CLR 使用 C# 自定义函数 一.简介 Microsoft SQL Server 2005之后,实现了对 Microsoft .NET Framework 的公共语言运行时(CLR)的集成.CLR 集成使得现在可以使用 .NET Framework 语言编写代码,从而能够在 SQL Server 上运行,现在就可以通过 C# 来编写 SQL Server 自定义函数.存储过程.触发器等.我最初的目的是因为在 SQL Server 数据库中遇到数字的十进制与十六进制的

PCB MS SQL表值函数与CLR 表值函数 (例:字符串分割转表)

将字符串分割为表表经常用到,这里 SQL表值函数与CLR  表值函数,两种实现方法例出来如下: SELECT * FROM FP_EMSDB_PUB.dbo.SqlSplit('/','1oz/1.5oz/2oz/3oz') 效果如下: SQL实现表值函数 CREATE FUNCTION [dbo].[splitStr]( @s varchar(max), --待分拆的字符串 @split varchar(10) --数据分隔符 )RETURNS @re TABLE(id int IDENTIT

PCB MS SQL 标量函数(CLR) 实现转Json方法

一.准备需转为json的数据 在数据库中执行一段SQL返回的数据 需转换后的JSON字符串的效果 [{"TechName":"开料","ItemName":"综合利用率是否为最高","ItemPara":"/"},{"TechName":"开料","ItemName":"综合利用率","ItemPa

R read.table函数的check.names参数

今天用cummeRbund 对cuffdiff的结果进行可视化, 一直报错,之前跑的好好的,找了半天原因, 原来出现在read.table这个函数上: read.table有一个参数check.names , 其默认值为TRUE,它会自动将变量名转换成唯一的字符型向量 其通过调用make.names函数来实现这一过程, 比如我的原始数据中列名称分别为1,2,3,4,5,6, make.names(c("1", "2", "3", "4&

Lua中的table函数库

table.concat(table, sep,  start, end) concat是concatenate(连锁, 连接)的缩写. table.concat()函数列出参数中指定table的数组部分从start位置到end位置的所有元素, 元素间以指定的分隔符(sep)隔开.除了table外, 其他的参数都不是必须的, 分隔符的默认值是空字符, start的默认值是1, end的默认值是数组部分的总长. sep, start, end这三个参数是顺序读入的, 所以虽然它们都不是必须参数,

转 Lua标准库: table函数, 数学函数, 字符串函数/格式化/配对, WoW新增函数, 函数别名

这里只介绍和插件编写比较有关的几个函数. 详细的Lua手册请参照Lua Reference Manual 5.1. assert(value) - 检查一个值是否为非nil, 若不是则(如果在wow.exe打开调试命令)显示对话框以及输出错误调试信息 collectgarbage() - 垃圾收集器. (新增于1.10.1) date(format, time) - 返回当前用户机器上的时间. error("error message",level) - 发生错误时,输出一条定义的错误

lua的table库中的常用函数总结

https://www.cnblogs.com/daochong/p/7363649.html table是Lua语言中的一种重要的数据类型, table 的一些特性简单列举如下: (1).table 是一个“关联数组”,数组的索引可以是数字或者是字符串; (2).table 的默认初始索引一般以 1 开始; (3).table 的变量只是一个地址引用,对 table 的操作不会产生数据影响; (4).table 不会固定长度大小,有新数据插入时长度会自动增长; (5).table 所有索引值都