这将是非常困难的仅使用正则表达式.如果你真的需要做reliably,你可以根据他们的需要做check out how pgpool-II
re-used PostgreSQL's own parser—这是一个C++密集型任务,而不是SQL任务.
Here are some more examples at the wiki,其中一些可以直接使用.您甚至可以让Python sqlparse
处理查询文本,然后处理.get_identifiers()
,所有这些都在db中,在一个PL/Python函数中.
如果你只想涵盖一些非常基本的情况,你可以try 将目标标记放在某些关键字下面:
select field1
,unnest(
regexp_matches(
field2
,'(?:UPDATE|INTO|FROM|JOIN|USING|TABLE)(?:\s+ONLY)*\s+([[:alpha:]_]+[[:word:]]*|"[^"]+")'
,'gi'
)
) AS spotted_table
from table1;
field1 |
spotted_table |
a |
table2 |
a |
table1 |
b |
table3 |
c |
table4 |
?:
in (?:something)
使括号不可捕获,这就是为什么它只报告来自最后一组没有?:
的匹配项
'gi'
中的g
使此报告全部匹配,i
禁用区分大小写
- the identifier syntax is taken from the doc, except the
$
oddity:
SQL标识符和关键字必须以字母(a-z
,但也包括带变音标记的字母和非拉丁字母)或下划线(_
)开头.标识符或关键字中的后续字符可以是字母、下划线、数字(0-9
)或美元符号($
)
这个关键字列表绝不是详尽无遗的,虽然它涵盖了示例,但这个正则表达式非常脆弱.看obvious blind spots in this demo个左右.
如果你考虑到
- 标识符可以是双引号,也可以是非引号,这使它们成为fold to lowercase.
- 包含SQL外观文本的单个或美元引号字符串常量—如果您也考虑dynamic SQL,则非常有用,否则它会导致错误肯定
- 从技术上讲,你可以把一个表命名为
"select from table7 join TABLE8 on waitaminute;"
(整个表就是表的名称,而不仅仅是table7
部分):demo
- 长的、逗号分隔的关系列表与非关系的源交织,特别是子查询
- 行尾
//
和行内/多行/*...*/
条 comments
如果您正在分析的查询在您保存它们的同一个数据库上运行,则可以将其与information_schema.tables
相关联.注意,在查询主体中,有9 different things可以在同一个位置,这还不包括table只是其中一种形式的relation.你也可以从view
、materialized view
、foreign table
、partitioned table
中 Select select
,所有这些都在某种程度上像table
.Some views are updatable,这意味着您也可以从它们insert
/merge
/update
/delete
,就像您直接与它们的底层表交互一样.
如果你试图跟踪有效的交互,你还必须跟踪rule
和trigger
系统、视图和matview定义以及routine
主体和依赖项.