簡體   English   中英

從VB.NET構建動態SQL查詢

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM