如何在C#中修正正则,匹配未被WHEN及任意空格前置的EMP_ID?
解决方案:修正正则或使用SQL语法解析器
一、修正正则表达式
原正则(?<!WHEN\s)EMP_ID的问题在于仅能排除WHEN后紧跟单个空格的情况,无法处理多空格、制表符等空白字符,同时未考虑排除WHERE子句中的匹配(如果这是你的需求)。
1. 处理WHEN后任意空白字符
将负向后行断言改为匹配WHEN后跟任意数量的空白字符,同时开启大小写不敏感(SQL关键字不区分大小写):
string pattern = @"(?<!WHEN\s*)EMP_ID"; Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
这样无论WHEN后是1个还是多个空格、制表符,后面的EMP_ID都不会被匹配。
2. 同时排除WHERE子句中的EMP_ID
如果需要同时排除WHERE后的EMP_ID,可以扩展断言:
string pattern = @"(?<!(WHEN|WHERE)\s*)EMP_ID"; Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
3. 边缘情况补充
如果要避免匹配字符串、注释中的EMP_ID,可以进一步扩展正则,但正则处理SQL始终存在局限性,比如无法应对嵌套结构等复杂场景。
二、更可靠的方案:使用SQL语法解析器
正则处理SQL容易遇到各种边缘场景(比如嵌套CASE、字符串中的列名、注释等),推荐使用专业的SQL解析库Microsoft.SqlServer.TransactSql.ScriptDom:
- 安装NuGet包:
Microsoft.SqlServer.TransactSql.ScriptDom - 编写解析代码:
using Microsoft.SqlServer.TransactSql.ScriptDom; public static List<string> GetTargetSelectColumns(string sql) { List<string> targetColumns = new List<string>(); TSql160Parser parser = new TSql160Parser(false); IList<ParseError> parseErrors = new List<ParseError>(); using (StringReader reader = new StringReader(sql)) { TSqlFragment sqlFragment = parser.Parse(reader, out parseErrors); if (parseErrors.Count > 0) { // 此处可添加解析错误的处理逻辑 return targetColumns; } if (sqlFragment is TSqlBatch batch) { foreach (var statement in batch.Statements) { if (statement is SelectStatement selectStmt) { if (selectStmt.QueryExpression is QuerySpecification querySpec) { foreach (var selectElement in querySpec.SelectElements) { if (selectElement is SelectScalarScalarExpression scalarExpr) { if (scalarExpr.Expression is ColumnReferenceExpr columnRef) { // 处理单部分列名(如EMP_ID) if (columnRef.MultiPartIdentifier.Identifiers.Count == 1) { string columnName = columnRef.MultiPartIdentifier.Identifiers[0].Value; if (columnName.Equals("EMP_ID", StringComparison.OrdinalIgnoreCase)) { targetColumns.Add(columnName); } } } } } } } } } } return targetColumns; }
这个方法可以精准识别SELECT列表中的目标列名,完全避免正则的误匹配问题,适合复杂SQL场景。
内容的提问来源于stack exchange,提问作者Walter
相关产品推荐
相关产品推荐

