SqlHelper中IN集合场景下的参数处理
我手頭有個古老的項目,持久層用的是古老的ADO.net。前兩天去昆明旅游,其中的一個景點是云南民族村,通過導游介紹知道了一個古老的民族——基諾族,“基”在這個族內代表舅舅,“基諾”意為“跟在舅舅后邊”,加以引申即為“尊崇舅舅的民族”,很有意思吧,這是我國最后一個被發現并確認下來的少數民族,即第56個民族。 ?項目里的ado.net和基諾族一樣古老。
話說,項目里數據訪問層,好多都是拼的sql,這給sql注入提供了可乘之機,為了系統安全,決定在有限的時間內,將它改成參數化。
其中,有個根據多個訂單號查詢支付單的方法,簽名如下:
public DataTable GetAlipayNotifyRecords(AlipayPaymentStatus status, params string[] trade_no)那么,問題來了,因為sql里有in, 而 in(@no)的方式是行不通的。
怎么辦呢? ?首先想到的是對參數做處理:
public DataTable GetAlipayNotifyRecords(AlipayPaymentStatus status, params string[] trade_no) {string sql = @"select * from T_AlipayNotityRecord where trade_status=@trade_status and trade_no in(@trade_no)";//string inValue = "'" + string.Join("','", trade_no) + "'";//= string.Join(",", trade_no)string inValue = "";trade_no.ToList().ForEach(no => inValue += " union all select '" + no+"'");inValue = inValue.Substring(" union all".Length);List<SqlParameter> paramList = new List<SqlParameter>(){new SqlParameter("@trade_status",status.ToString()), new SqlParameter("@trade_no",inValue),};var ds = SqlHelper.SqlDataSet(ConfigFile.PayCenterConnection, sql, CommandType.Text, paramList.ToArray());if (ds == null || ds.Tables.Count == 0)return null;return ds.Tables[0]; }經測試,無效。經分析可知,sqlhelper會把你參數值當成字符串,不會對其做轉義。所以,不管怎么對參數值處理,都還是一串字符串。
按這樣的原理往下想,只能是將單號分開來傳遞給sql了。那么正好sql的in可以通過如下幾種方式等效實現:
- sql里有臨時表,可以in一個臨時表--這時,可以考慮and trade_no in(select @p1 union all select @p2 union all...)的方式
- 把sql的in集合,轉換為一個用or拼接起來的集合---即,and (trade_no=@p1 or trade_no=@p2 or trade_no=@p3 or...)
如下代碼是按照后者的思路解決了這個問題:
public DataTable GetAlipayNotifyRecords(AlipayPaymentStatus status, params string[] trade_no) {string sql = @"select * from T_AlipayNotityRecord where trade_status=@trade_status and ({0})";List<SqlParameter> paramList = new List<SqlParameter>(){new SqlParameter("@trade_status",status.ToString()), };string sql1 = "";for (int i=0;i<trade_no.Length;i++){sql1 += " or trade_no=@no" + i;paramList.Add(new SqlParameter("@no" + i, trade_no[i]));}sql = string.Format(sql, sql1.Substring(" or ".Length));var ds = SqlHelper.SqlDataSet(ConfigFile.PayCenterConnection, sql, CommandType.Text, paramList.ToArray());if (ds == null || ds.Tables.Count == 0)return null;return ds.Tables[0]; }【結語】無意中從園子里看到一篇文章,不該活著的SqlHelper和DBHelper,很贊!
?
-----2016-12-13 09:39:32
【續】方法總比問題多
今天早上刷牙時,靈光一現,對于昨天的方案,不需要通過借助or或union的方式來更改sql的in了,即,可以直接生成如下的sql語句:
select * from T_AlipayNotityRecord where trade_status=@trade_status and trade_no in(@no0,@no1,...)程序代碼在上面的基礎上稍做處理:
public DataTable GetAlipayNotifyRecords(AlipayPaymentStatus status, params string[] trade_no) {string sql = @"select * from T_AlipayNotityRecord where trade_status=@trade_status and trade_no in({0})";List<SqlParameter> paramList = new List<SqlParameter>() {new SqlParameter("@trade_status",status.ToString()), };string sql1 = "";for (int i = 0; i < trade_no.Length; i++){sql1 += ",@no" + i;paramList.Add(new SqlParameter("@no" + i, trade_no[i]));}sql = string.Format(sql, sql1.Substring(",".Length));var ds = SqlHelper.SqlDataSet(ConfigFile.PayCenterConnection, sql, CommandType.Text, paramList.ToArray());if (ds == null || ds.Tables.Count == 0)return null;return ds.Tables[0]; }這樣子生成的sql就很直觀了。比上面方案的還簡短。
?
轉載于:https://www.cnblogs.com/buguge/p/6165972.html
總結
以上是生活随笔為你收集整理的SqlHelper中IN集合场景下的参数处理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 转!mysql 查询 distinct多
- 下一篇: C++ 编写DLL文件给易语言调用