另類SQL拼接方法

smark發表於2013-08-15

在編寫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是好是壞就沒有一個標準,相對一些人來說也許方便,但也有可能覺得這簡值一塌糊塗:)看自己喜好。

相關文章