using System.Collections.Generic;
using System.Text;
using System;
using System.Linq;
using System.Text.RegularExpressions;
namespace JiaZhiQuan.Common.Utils.Extend {
public static class BuildSqlExtensions {
///
/// 生成更新sql
///
/// 数据
/// 表名
/// 唯一字段,多个字段逗号隔开
/// 字段值为null时是否覆盖,默认覆盖
///
///
public static string BuildBatchUpdatesql(this IEnumerable source, string tableName,
string uniqueFields, bool cover = true) {
if (source.Count() == 0) return string.Empty;
List keyFields = uniqueFields?.Split(',').Where(x => !string.IsNullOrWhiteSpace(x)).ToList();
if (keyFields == null || keyFields.Count() == 0) throw new Exception("唯一字段列表不能为空");
//考虑怎么写更优雅
IEnumerable> check = source.Where(x => x != null).Select(
x => (IDictionary)ExpandoUtils.ConvertToDynamic(x));
foreach (var item in check) {
foreach (var key in keyFields) {
if (!item.ContainsKey(key)) throw new Exception("唯一字段不在数据字段中,不能创建更新sql");
if (item[key] == null) throw new Exception("唯一字段对应的数据不能为空,不能创建更新sql");
}
}
//根据唯一字段去重数据
var data = check.Distinct(x => string.Join(",", keyFields.Select(y => x[y])));
var fields = data.First().Keys;
var cols = fields.Where(x => !keyFields.Contains(x));
if (0 == cols.Count()) {
return string.Empty;
}
StringBuilder sb = new StringBuilder("update ");
sb.Append(tableName).Append(" t inner join ");
sb.Append(BuildForeachStr(data, " union all ", t => {
return BuildForeachStr(fields, ",",
k => (null == t[k] ? "null" : "'" + EscapeSql(t[k]) + "'") + " " + k,
"select ", null);
}, "(", ")"));
sb.Append(" a on ");
sb.Append(BuildForeachStr(keyFields, " and ", t => $"t.{t}=a.{t}"));
sb.Append(" set ");
//是否覆盖
if (cover) {
sb.Append(BuildForeachStr(cols, ",", t => $"t.{t}=a.{t}"));
} else {
sb.Append(BuildForeachStr(cols, ",",
t => $"t.{t}=case when a.{t} is null then t.{t} else a.{t} end"));
}
sb.Append(";select row_count();");
return sb.ToString();
}
///
/// 生成插入sql,如果数据在库中存在,则去掉,并且会根据keyFields去重数据
///
/// 数据
/// 表名
/// 唯一字段,多个字段逗号隔开
///
///
public static string BuildBatchInsertsql(this IEnumerable source, string tableName,
string uniqueFields) {
if (source.Count() == 0) return string.Empty;
List keyFields=uniqueFields?.Split(',').Where(x=>!string.IsNullOrWhiteSpace(x)).ToList();
if (keyFields == null || keyFields.Count() == 0) throw new Exception("唯一字段列表不能为空");
//考虑怎么写更优雅
IEnumerable> check = source.Where(x => x != null).Select(
x => (IDictionary)ExpandoUtils.ConvertToDynamic(x));
foreach (var item in check) {
foreach (var key in keyFields) {
if (!item.ContainsKey(key)) throw new Exception("唯一字段不在数据字段中,不能创建插入sql");
if (item[key] == null) throw new Exception("唯一字段对应的数据不能为空,不能创建插入sql");
}
}
//根据唯一字段去重数据
var data = check.Distinct(x => string.Join(",", keyFields.Select(y => x[y])));
var fields = data.First().Keys;
StringBuilder sb = new StringBuilder("insert into " + tableName);
sb.Append(BuildForeachStr(fields, ",", open: "(", close: ")"));
sb.Append(" select a.* from ").Append(BuildForeachStr(data, " union all ", t => {
return BuildForeachStr(fields, ",",
k => (null == t[k] ? "null" : "'" + EscapeSql(t[k]) + "'") + " " + k,
"select ", null);
}, "(", ")a "));
sb.Append($" left join {tableName} t on ");
sb.Append(BuildForeachStr(keyFields, " and ", t => $"t.{t}=a.{t} "));
sb.Append($"where t.{keyFields.First()} is null ;select row_count();");
return sb.ToString();
}
public static string BuildForeachStr(this IEnumerable list,
string split, Func getInfo = null, string open = null, string close = null) {
if (list.Count() == 0) {
return string.Empty;
}
StringBuilder sb = new StringBuilder(" ").Append(open ?? "");
sb.Append(string.Join(split, list.Select(x => getInfo == null ? x.ToString() : getInfo(x))));
sb.Append(close ?? "").Append(" ");
return sb.ToString();
}
private static string EscapeSql(object value) {
if (null == value) return null;
if (value is DateTime time) return time.ToString("yyyy-MM-dd HH:mm:ss");
else {
return value.ToString().Replace(@"\", @"\\").Replace(@"'", @"\'");
}
}
}
}