SQLserver 資料庫自定義函式
阿新 • • 發佈:2020-10-23
起源
最近專案開發上使用的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:\ConactDll\Database3.dll', SINGLE_BLOB) AS [Data]))) 第三步:建立程式集與聚合函式 CREATE ASSEMBLY MyAgg FROM 'F:\ConactDll\Database3.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://dotblogs.com.tw/stanley14/2018/05/26/tsql_string_agg_insql2016