在編寫SQL的時候經常需要對SQL進行拼接,拼接的方式就是直接String+處理,但這種情況有個不好的地方就是不能對SQL進行引數化處理。下面介紹一種就算基於String +的方式也可以進行SQL引數處理。
常見的SQL拼接
id =3; "select * from orders where employeeid="+id;
這樣存在的問題是相當明顯的就是SQL隱碼攻擊,如果需要引數化那在編寫程式碼的時候就相對多了些工作。下面介紹通過以上的編寫方式自動實現引數化功能。
自動引數化處理
id=3; SQL sql="select * from orders where empoyeeid=@id"; sql = sql +id;
更多實際應用效果
string city = "sdf"; SQL sql = "select * from orders where employeeid=@i"; sql = sql + 3; Output(sql); sql = "select * from order where employeeid in(@p1,@p2)"; sql = sql + 3 + 4; Output(sql); sql = "select * from orders where 1=1"; if (city != null) sql = sql+" and city=@p1" + city; Output(sql);
最終處理引數化的結果是:
SQL:select * from orders where employeeid=@i Name:@i=3 ------------------------------------------- SQL:select * from order where employeeid in(@p1,@p2) Name:@p1=3 Name:@p2=4 ------------------------------------------- SQL:select * from orders where 1=1 and city=@p1 Name:@p1=sdf -------------------------------------------
實現
為了達到以上處理效果針對性實現了一個SQL物件,通過運算子的過載把+運算修改一下。在處理的過程需要對SQL語句和值的處理,首先當一個SQL String進桟的時候先分析一下這個String是否包括引數,如果包括就把引數壓到佇列中,大概程式碼如下:
private void MatchSql(string sql) { MatchCollection matchs = Regex.Matches(sql, "@[a-zA-Z0-9]+"); if (matchs.Count > 0) { foreach (Match item in matchs) { mInputParameters.Enqueue(item.Value); } } }
簡單地一個正則匹配就OK了,把找到的引數壓佇列中。有了這個依據那在向SQL物件再次壓入值的時候就可以判斷引數佇列是否有引數,如果有就壓到SQL引數集裡面,沒有就拼接到SQL語句中。
public static SQL operator +(SQL sql, ValueType value) { if (sql.mInputParameters.Count > 0) { sql.Parameter(sql.mInputParameters.Dequeue(), value); } return sql; } public static SQL operator +(SQL sql, string subsql) { if (sql.mInputParameters.Count > 0) { sql.Parameter(sql.mInputParameters.Dequeue(), subsql); } else sql.AddSql(subsql); return sql; }
這樣一個基於拼接的SQL引數化處理就完成了,以上緊緊是想表達一下運算子過載所帶來的效果,對於這種方式編寫引數化SQL是好是壞就沒有一個標準,相對一些人來說也許方便,但也有可能覺得這簡值一塌糊塗:)看自己喜好。