[英]Building a dynamic sql query from VB.NET
我已經搜索並找到了答案,但是找不到。 我有一個選中的列表框,用戶將選擇他們在計算機上遇到的問題。 在選中的列表框中,您將看到諸如...,緩慢,病毒,硬盤驅動器損壞...之類的信息,根據他們選擇的內容,我將告訴他們估計的維修成本。 目前這是我構建查詢的方式:
Dim mIssues As String = ""
For i = 0 To lstIssues.CheckedItemsCount - 1
If mIssues = "" Then
mIssues = String.Format("IssueName = '{0}'", lstIssues.CheckedItems(i))
Else
mIssues = String.Format("{0} OR IssueName = '{1}'", mIssues, lstIssues.CheckedItems(i))
End If
Next
上面的代碼將查看他們選擇了多少問題。 如果他們只選擇一個問題,那么它將返回如下字符串:IssueName ='無論他們選擇什么'。 如果他們選擇了多個問題,則將返回如下字符串:IssueName ='無論他們選擇了什么'或IssueName ='第二個選擇'。 因此,基本上,如果所有選擇均選擇多個問題,我將在所有選擇之間添加一個OR。 我這樣做是為了在查詢中動態構建where子句。
這是我的查詢:
Dim mySQL As String = "SELECT IssueID, IssueTypeID, IssueName, IssueDescription, " _
& "CustomerID, IndividualCost, GroupCost, Active, ChargeType " _
& "FROM (SELECT IssueID, IssueTypeID, IssueName, IssueDescription, " _
& "CustomerID, IndividualCost, GroupCost, Active, ChargeType " _
& "FROM(cfg_Issues) " _
& "WHERE " & mIssues & " " _
& "GROUP BY IssueID, IssueTypeID, IssueName, IssueDescription, CustomerID, " _
& "IndividualCost, GroupCost, Active) " _
& "ORDER BY IndividualCost DESC, GroupCost ASC;"
正如您可以看到我的where子句來自第一部分代碼。 我的問題是,有沒有更好的方法來做到這一點? 我知道必須有一個更好的方法來構建動態where子句查詢,我想看看如何。 感謝您提供的任何指導。
這里的第一個問題是SQL注入的大門。 我希望你能完全控制在lstIssues
插入的lstIssues
因為在為數據庫引擎創建命令時,字符串連接總是一件危險的事情。
使用StringBuilder類實例可以減少代碼,當有許多元素在字符串中連接時,它會有所幫助
Dim mIssues As StringBuilder = new StringBuilder()
For i = 0 To lstIssues.CheckedItemsCount - 1
mIssues.AppendFormat("IssueName = '{0}' OR ", lstIssues.CheckedItems(i))
Next
' I suppose that you have a check in place to not allow to run this query if you don't have at
' least one element checked in the list (if not the WHERE condition will fail)'
mIssues.Length -= 4
這將刪除循環中的IF,並且為了刪除額外的OR,在退出循環時足以減少StringBuilder實例的長度。
在您的查詢文本中,StringBuilder可以使用返回其內部字符串
mIssues.ToString
您也可以嘗試將IN sql子句與此類代碼一起使用
Dim mIssues As StringBuilder = new StringBuilder()
For i = 0 To lstIssues.CheckedItemsCount - 1
mIssues.AppendFormat("'{0}', ", lstIssues.CheckedItems(i))
Next
' I suppose that you have a check in place to not allow this query if you don't have at
' least one element checked in the list (if not the WHERE condition will fail)'
mIssues.Length -= 2
mIssues.Insert(0, "IssueName IN(")
mIssues.Append(")")
我一直希望讓SQL為我做所有的動態工作。 正如許多人所展示的那樣,優點是你的所有SQL都是在幕后完成的,並且更安全,無法注入。 邪惡的人實際上有多種方法可以(我寧願不解釋黑客本身的詳細信息),將自己的SQL注入您的形式並可能造成很多損害。
這是動態SQL背后的基本前提(代碼可能不准確):您創建一個基本上編寫SQL代碼然后執行它的存儲過程
CREATE PROCEDURE p_getIssues
as
/*This is where you will place all your input parameters like this
@paramname1 datatype,
@paramname1 datatype,
@mIssues varchar(max) example: virus = 1 and slowcomp = 1
*/
BEGIN
DECLARE @SQL as varchar(max)
SET @SQL = 'SELECT * FROM tablename where ' + @mIssues
EXEC (@SQL)
END
注意:如果您必須調試存儲過程...,請注釋掉EXEC並添加一個PRINT(@SQL),您可以看到該存儲過程將運行哪種SQL。
如果你必須動態,這總是一個首選的方法。 另外,不建議在VB.NET代碼中使用sql恕我直言,因為從可伸縮性和可更新性的角度來看,如果要添加更多服務,則必須推出新的VB.NET代碼。 相反,您登錄到SQL,您可以進行更改,您就完成了!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.