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(@"'", @"\'"); } } } }