zoukankan      html  css  js  c++  java
  • SQLserver 数据库自定义函数

    起源

        最近项目开发上使用的SQLserver数据库是2008版本,由于08版本的数据是没有字符串合并(STRING_AGG)这个函数(2017版本及以上支持)的,只有用stuff +for xml path('') 来达到效果。所以才有萌生出了自定义聚合函数的想法。
    

    使用 Visual Studio 创建数据库项目生成调用的 DLL

    第一步新建项目:
    2008版本选择 文件→新建→项目→SQL Server项目
    

     创建成功结果如下:
    

    第二步新建项→聚合:
    

    第三步:编写代码(实现字符串合并的函数代码如下)
    
    聚合函数代码
    using System;
    using System.Data;
    using Microsoft.SqlServer.Server;
    using System.Data.SqlTypes;
    using System.IO;
    using System.Text;
    
    [Serializable]
    [SqlUserDefinedAggregate(
    Format.UserDefined, //use clr serialization to serialize the intermediate result
    IsInvariantToNulls = true, //optimizer property
    IsInvariantToDuplicates = false, //optimizer property
    IsInvariantToOrder = false, //optimizer property
    MaxByteSize = 8000) //maximum size in bytes of persisted value
    ]
    
    public class Concatenate : IBinarySerialize
    {
    /// <summary>
    /// The variable that holds the intermediate result of the concatenation
    /// </summary>
    private StringBuilder intermediateResult;
    
    /// <summary>
    /// Initialize the internal data structures
    /// </summary>
    public void Init()
    {
        this.intermediateResult = new StringBuilder();
    }
    
    /// <summary>
    /// Accumulate the next value, not if the value is null
    /// </summary>
    /// <param name="value"></param>
    public void Accumulate(SqlString value)
    {
        if (value.IsNull)
        {
            return;
        }
    
        this.intermediateResult.Append(value.Value).Append(',');
    }
    
    /// <summary>
    /// Merge the partially computed aggregate with this aggregate.
    /// </summary>
    /// <param name="other"></param>
    public void Merge(Concatenate other)
    {
        this.intermediateResult.Append(other.intermediateResult);
    }
    
    /// <summary>
    /// Called at the end of aggregation, to return the results of the aggregation.
    /// </summary>
    /// <returns></returns>
    public SqlString Terminate()
    {
        string output = string.Empty;
        //delete the trailing comma, if any
        if (this.intermediateResult != null
            && this.intermediateResult.Length > 0)
        {
            output = this.intermediateResult.ToString(0, this.intermediateResult.Length - 1);
        }
    
        return new SqlString(output);
    }
    
    public void Read(BinaryReader r)
    {
        intermediateResult = new StringBuilder(r.ReadString());
    }
    
    public void Write(BinaryWriter w)
    {
        w.Write(this.intermediateResult.ToString());
    }
    }
    
    第四步:生成项目DLL并放于其他目录下面(非必须,C盘可能存在权限问题在注册时无法使用)
        我放在F盘下面的这个路径
    

    SQLserver 注册刚才编写的聚合函数 DLL

    第一步:允许SQLserver安装外部程序集
       数据库默认是不允许安装外部程序级的,需要通过sp_configure命令 修改clr enabled
    
       /*允许程序使用外部程序集*/
       EXEC sp_configure 'clr enabled', 1
       RECONFIGURE WITH OVERRIDE
       GO
    第二步:解决安全权限的配置引发的问题(不执行这一步就会触发安全权限配置问题)
      具体链接安全问题链接:https://blog.csdn.net/weixin_34150503/article/details/92828414
    
      /*sp_add_trusted_assembly的方式添加信任到数据库里去.*/
    DECLARE @hash AS BINARY(64) = (SELECT HASHBYTES('SHA2_512', (SELECT * FROM OPENROWSET (BULK 'F:ConactDllDatabase3.dll', SINGLE_BLOB) AS [Data])))
    
    第三步:创建程序集与聚合函数
    CREATE  ASSEMBLY MyAgg FROM 'F:ConactDllDatabase3.dll'
    WITH PERMISSION_SET = SAFE;
    GO
    
    CREATE AGGREGATE MyAgg (@input nvarchar(200)) RETURNS nvarchar(max)
    EXTERNAL NAME MyAgg.Concatenate;
    
    注册完成之后系统数据库会出现我们自定义的聚合函数
    

    SQL 中使用自定义聚合函数

    select  dbo.myagg(需要合并的表字段)  结果 from   表  where 查询条件
    使用效果如下:
    

    额外篇

    使用VS2019新建SQLserver数据库项目
    
    第一步:创建项目
    


    第二步:添加新项
    

    后面就可以开始编写代码了,操作流程跟之前的 08 版本一样
    最后附上已经写好的两个版本,需要的同学自取:https://pan.baidu.com/s/1encGUxiMpFcZXLum1zr3Ug 提取码: 8wyq
    文章参考:https://dotblogs.com.tw/stanley14/2018/05/26/tsql_string_agg_insql2016

  • 相关阅读:
    React 之 jsx
    React 之 初识
    vue 之 svg
    c#进阶 之 特性
    c#进阶 之 反射Reflection
    面试题解答分析
    c#进阶 之 泛型
    c#进阶 之 修饰符
    c#进阶 之 方法汇总
    微信开发学习(二)
  • 原文地址:https://www.cnblogs.com/wofeiliangren/p/13863177.html
Copyright © 2011-2022 走看看