
# 简介
我最初想着从 **==函数==** 动态获取仓位名称,但是运行函数提示运算符EXECUTE STRING 无效,在function中不能使用exec和sp_executesql。
所以做了一个获取仓位名称的 **==存储过程==**
**传送门:[MSSQL - 仓位的标识【动态】获取仓位名称](https://wenku.my7c.com/article/483211870225238784?productLineId=1)**
但是使用存储过程
局限性较大,无法直接在查询中调用,为了解决这个问题决定使用 **
CLR 用户定义函数 ** 来实现
# 配置 SQL Server CLR
``` SQL
---开启所有服务器配置选项
EXEC sp_configure N'show advanced options', N'1';
RECONFIGURE WITH OVERRIDE
```
``` SQL
--开启clr enabled 选项
EXEC sp_configure N'clr enabled', N'1'
RECONFIGURE WITH OVERRIDE
```
``` SQL
--关闭所有服务器配置选项
EXEC sp_configure N'show advanced options', N'0'
RECONFIGURE WITH OVERRIDE
```
## 假如存在权限异常
**
如果存在权限问题,执行下面一段脚本**
``` sql
ALTER DATABASE 数据库名 SET TRUSTWORTHY ON
EXEC sp_changedbowner 'sa'
```
# 创建CLR函数 VS2022
## 1. 创建一个数据库项目

## 2. 新建一个用户自定义函数

## 3. 根据上一篇文章存储过程改为 C# 代码
``` C#
[Microsoft.SqlServer.Server.SqlFunction(DataAccess = DataAccessKind.Read)]
public static SqlString ScalarFunction(SqlInt32 FSTOCKID, SqlInt32 FSTOCKLOCID)
{
using (SqlConnection conn = new SqlConnection("context connection=true"))
{
conn.Open();
DataTable T_BD_STOCKFLEXITEM = new DataTable();
string Str = $"SELECT FSEQ, T31.FFLEXNUMBER FROM T_BD_STOCKFLEXITEM T1 INNER JOIN T_BAS_FLEXVALUES T31 ON T1.FFLEXID = T31.FID WHERE FSTOCKID = {FSTOCKID} ";
SqlCommand cmd = new SqlCommand(Str, conn);
var edr = cmd.ExecuteReader();
DataTable schemaTable = edr.GetSchemaTable();
try
{
//动态构建表,添加列
foreach (DataRow dr in schemaTable.Rows)
{
DataColumn dc = new DataColumn();
//设置列的数据类型
dc.DataType = dr[0].GetType();
//设置列的名称
dc.ColumnName = dr[0].ToString();
//将该列添加进构造的表中
T_BD_STOCKFLEXITEM.Columns.Add(dc);
}
if (edr.HasRows)
{
//读取数据添加进表中
while (edr.Read())
{
DataRow row = T_BD_STOCKFLEXITEM.NewRow();
//填充一行数据
for (int i = 0; i < schemaTable.Rows.Count; i++)
{
row[i] = edr[i].ToString();
}
T_BD_STOCKFLEXITEM.Rows.Add(row);
row = null;
}
edr.Close();
schemaTable = null;
}
}
catch (Exception ex)
{
if (!edr.IsClosed) { edr.Close(); };
//抛出异常
throw new Exception(ex.Message);
}
string ReturnStr = "";
if (T_BD_STOCKFLEXITEM != null&& T_BD_STOCKFLEXITEM.Rows.Count>0)
{
foreach (DataRow item in T_BD_STOCKFLEXITEM.Rows)
{
string FFLEXNUMBER_SQL = $"SELECT V{item["FFLEXNUMBER"].ToString()}.FNAME FROM T_BAS_FLEXVALUESDETAIL FVD LEFT JOIN T_BAS_FLEXVALUESENTRY_L AS V{item["FFLEXNUMBER"].ToString()} ON FVD.{item["FFLEXNUMBER"].ToString()}=V{item["FFLEXNUMBER"].ToString()}.FENTRYID AND V{item["FFLEXNUMBER"].ToString()}.FLOCALEID = 2052 WHERE FID={FSTOCKLOCID}";
cmd = new SqlCommand(FFLEXNUMBER_SQL, conn);
string OutPutStr = (string) cmd.ExecuteScalar();
if (!string.IsNullOrEmpty(OutPutStr))
{
ReturnStr = $"{ReturnStr}.{OutPutStr}";
}
}
}
return ReturnStr.Trim('.');
}
return new SqlString("获取失败");
}
```
# 注册 CLR 程序集
## 注册CLR程序集方式一,指定程序集DLL的路径
``` sql
--注册CLR程序