我們在做多個字段模糊查詢時,是不是覺得非常麻煩?比如我要模糊查詢某表多個字段存在某數據時,如下
select * from table where a like '%key%' or b like '%key%' or c like '%key%'..........
上面的語句不但長,而且寫起來好麻煩。我們是不是有更好的辦法呢?
答案是肯定的。我們可以這樣寫:
SELECT * FROM table where CONCAT(a,b,c......) like '%key%'
這樣不就顯得很簡單,很簡潔?
如果存在N個字段,而你又不情願一個一個的手寫每個字段,你又該如何呢?
我的思路是這樣的,首先讀取某表所有的字段,比如讀出來某表含有a,b,c,d....等字段(select name from syscolumns where id=object_id(TableName)語句可以讀取某表字段信息),
然后將這些字段拼接到concat中,拼接的結果像這樣的:SELECT * FROM table where CONCAT(a,b,c......) like '%key%'
這樣一來,簡單了很多,減少了繁瑣不必要的sql拼接操作。
本人為了這個問題,也做了一些程序demo,以便大家互相學習。
0.列名實體類
public class SysColumns { public string Key { get; set; } public string ColumnName { get; set; } }
1,枚舉查詢倒序,排序
public enum OrderType { /// <summary> /// 倒序 /// </summary> Desc = 0, /// <summary> /// 順序 /// </summary> ASC = 1, }
2.分頁實體類
public class Paging { /// <summary> /// 總數 /// </summary> public int TotalItems { get; set; } /// <summary> /// 每頁多少條 /// </summary> public int ItemsPerPage { get; set; } /// <summary> /// 當前頁 /// </summary> public int CurrentPage { get; set; } /// <summary> /// 總共多少頁 /// </summary> public int TotalPages { get { return (int)Math.Ceiling((decimal)TotalItems / ItemsPerPage); } }
3.帥選條件
public class SelectField { /// <summary> /// 表名 /// </summary> public string TableName { get; set; } /// <summary> /// 查找的關鍵字 /// </summary> public string Key { get; set; } /// <summary> /// 其他條件 /// </summary> public string OtherWhere { get; set; } /// <summary> /// 排序字段 /// </summary> public string OrderField { get; set; } /// <summary> /// 排序類型 /// </summary> public string OrderType { get; set; } }
4.封裝的方法
public class SelectForMoreField<T> where T : new() { private string conn = null; /// <summary> /// 連接字符串 /// </summary> public SelectForMoreField() { conn = ConfigurationManager.ConnectionStrings["Conn"].ConnectionString; } /// <summary> /// 判斷SqlDataReader是否存在某列 /// </summary> /// <param name="dr">SqlDataReader</param> /// <param name="columnName">列名</param> /// <returns></returns> private bool readerExists(SqlDataReader dr, string columnName) { dr.GetSchemaTable().DefaultView.RowFilter = "ColumnName= '" + columnName + "'"; return (dr.GetSchemaTable().DefaultView.Count > 0); } /// <summary> /// 帶有分頁的多字段查詢 /// </summary> /// <param name="TableName">表名</param> /// <param name="KeyWord">查詢關鍵字</param> /// <param name="page">當前頁號</param> /// <param name="take">每頁顯示行數 </param> /// <returns></returns> public IList<T> QueryForMoreField(SelectField field, Paging page) { IList<SysColumns> ls = GetTableField(field.TableName); StringBuilder sb = new StringBuilder(); sb.Append("SELECT [t1].* FROM (SELECT ROW_NUMBER() OVER (ORDER BY [t0]." + field.OrderField + " " + field.OrderType + ") AS [ROW_NUMBER], [t0].* FROM "); sb.Append(field.TableName); sb.Append(" AS [t0]"); sb.Append(" where "); int i = 0; sb.Append("CONCAT("); foreach (SysColumns sysc in ls) { sb.Append(" cast(" + sysc.ColumnName + " as nvarchar(max)),"); if ((ls.Count - 1) == i) { sb.Append(" cast(" + sysc.ColumnName + " as nvarchar(max)))"); sb.Append(" like '%" + field.Key + "%'"); } i++; } if (!String.IsNullOrEmpty(field.OtherWhere)) { sb.Append("and "); sb.Append(field.OtherWhere); } sb.Append(" ) AS [t1] "); sb.Append("WHERE [t1].[ROW_NUMBER] BETWEEN ((" + page.CurrentPage + "*" + page.ItemsPerPage + ") - (" + page.ItemsPerPage + " -1)) AND (" + page.CurrentPage + "*" + page.ItemsPerPage + ")"); sb.Append("ORDER BY [t1].[ROW_NUMBER]"); string sql = sb.ToString(); IList<T> list; Type type = typeof(T); string tempName = string.Empty; using (SqlDataReader reader = SqlHelper.ExecuteReader(conn, CommandType.Text, sql)) { if (reader.HasRows) { list = new List<T>(); while (reader.Read()) { T t = new T(); PropertyInfo[] propertys = t.GetType().GetProperties(); foreach (PropertyInfo pi in propertys) { tempName = pi.Name; if (readerExists(reader, tempName)) { if (!pi.CanWrite) { continue; } var value = reader[tempName]; if (value != DBNull.Value) { pi.SetValue(t, value, null); } } } list.Add(t); } sb = null; sql = null; conn = null; return list; } } return null; } /// <summary> /// 簡單的條件查詢 /// </summary> /// <param name="field">查詢條件</param> /// <returns></returns> public IList<T> QueryForMoreField(SelectField field) { IList<SysColumns> ls = GetTableField(field.TableName); StringBuilder sb = new StringBuilder(); sb.Append("SELECT * FROM " + field.TableName); sb.Append(" where "); int i = 0; sb.Append("CONCAT("); foreach (SysColumns sysc in ls) { sb.Append(" cast(" + sysc.ColumnName + " as nvarchar(max)),"); if ((ls.Count - 1) == i) { sb.Append(" cast(" + sysc.ColumnName + " as nvarchar(max)))"); sb.Append(" like '%" + field.Key + "%'"); } i++; } string sql = sb.ToString(); IList<T> list; Type type = typeof(T); string tempName = string.Empty; using (SqlDataReader reader = SqlHelper.ExecuteReader(conn, CommandType.Text, sql)) { if (reader.HasRows) { list = new List<T>(); while (reader.Read()) { T t = new T(); PropertyInfo[] propertys = t.GetType().GetProperties(); foreach (PropertyInfo pi in propertys) { tempName = pi.Name; if (readerExists(reader, tempName)) { if (!pi.CanWrite) { continue; } var value = reader[tempName]; if (value != DBNull.Value) { pi.SetValue(t, value, null); } } } list.Add(t); } sb = null; sql = null; conn = null; return list; } } return null; } /// <summary> /// 獲取表中所有字段 /// </summary> /// <param name="TableName">表名</param> /// <returns></returns> public IList<SysColumns> GetTableField(string TableName) { SqlDataReader read = SqlHelper.ExecuteReader(conn, CommandType.Text, "select name from syscolumns where id=object_id('" + TableName + "')"); IList<SysColumns> ls = new List<SysColumns>(); while (read.Read()) { SysColumns co = new SysColumns(); co.Key = Guid.NewGuid().ToString().Replace("-", ""); co.ColumnName = read.GetString(0); ls.Add(co); } read.Close(); return ls; } }
5.調用演示
class Program { // static string conn = ConfigurationManager.ConnectionStrings["Conn"].ConnectionString; static void Main(string[] args) { SelectForMoreField<Product> ls = new SelectForMoreField<Product>(); SelectField field = new SelectField(); field.TableName = "Product"; field.Key = "1"; field.OtherWhere = "Id > 12281"; int y = (int)OrderType.Desc; field.OrderType = ((OrderType)y).ToString(); field.OrderField = "Id"; Paging page = new Paging(); page.CurrentPage = 1; page.ItemsPerPage = 10; IList<Product> data = ls.QueryForMoreField(field, page); foreach (var d in data) { Console.WriteLine("ID:"+d.Id+" Name"+d.Name); } }
注:這只是個簡陋粗糙的實現而已,后續精簡程序,拓展Linq 這類方法,程序無法提供下載,因為不知道博客園編輯器如何上傳,見諒。
注意:本程序支持sql2008 R2以上的數據庫