sql - 在 SQL 中查找函数
问题描述
在类似下面的代码中,我只想提取具有多个参数的函数,并希望忽略具有 2 个参数的合并。请帮助我已经使用 REGEX 进行了几天的工作,并认为这可能只是我无法理解的事情。我相信答案是一个组,并使用子正则表达式或类似的东西解析该组。
AND NOT COALESCE(UPPER(FUNCTION_TO_FIND(B.PARAM, B.TEST_PARAM1, B.TEST_PARAM2, B.TEST_PARAM3,'Routine Type', ATT_TO_DATE())),'NO_VALUE') IN (UPPER('Routine Appointment Letter'))
AND NOT UPPER(DBO.FUNCTION_TO_FIND( B.PARAM , B.TEST_PARAM1 , B.TEST_PARAM2, B.TEST_PARAM3,'Routine Type', ATT_TO_DATE())) IN (UPPER('Routine Appointment Letter'))
AND NOT COALESCE(1, 3) = 2
我希望找到
DBO.FUNCTION_TO_FIND( B.PARAM , B.TEST_PARAM1 , B.TEST_PARAM2, B.TEST_PARAM3,'Routine Type', ATT_TO_DATE())
和
FUNCTION_TO_FIND(B.PARAM, B.TEST_PARAM1, B.TEST_PARAM2, B.TEST_PARAM3,'Routine Type', ATT_TO_DATE())
请注意,这些函数并不总是相同的层数,但它们都会有超过 2 个参数。
我尝试了以下平衡括号函数的不同版本和编辑,但无法让它正确计算参数以捕获整个函数。
(\((?>[^()]|(?1))*\))
编辑,以下澄清
EDIT1:请注意,在查找函数时,我将无法访问将运行 SQL 的服务器,这必须完全脱机完成。
EDIT2:进一步考虑这一点,我认为这是一个需要解决的问题,而不是一个正则表达式,而是使用另一种工具即时创建正则表达式。
- 创建一个我不想找到的常见函数列表TO_CHAR, TO_NUMBER, UPPER, LOWER, COALESCE, MIN, MAX, AND, EXISTS, COALESCE, SUM, FROM
- 使用类似以下的内容查找查询字符串中使用的任何函数的开头。
[[:alnum:]][^)( \r\n]+?\s*?\(
- 备份字符串中的一个字符并使用以下代码查找匹配的括号。
(\((?>[^()]|(?1))*\))
- ...
我将尝试达到上述效果并返回答案。同时,如果有人有不同的想法,请随时贡献。
解决方案
好的,我试了一下,Microsoft.SqlServer.Management.SqlParser.Parser
从Microsoft.SqlServer.SqlManagementObjects
nuget 包中可能是要走的路。
var sql = @"SELECT .... ";
var result = Parser.Parse(sql);
var batch = result.Script.Batches.First();
var select = batch.Children.Cast<SqlSelectStatement>().First();
var selectSpec = select.SelectSpecification;
因此,selectSpec.Xml
包含表示该SELECT
语句的分层 XML 文档。
SqlCodeObject
s 提供了一个Accept()
实现访问者模式的方法。写一个访问者并评估您感兴趣的类型的表达式:SqlNullScalarExpression
, SqlUserDefinedScalarFunctionCallExpression
, 可能更多。
请注意,解析器无法识别没有dbo.
架构的用户定义函数:
<SqlNullScalarExpression Location="((3,9),(3,137))">
<!--COALESCE(UPPER(FUNCTION_TO_FIND(B.PARAM, B.TEST_PARAM1, B.TEST_PARAM2, B.TEST_PARAM3,'Routine Type', ATT_TO_DATE())),'NO_VALUE')-->
</SqlNullScalarExpression>
相对
<SqlUserDefinedScalarFunctionCallExpression Location="((4,15),(4,122))" ObjectIdentifier="DBO.FUNCTION_TO_FIND">
<!--DBO.FUNCTION_TO_FIND( B.PARAM , B.TEST_PARAM1 , B.TEST_PARAM2, B.TEST_PARAM3,'Routine Type', ATT_TO_DATE())-->
<SqlObjectIdentifier Location="((4,15),(4,35))" SchemaName="DBO" ObjectName="FUNCTION_TO_FIND">
<!--DBO.FUNCTION_TO_FIND-->
<SqlIdentifier Location="((4,15),(4,18))" Value="DBO">
<!--DBO-->
</SqlIdentifier>
<SqlIdentifier Location="((4,19),(4,35))" Value="FUNCTION_TO_FIND">
<!--FUNCTION_TO_FIND-->
</SqlIdentifier>
</SqlObjectIdentifier>
...
<SqlBuiltinScalarFunctionCallExpression Location="((4,108),(4,121))" FunctionName="ATT_TO_DATE" IsStar="False">
<!--ATT_TO_DATE()-->
</SqlBuiltinScalarFunctionCallExpression>
</SqlUserDefinedScalarFunctionCallExpression>
推荐阅读
- python - 如何使用 boto3 cloudformation 资源列出和过滤堆栈?
- mysql - 在 MYSQL 中从组中查找最新行
- azure-devops - 如何允许客户仅读取 VSTS/Azure DevOps 中的特定分支
- c# - 从 Controller .Net Core 2.1 调用 Signalr 方法
- java - JAX-RS(Genson + jersey):对象未转换为 json
- python - 有人可以帮我吗?(Python 3)
- ios - JSONSerialization.jsonObject 返回 nil
- wordpress - 下一项的手风琴覆盖
- python - 将 PostGIS 查询转换为 Django QuerySet (geoDjango postgis)
- python-asyncio - get_event_loop() 调用的开销