我正在做动态报告系统。对于前端我使用Asp.net和oracle作为后端。项目要求是,用户可以在TextBox中编写查询,并在点击 WHERE 关键字后的查询按钮时将所有参数拆分。拆分将根据模式工作,在查询中找到( AND | OR | ,)。
例如: -
select * from EmpInfo where age >= 40, active='A' and rownum < 15
结果将
age >= 40
active='A'
rownum < 15
但是,如果我在之后使用子查询,那么也将遵循相同的模式
例如: -
select * from EmpInfo where age in (select age from Emp_pns where age >= 60 ), active='A' and rownum < 15
结果将
age >= 60
active='A'
rownum < 15
这是我的示例代码,我尽我所能,但我没有得到完美的解决方案。
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim query As String = TextBox1.Text.ToLower
getParameter(query)
For i As Integer = 0 To ListBox2.Items.Count - 1
ListBox1.Items.Add(ListBox2.Items(i).Text)
Next
End Sub
Public Sub getParameter(ByVal argument As String)
Dim query As String = argument
Static Dim tempString As String
If query.Contains("order by") Or query.Contains("group by") Then
Dim mtch As Match = Regex.Match(query, "(?<=where)(.*)(?=order by|group by)")
Dim mtchString As String = mtch.Groups(1).Value
tempString = mtchString
If mtchString.Length >= 1 Then
Dim bindlist As String() = Regex.Split(mtchString, " and | or |,")
ListBox1.DataSource = bindlist
ListBox1.DataBind()
getParameter(tempString)
End If
Else
Dim mtch As Match = Regex.Match(query, "(?<=where)(.*)")
Dim mtchString As String = mtch.Groups(1).Value
Dim bindlist As String() = Regex.Split(s, " and | or |,")
ListBox2.DataSource = bindlist
ListBox2.DataBind()
End If
End Sub
答案 0 :(得分:1)
Regex
或Split
可为明确定义的模式提供准确的效果;您正在寻找的模式对于那些方法而言过于复杂(所需的实现将太困难,并且在任何情况下都太严格)。这种复杂的问题应该依靠字符串分析来解决。使用输入字符串(或等效字符串)提供预期结果的示例代码:
Public Class Form1
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim inputString As String = "select * from EmpInfo where age in (select age from Emp_pns where age >= 60 ), active='A' and rownum < 15"
Dim whereString As String = inputString.Substring(inputString.ToLower().IndexOf("where") + "where".Length, inputString.Length - (inputString.ToLower().IndexOf("where") + "where".Length)).Trim()
Dim allParts(whereString.Length + 2) As String
Dim allPartsCount As Integer = 0
Dim done As Boolean = False
If (whereString.Contains("(") And whereString.Contains(")")) Then
If (whereString.Split("(").Length = whereString.Split(")").Length) Then
done = True
Dim remString = whereString
Do
Dim temp = inBrackets(remString)
If (temp(0).Trim().Length > 0) Then
allPartsCount = allPartsCount + 1
allParts(allPartsCount) = temp(0)
End If
If (temp(1).Trim().Length > 0) Then
remString = temp(1)
Else
Exit Do
End If
Loop While (remString.Trim().Length > 0)
End If
End If
If (Not done) Then
'Standard treatment
End If
End Sub
Private Function inBrackets(inputString As String) As String()
Dim outStrings(1) As String
Dim openBracket As Boolean = False
Dim count As Integer = -1
Do
count = count + 1
outStrings(0) = outStrings(0) & inputString.Substring(count, 1)
If (inputString.Substring(count, 1) = "(") Then
openBracket = Not openBracket
ElseIf (openBracket And inputString.Substring(count, 1) = ")") Then
openBracket = False
End If
If (Not openBracket) Then
If (inputString.Substring(count, 1) = ",") Then
Exit Do
ElseIf (count >= "and".Length AndAlso inputString.ToLower().Substring(count - "and".Length, "and".Length) = "and") Then
Exit Do
ElseIf (count >= "or".Length AndAlso inputString.ToLower().Substring(count - "or".Length, "or".Length) = "or") Then
Exit Do
End If
End If
Loop While (count < inputString.Length - 1)
If (outStrings(0).Trim().Length > 0) Then
outStrings(1) = inputString.Substring(outStrings(0).Length, inputString.Length - outStrings(0).Length)
End If
Return outStrings
End Function
End Class
此代码显示了针对此类情况的典型方法:您需要根据需要调整/扩展它以满足您的确切要求。它分析了只有支架的情况(平行数量的开/关括号)。这个想法很简单:逐个字符地分析给定的字符串,直到找到你正在寻找的“分隔符”之一,并另外考虑一下:如果找到一个开括号,它将不会退出循环直到找到相应的结束一。执行分析的函数返回一个包含当前位和剩余字符串的数组,以便主循环可以继续分析。在任何情况下你都应该进行进一步的扩展:括号变化(例如方括号),占嵌套括号(此代码只占“括号的一个级别”)等等。