我正在研究用户输入的验证逻辑,它非常接近sql where子句。
在页面上,用户可以从下拉列表的组合中进行选择(其中' - '字符代表最后一个句子中的空白字符):
DropDown1 DropDown2 DropDown3 DropDown4 DropDown5 DropDown6
- - - - - -
( SomeCriteria = Value ) AND
<> OR
不幸的是我对如何验证这个子句没有任何硬性要求,除了它应该'表现得像sql where子句':(
应该通过验证的一些
(Criteria = Value)
(criteria1 = Value1 OR Criteria2 <> value2)
(criteria1 = value1) AND (Criteria2 = value2)
(criteria1 = value1) OR (Criteria2 = value2 AND criteria3 = value3)
一些应该验证失败的人:
)Criteria = value) (first character is not '(' )
(Criteria = value( (last character is not ')' )
((Criteria = value) (# of '(' does not match # of ')' )
(Criteria = Value (AND Criteria1 = value1)) ( 'AND' and 'OR' should not be immediately preceded or followed by a '(' or ')' character.
任何有关编写正则表达式以验证这些选择的帮助都将非常感激。在探讨之后,我看到其他人谈到sql解析器,这对于这个“受限制的”where子句来说是更好的解决方案吗?
答案 0 :(得分:0)
注意:对于用户需要发表如下语句的情况:(A == B AND B != C OR (A == B OR (A == C)))
,只有在左侧括号下拉列表和右侧为用户提供更多选项时,您的解决方案才有效括号下拉列表。左括号下拉列表应包含以下选项:'(', '((', '(((', '(((('
,您可以在连续4个左括号中将其封闭。右括号下拉列表应该看起来一样。
您可以将您的下拉列表放在Repeater中,以便.Net为每个下拉列表分配一个唯一的ID。
验证码:
// this will keep track of left brackets that have not been closed
int numUnclosedLeftBrackets = 0;
// changing dropdown instance names for clarity
ddlLeftBracket == DropDown1;
ddlCriteria == DropDown2;
ddlConOperator == DropDown3;
ddlValue == DropDown4;
ddlRightBracket = DropDown5;
ddlExtension == DropDown6;
Boolean isValidStmt = false;
Boolean areValidBrackets = false;
Boolean addAnotherStmt = false;
// conditional operator dropdown cannot be blank
if(ddlConOperator.SelectedIndex > 0)
{
if(ddlConOperator.SelectedValue == "=" && ddlCriteria.SelectedValue == ddlValue.SelectedValue)
isValidStmt = true;
if(ddlConOperator.SelectedValue == "<>" && ddlCriteria.SelectedValue != ddlValue.SelectedValue)
isValidStmt = true;
// check if both left and right brackets exist, or if both do not exist.
if((ddlLeftBracket.SelectedIndex == 0 && ddlRightBracket.SelectedIndex == 0) ||
(ddlLeftBracket.SelectedIndex > 0 && ddlRightBracket.SelectedIndex > 0))
areValidBrackets = true;
// check if AND, or OR is attached
if(ddlExtension.SelectedIndex != 0)
{
addAnotherStmt = true;
// check if brackets need to be validated now that the where clause will continue on
if(!areValidBrackets)
{
// check if left bracket but no right bracket
if(ddlLeftBracket.SelectedIndex > 0 && ddlRightBracket.SelectedIndex == 0)
{
areValidBrackets = true;
numUnclosedLeftBrackets += ddlLeftBracket.SelectedIndex;
}
// check if right bracket but no left bracket
if(ddlLeftBracket.SelectedIndex == 0 && ddlRightBracket.SelectedIndex > 0)
{
// check if left bracket needs closing in a previous value/criteria row and make sure user is not trying to add more right closing brackets than allowed
if(numUnclosedLeftBrackets > 0 && (numUnclosedLeftBrackets - ddlRightBracket.SelectedIndex) > -1)
{
areValidBrackets = true;
numUnclosedLeftBrackets -= ddlRightBracket.SelectedIndex;
}
}
}
}
else
{
// Since the user has not selected AND or OR, check that there are no unclosed left brackets remaining
if(numUnclosedLeftBrackets > 0)
areValidBrackets = false;
}
}
if(!areValidBrackets)
// brackets not valid
else
if(!isValidStmt)
// not a valid statement
else
if(addAnotherStmt)
// create a new row
else
// finished and valid - allow saving valid 'WHERE clause' string
您可以将其设置为启用最新的转发器行并禁用所有先前的行,从而强制用户删除每个最新的行,直到他们要编辑的行变为启用状态。这简化了验证,b / c然后您只关心最近的行,知道所有先前的行都经过验证。当最新的行有效时,将整个字符串作为SQL WHERE子句运行是安全的。
注意:如果您像我建议的那样锁定以前的行,那么当用户删除最近的行时,您必须检查numUnclosedLeftBrackets
的值,这可能需要稍微不同的方法,例如:为包含未关闭的左括号的每一行存储转发器行索引。
答案 1 :(得分:0)
我偶然发现自己的一个解决方案,我认为可能对其他人有用,因为我见过其他有类似问题的人......
如果您的子句的格式类似于sql where子句,则可以使用以下过程对数据库进行调用来验证它:
SET PARSE ONLY
SELECT 1
FROM sys.objects
WHERE [user generated clause]
如果没有任何错误,你有一个有效的sql where子句......
希望这有助于某人。