我們在做多個字段模糊查詢時,是不是覺得非常麻煩?比如我要模糊查詢某表多個字段存在某數據時,如下
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以上的數據庫
