PCB MS SQL 标量函数(CLR) 实现DataTable转Json方法
一.准备需转为json字符串的DataTable数据
在数据库中执行一段SQL返回的数据
需转换后的JSON字符串的效果
[{"TechName":"开料","ItemName":"综合利用率是否为最高","ItemPara":"/"},{"TechName":"开料","ItemName":"综合利用率","ItemPara":"68.36"},{"TechName":"开料","ItemName":"纬向余料","ItemPara":"0"},{"TechName":"开料","ItemName":"经向余料","ItemPara":"0"},{"TechName":"开料","ItemName":"是否为小交货面积拼板","ItemPara":"n"},{"TechName":"开料","ItemName":"纬向尺寸","ItemPara":"24"},{"TechName":"开料","ItemName":"是否为阴阳铜结构","ItemPara":"N"},{"TechName":"开料","ItemName":"是否横竖开料","ItemPara":"N"},{"TechName":"开料","ItemName":"生产尺寸长","ItemPara":"24"},{"TechName":"开料","ItemName":"生产尺寸宽","ItemPara":"18"},{"TechName":"开料","ItemName":"拼板利用率","ItemPara":"68.36"},{"TechName":"开料","ItemName":"开料图纸","ItemPara":"/"},{"TechName":"开料","ItemName":"是否顾客指定板材","ItemPara":"N"},{"TechName":"开料","ItemName":"开料数","ItemPara":"4"},{"TechName":"开料","ItemName":"大料经向尺寸","ItemPara":"36"},{"TechName":"开料","ItemName":"大料纬向尺寸","ItemPara":"48"},{"TechName":"开料","ItemName":"成品尺寸长","ItemPara":"12"},{"TechName":"开料","ItemName":"成品尺寸宽","ItemPara":"13.5"},{"TechName":"开料","ItemName":"是否为PTFE板材","ItemPara":"N"},{"TechName":"开料","ItemName":"交货拼板个数","ItemPara":"1"},{"TechName":"开料","ItemName":"生产拼板个数","ItemPara":"1176"},{"TechName":"开料","ItemName":"交货单位","ItemPara":"U"},{"TechName":"开料","ItemName":"是否为凹蚀板材","ItemPara":"N"}]
二.C#写SQL SERVER(CLR)转JSON函数
先执行SQL返回DataTable,接着再将DataTable转为Json, 这里转为Json有2种方法,代码都贴在下方了
/// <summary>
/// 执行SQL语句 返回的DataTable 转为 Json
/// </summary>
/// <param name="StrSQL"></param>
/// <returns></returns>
[Microsoft.SqlServer.Server.SqlFunction(DataAccess = DataAccessKind.Read)]
public static string ExecSQL2Json(string StrSQL)
{
DataTable dt = getDataTable(StrSQL);
//return DataTable2Json(dt); //方法1 转为 Json
if (dt is null)
return null;
List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();
foreach (DataRow dr in dt.Rows)
{
Dictionary<string, object> result = new Dictionary<string, object>();
foreach (DataColumn dc in dt.Columns)
{
result.Add(dc.ColumnName, dr[dc].ToString());
}
list.Add(result);
}
return Json.Serialize(list);//方法2 转为 Json
}
/// <summary>
/// 执行SQL获取DataTable
/// </summary>
/// <param name="StrSQL"></param>
/// <returns></returns>
private static DataTable getDataTable(string StrSQL)
{
DataTable dt = new DataTable();
try
{
using (SqlConnection cn = new SqlConnection("context connection=true"))
{
using (SqlDataAdapter da = new SqlDataAdapter(StrSQL, cn))
{
DataSet ds = new DataSet();
da.Fill(ds, "tab");
dt = ds.Tables["tab"];
}
}
}
catch (Exception ex)
{
throw;
}
return dt;
}
方法一:DataTable转Json
/// <summary>
/// DataTable转Json
/// </summary>
/// <param name="table"></param>
/// <returns></returns>
public static string DataTable2Json(DataTable table)
{
var JsonString = new StringBuilder();
if (table.Rows.Count > )
{
JsonString.Append("[");
for (int i = ; i < table.Rows.Count; i++)
{
JsonString.Append("{");
for (int j = ; j < table.Columns.Count; j++)
{
object ValueNull = table.Rows[i][j];
if (ValueNull == DBNull.Value)
{
JsonString.Append("\"" + table.Columns[j].ColumnName.ToString() + "\":null" + ((j < table.Columns.Count - ) ? "," : ""));
}
else
{
string Value = table.Rows[i][j].ToString();
if (table.Columns[j].DataType == typeof(string) || table.Columns[j].DataType == typeof(DateTime) || table.Columns[j].DataType == typeof(Guid))
{
JsonString.Append("\"" + table.Columns[j].ColumnName.ToString() + "\":" + "\"" + Value + "\"" + ((j < table.Columns.Count - ) ? "," : ""));
}
else
{
if (table.Columns[j].DataType == typeof(bool)) Value = Value.ToLower();
JsonString.Append("\"" + table.Columns[j].ColumnName.ToString() + "\":" + Value + ((j < table.Columns.Count - ) ? "," : ""));
}
} }
JsonString.Append("}" + ((i < table.Rows.Count - ) ? "," : ""));
}
JsonString.Append("]");
}
return JsonString.ToString();
}
方法二: 开源MiniJSON类解析Json字符串
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text; namespace SQLClr
{
/// <summary>
/// This class encodes and decodes JSON strings.
/// Spec. details, see http://www.json.org/
///
/// JSON uses Arrays and Objects. These correspond here to the datatypes IList and IDictionary.
/// All numbers are parsed to doubles.
/// </summary>
public static class Json
{
/// <summary>
/// Parses the string json into a value
/// </summary>
/// <param name="json">A JSON string.</param>
/// <returns>An List<object>, a Dictionary<string, object>, a double, an integer,a string, null, true, or false</returns>
//反序列化
public static object Deserialize(string json)
{
// save the string for debug information
if (json == null)
{
return null;
} return Parser.Parse(json);
}
//阻止其他类从该类继承
sealed class Parser : IDisposable
{
const string WORD_BREAK = "{}[],:\""; public static bool IsWordBreak(char c)
{
// 如果 c 是空白,则为 true;否则,为 false;报告指定 Unicode 字符在此字符串中的第一个匹配项的索引。
return Char.IsWhiteSpace(c) || WORD_BREAK.IndexOf(c) != -;
} enum TOKEN
{
NONE,
CURLY_OPEN,
CURLY_CLOSE,
SQUARED_OPEN,
SQUARED_CLOSE,
COLON,
COMMA,
STRING,
NUMBER,
TRUE,
FALSE,
NULL
};
// 实现从字符串进行读取的 System.IO.TextReader。
StringReader json; Parser(string jsonString)
{
json = new StringReader(jsonString);
} public static object Parse(string jsonString)
{
using (var instance = new Parser(jsonString))
{
return instance.ParseValue();
}
}
//释放
public void Dispose()
{
json.Dispose();
json = null;
} Dictionary<string, object> ParseObject()
{
Dictionary<string, object> table = new Dictionary<string, object>(); // ditch opening brace
json.Read(); // {
while (true)
{
switch (NextToken)
{
case TOKEN.NONE:
return null;
case TOKEN.COMMA:
continue;
case TOKEN.CURLY_CLOSE:
return table;
default:
// name
string name = ParseString();
if (name == null)
{
return null;
} // :
if (NextToken != TOKEN.COLON)
{
return null;
}
// ditch the colon
json.Read(); // value
table[name] = ParseValue();
break;
}
}
} List<object> ParseArray()
{
List<object> array = new List<object>(); // ditch opening bracket
json.Read(); // [
bool parsing = true;
while (parsing)
{
TOKEN nextToken = NextToken; switch (nextToken)
{
case TOKEN.NONE:
return null;
case TOKEN.COMMA:
continue;
case TOKEN.SQUARED_CLOSE:
parsing = false;
break;
default:
object value = ParseByToken(nextToken); array.Add(value);
break;
}
} return array;
} object ParseValue()
{
TOKEN nextToken = NextToken;
return ParseByToken(nextToken);
} object ParseByToken(TOKEN token)
{
switch (token)
{
case TOKEN.STRING:
return ParseString();
case TOKEN.NUMBER:
return ParseNumber();
case TOKEN.CURLY_OPEN:
return ParseObject();
case TOKEN.SQUARED_OPEN:
return ParseArray();
case TOKEN.TRUE:
return true;
case TOKEN.FALSE:
return false;
case TOKEN.NULL:
return null;
default:
return null;
}
} string ParseString()
{
StringBuilder s = new StringBuilder();
char c; // ditch opening quote
json.Read(); bool parsing = true;
while (parsing)
{ if (json.Peek() == -)
{
parsing = false;
break;
} c = NextChar;
switch (c)
{
case '"':
parsing = false;
break;
case '\\':
if (json.Peek() == -)
{
parsing = false;
break;
} c = NextChar;
switch (c)
{
case '"':
case '\\':
case '/':
s.Append(c);
break;
case 'b':
s.Append('\b');
break;
case 'f':
s.Append('\f');
break;
case 'n':
s.Append('\n');
break;
case 'r':
s.Append('\r');
break;
case 't':
s.Append('\t');
break;
case 'u':
var hex = new char[]; for (int i = ; i < ; i++)
{
hex[i] = NextChar;
} s.Append((char)Convert.ToInt32(new string(hex), ));
break;
}
break;
default:
s.Append(c);
break;
}
} return s.ToString();
} object ParseNumber()
{
string number = NextWord;
// 摘要:
// 报告指定 Unicode 字符在此字符串中的第一个匹配项的索引。
//
// 参数:
// value:
// 要查找的 Unicode 字符。
//
// 返回结果:
// 如果找到该字符,则为 value 的从零开始的索引位置;如果未找到,则为 -1。
if (number.IndexOf('.') == -)
{
long parsedInt;
// 将数字的字符串表示形式转换为它的等效 64 位有符号整数。一个指示转换是否成功的返回值。
Int64.TryParse(number, out parsedInt);
return parsedInt;
} double parsedDouble;
Double.TryParse(number, out parsedDouble);
return parsedDouble;
}
//
void EatWhitespace()
{
//指示指定字符串中位于指定位置处的字符是否属于空白类别。
while (Char.IsWhiteSpace(PeekChar))
{
json.Read();
//摘要:
// 返回下一个可用的字符,但不使用它。
//
// 返回结果:
// 表示下一个要读取的字符的整数,或者,如果没有更多的可用字符或该流不支持查找,则为 -1。
if (json.Peek() == -)
{
break;
}
}
} char PeekChar
{
get
{
// 读取输入字符串中的下一个字符并将该字符的位置提升一个字符。
//
// 返回结果:
// 基础字符串中的下一个字符,或者如果没有更多的可用字符,则为 -1。
return Convert.ToChar(json.Peek());
}
} char NextChar
{
get
{
return Convert.ToChar(json.Read());
}
} string NextWord
{
get
{
// 表示可变字符字符串。无法继承此类。
StringBuilder word = new StringBuilder(); while (!IsWordBreak(PeekChar))
{
// 摘要:
// 在此实例的结尾追加指定 Unicode 字符的字符串表示形式。
//
// 参数:
// value:
// 要追加的 Unicode 字符。
//
// 返回结果:
// 完成追加操作后对此实例的引用。
word.Append(NextChar);
//下一个字符为空
if (json.Peek() == -)
{
break;
}
}
//
return word.ToString();
}
} TOKEN NextToken
{
get
{
EatWhitespace(); if (json.Peek() == -)
{
return TOKEN.NONE;
} switch (PeekChar)
{
case '{':
return TOKEN.CURLY_OPEN;
case '}':
json.Read();
return TOKEN.CURLY_CLOSE;
case '[':
return TOKEN.SQUARED_OPEN;
case ']':
json.Read();
return TOKEN.SQUARED_CLOSE;
case ',':
json.Read();
return TOKEN.COMMA;
case '"':
return TOKEN.STRING;
case ':':
return TOKEN.COLON;
case '':
case '':
case '':
case '':
case '':
case '':
case '':
case '':
case '':
case '':
case '-':
return TOKEN.NUMBER;
} switch (NextWord)
{
case "false":
return TOKEN.FALSE;
case "true":
return TOKEN.TRUE;
case "null":
return TOKEN.NULL;
} return TOKEN.NONE;
}
}
} /// <summary>
/// Converts a IDictionary / IList object or a simple type (string, int, etc.) into a JSON string
/// </summary>
/// <param name="json">A Dictionary<string, object> / List<object></param>
/// <returns>A JSON encoded string, or null if object 'json' is not serializable</returns>
public static string Serialize(object obj)
{
return Serializer.Serialize(obj);
} sealed class Serializer
{
StringBuilder builder; Serializer()
{
//创建生成器
builder = new StringBuilder();
}
//序列化
public static string Serialize(object obj)
{
var instance = new Serializer(); instance.SerializeValue(obj); return instance.builder.ToString();
}
//类型
void SerializeValue(object value)
{
IList asList;
IDictionary asDict;
string asStr; if (value == null)
{
builder.Append("null");
}
else if ((asStr = value as string) != null)
{
SerializeString(asStr);
}
else if (value is bool)
{
builder.Append((bool)value ? "true" : "false");
}
else if ((asList = value as IList) != null)
{
SerializeArray(asList);
}
else if ((asDict = value as IDictionary) != null)
{
SerializeObject(asDict);
}
else if (value is char)
{
SerializeString(new string((char)value, ));
}
else
{
SerializeOther(value);
}
}
//序列化对象
void SerializeObject(IDictionary obj)
{
bool first = true; builder.Append('{'); foreach (object e in obj.Keys)
{
if (!first)
{
builder.Append(',');
} SerializeString(e.ToString());
builder.Append(':'); SerializeValue(obj[e]); first = false;
} builder.Append('}');
}
// 序列化数组
void SerializeArray(IList anArray)
{
builder.Append('['); bool first = true; foreach (object obj in anArray)
{
if (!first)
{
builder.Append(',');
} SerializeValue(obj); first = false;
} builder.Append(']');
}
//string
void SerializeString(string str)
{
builder.Append('\"'); char[] charArray = str.ToCharArray();
foreach (var c in charArray)
{
switch (c)
{
case '"':
builder.Append("\\\"");
break;
case '\\':
builder.Append("\\\\");
break;
case '\b':
builder.Append("\\b");
break;
case '\f':
builder.Append("\\f");
break;
case '\n':
builder.Append("\\n");
break;
case '\r':
builder.Append("\\r");
break;
case '\t':
builder.Append("\\t");
break;
default:
int codepoint = Convert.ToInt32(c);
if ((codepoint >= ) && (codepoint <= ))
{
builder.Append(c);
}
else
{
//builder.Append("\\u");
//builder.Append(codepoint.ToString("x4"));
builder.Append(c);
}
break;
}
} builder.Append('\"');
}
//其他
void SerializeOther(object value)
{
// NOTE: decimals lose precision during serialization.
// They always have, I'm just letting you know.
// Previously floats and doubles lost precision too.
//注意:小数在序列化过程中丢失精度。
//他们总是有,我只是让你知道。
//以前失去精度和双精度浮点数。
if (value is float)
{
builder.Append(((float)value).ToString("R"));
}
else if (value is int
|| value is uint
|| value is long
|| value is sbyte
|| value is byte
|| value is short
|| value is ushort
|| value is ulong)
{
builder.Append(value);
}
else if (value is double
|| value is decimal)
{
builder.Append(Convert.ToDouble(value).ToString("R"));
}
else
{
SerializeString(value.ToString());
}
}
}
}
}
三.SQL服务器CLR配置(允许SQL调用.net程序)
sp_configure 'show advanced options', 1;
RECONFIGURE WITH override
GO
sp_configure 'clr enabled', 1;
RECONFIGURE WITH override
GO
Sp_changedbowner 'sa',true --sa改为当前登入用户名
alter database [dbname] set trustworthy on --bbname 改为自己的库名
四.注册 CLR 程序集
create ASSEMBLY SQLfunctionAssembly
FROM 'D:\SQLClr.dll' --改为自己C#写的dll路径填写
WITH PERMISSION_SET = UNSAFE;
创建的.net程序集数据会写入下表:
select * from sys.assemblies
select * from sys.assembly_files
五.创建标量函数
create FUNCTION [dbo].[ExecSQL2Json](@StrSQL [nvarchar](max))
RETURNS [nvarchar](max) WITH EXECUTE AS CALLER
AS
EXTERNAL NAME [SQLfunctionAssembly].[SQLClr.SQLfunction].[ExecSQL2Json]
六.测试DataTable转Json函数
DECLARE @SQL VARCHAR(MAX)
SET @SQL = 'SELECT TechName,ItemName,ItemPara
FROM FP_EMS_DB.dbo.V_ppegeneral
WHERE pdctno = ''2V011Z30A4'' AND TechNo = ''CC_01'' ORDER BY ItemNo '
SELECT dbo.ExecSQL2Json(@SQL)
运行后结果
七.小结
采用CLR方式写SQL SERVER函数转为json字符串,那么只要传入一段SQL语句就可以转为Json字符串,是不是很方便,但这种作法在实际应用中作用不太大,因为业务系统现在基本采用ORM 对象关系映射模型开发,数据库表映射成对象,直接操作的对象,然而对象转为json放在应用程序端转换是及为方便的,在这里只开拓一种新思路在数据库中实现转json的方法。
PCB MS SQL 标量函数(CLR) 实现DataTable转Json方法的更多相关文章
- PCB MS SQL 标量函数(CLR) 实现DataTable转HTML的方法
一.准备需转为HMLT字符串的DataTable数据 在数据库中执行一段SQL返回的数据 需转换后的HTML的文本 <html ><head></head>< ...
- PCB MS SQL 标量函数(CLR) 实现Socket发送消息
在PCB业务系统中,数据库中的数据总是被应用端主动连接数据库并操作数据,是否想过可以让数据库主动的将数据推送出去呢! 答应其实是可以的.比如有这样的应用场景! 当SQL SERVER数据库满足某个条件 ...
- PCB MS SQL 标量函数与表值函数(CLR) 实现文件与目录操作
一.C#写SQL SERVER(CLR)实现文件操作 标量函数: 文件移动 ,复制,检测文件存在,写入新文件文本,读取文本,创建目录,删除目录,检测目录是否存在 /// <summary> ...
- PCB MS SQL表值函数与CLR 表值函数 (例:字符串分割转表)
将字符串分割为表表经常用到,这里 SQL表值函数与CLR 表值函数,两种实现方法例出来如下: SELECT * FROM FP_EMSDB_PUB.dbo.SqlSplit('/','1oz/1.5 ...
- SQL标量函数
调用 MS SQL 标量值函数,应该在函数前面加上 "dbo.",否则会报 “不是可以识别的 内置函数名称”错误.例如 DECLARE @WhichDB TINYINT; ...
- MS SQL自定义函数IsPositiveInteger MS SQL自定义函数IsNumeric 水晶报表使用IEnumerable<T>数据源
MS SQL自定义函数IsPositiveInteger 判断字符串是否为正整数,0开始的的数字不算. SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON ...
- PCB MS SQL 排序应用---SQL相邻数据区间值求解
其中一篇 博文中有写<PCB MS SQL 排序应用---相邻数据且相同合并处理>此篇有也应相用也同的技巧,实现相邻数据区间值求解 示例: 原数据:处理前 求出区间值:处理后 SQL 代码 ...
- 靠谱的datatable转json方法
今天有之前同事问我要datatable转json的方法,以前自己也弄过,但感觉网上有很多不靠谱的方法.所以自己在博客里记录一个,当然也是网上找的,但是这个靠谱一点,起码可以用不会报错,所以叫他靠谱的d ...
- PCB MS SQL CLR聚合函数(函数作用,调用顺序,调用次数) CLR说明
用CLR写函数:标量函数,表值函数 很好理解,如果用聚合函数则不是那么好理解了, 这里将CLR函数说明一下,其实关键是对聚合函数说明 用CLR写聚合函数关键点,是要理解CLR与SQL是如何进行数据交互 ...
随机推荐
- 01java基础
01.java基础-18/07/09 1.System.out.print();和System.out.println();的区别是什么 System.out.println();打印的时候自带了换行 ...
- Luogu P4016 「 网络流 24 题 」负载平衡问题
吐槽题目难度,这个题建模好像比前两个都要难,但是难度评级却比第二个要低. 解题思路 依旧是考虑如何建模和建立源点汇点.每个点的货物数量到最后都一样的话肯定是等于他们的平均值.用 $num$ 数组存储原 ...
- Kattis - missinggnomesD Missing Gnomes (思路题)
题目: 题意: 给出已经去除了几个数的一个序列,任务是将去除的数字插回去补全这个序列,输出字典序排在第一的那个补全的序列. 例如: 样例输入: 5 3 1 4 2 样例输出: 1 3 4 2 5 思路 ...
- Python学习笔记之map、zip和filter函数
这篇文章主要介绍 Python 中几个常用的内置函数,用好这几个函数可以让自己的代码更加 Pythonnic 哦 1.map map() 将函数 func 作用于序列 seq 的每一个元素,并返回处理 ...
- 搭建一台功能简单的FTP服务器
#vi /etc/sysconfig/network-scripts/ifcfg-eno33554952 #revice network restart #ping www.baidu.com #ip ...
- buf.writeUInt8()函数详解
buf.writeUInt8(value, offset[, noAssert]) value {Number} 需要被写入到 Buffer 的字节 offset {Number} 0 <= o ...
- 安装charles
简介: Charles主要的功能包括: 支持SSL代理.可以截取分析SSL的请求. 支持流量控制.可以模拟慢速网络以及等待时间(latency)较长的请求. 支持AJAX调试.可以自动将json或xm ...
- react入门-----(jsx语法,在react中获取真实的dom节点)
1.jsx语法 var names = ['Alice', 'Emily', 'Kate']; <!-- HTML 语言直接写在 JavaScript 语言之中,不加任何引号,这就是 JSX 的 ...
- Hdu 4864(Task 贪心)(Java实现)
Hdu 4864(Task 贪心) 原题链接 题意:给定n台机器和m个任务,任务和机器都有工作时间值和工作等级值,一个机器只能执行一个任务,且执行任务的条件位机器的两个值都大于等于任务的值,每完成一个 ...
- Linux学习总结(19)——Linux中文本编辑器vim特殊使用方法
1. vim比对功能 在linux的环境下 用于观察两个文件的一致性的时候我们一般用diff这个命令来比对,但是这个命令不能你特别详细的比对出 具体的位置或者行对比.这里就用到了vim的对比功能 vi ...