1

我正在尝试从 SQL 脚本中提取表名。我有以下字符串:

from db1.tableX tbx1 --quantity table
inner join tableY tbx2  on tbx1.xyz=tbx2.xyz

我不想匹配这个字符串,因为tabley它没有以数据库名称为前缀。我试图做到这一点的方法是在数据库名称之前的字符串中检测单词“on”。

我的正则表达式匹配tablex但也匹配tbx1,我不希望我的表达式匹配。

我希望它只在这种情况下匹配。

from db1.tableX tbx1 --quantity table
inner join db1.tableY tbx2 on tbx1.xyz = tbx2.xyz

我的正则表达式应该给我tableXtableY因为它们以数据库名称为前缀。

这是我的表达:

(insert\s+into|from|inner\s+join|left\s+outer\s+join|join)\s+[\sa-zA-Z0-9_$#-]*\.\s*(?<table>[a-zA-Z0-9_]+)(?=\s+[a-zA-Z0-9_$#-]+)*
4

2 回答 2

1

你可以简化你的表达

(?<=\b(from|join)\s+[a-zA-Z0-9_$#-]*\.\s*)[a-zA-Z0-9_]+

它将直接产生表名,而不必使用命名组。我正在使用模式

(?<=prefix)find

这仅返回“查找”部分作为匹配值。作为前缀,我使用“from”或“join”,后跟数据库名称,点和可能的空格。

\b是单词的开头或结尾。

最后一部分[a-zA-Z0-9_]+是表名。

是否有内连接、外连接等都没有区别,所以我放弃了这种区别。

评论很难被发现,因为它们可以包含任何东西并且可以出现在任何地方。此外,您还有两种类型的评论-- Until end of line\* ... *\.

您可以尝试检测这样的评论和空格

(\s|--.*?$|\\\*.*?\*\\)+

请注意,退格和星号必须被转义,所以\*变得\\\**\变得\*\\

$表示行尾。?after.*确保不会一次跳过多个注释,从而跳过它们之间的有意义的文本。

这在大多数情况下都有效;但是,类似结构的注释可以包含在字符串文字中:SELECT 'hello -- world' AS greeting FROM .... 这不是评论!如果没有对 SQL 文本的完整语法分析,您将无法涵盖所有​​可能的情况。但是你不能用正则表达式来做到这一点。正则表达式有其局限性。

于 2013-02-26T18:09:59.900 回答
1

一步步:

1) http://regexr.com?33tto

我不知道你为什么在比赛结束时放那个前瞻。我认为你不需要它,所以我删除了它。

2) http://regexr.com?33ttr

现在我们解决您指出的问题。问题是在您的数据库名称匹配中[\sa-zA-Z0-9_$#-]*,您已将空格作为有效字符包含在内。我也删除了那个。

3) http://regexr.com?33ttu

这是期望的结果吗?

于 2013-02-26T15:31:54.580 回答