【问题标题】:Python-Parsing a SQL using pyparsingPython-使用 pyparsing 解析 SQL
【发布时间】:2016-08-30 07:44:21
【问题描述】:

我想解析一个复杂的 SQL,它有(内连接,外连接)并获取 SQL 中使用的表名。

如果是简单的选择,我可以得到表名,但是如果 SQL 有内连接,左连接如下所示,那么结果只给出第一个表。

select * from xyz  inner join dhf  on df = hfj  where z > 100 

我正在使用类似于以下 Paul 链接中的程序。

http://pyparsing.wikispaces.com/file/view/select_parser.py/158651233/select_parser.py

谁能告诉我如何获取 SQL 中使用的所有表,如下所示

select * from xyz  inner join dhf  on df = hfj  where z > 100.  

【问题讨论】:

  • 这可能是 stackoverflow.com/q/35295458/409172 的副本 该解决方案需要实时数据库和 PL/SQL 存储过程来完成大部分工作,我不确定这对您是否可行。但这可能是正确解析 complex SQL 的唯一方法。即使是非常重要的 Oracle SQL 也几乎无法解析。有 2175 个关键字,其中大部分没有保留,解析 Oracle SQL 是一项艰巨的任务。这就是为什么您需要一个快捷方式,例如在该答案中使用 EXPLAIN PLAN 方法。
  • Pyparsing 不再托管在 wikispaces.com 上。转至github.com/pyparsing/pyparsing

标签: sql oracle python-2.7 pyparsing


【解决方案1】:

这个解析器是很久以前写的,在结果名称中处理多个值直到后来才出现。

在您引用的解析器中更改此行:

single_source = ( (Group(database_name("database") + "." + table_name("table")) | table_name("table")) + 

到

single_source = ( (Group(database_name("database") + "." + table_name("table*")) | table_name("table*")) + 

当我通过 select_stmt 解析器运行您的示例语句时,我现在得到了这个:

select * from xyz  inner join dhf  on df = hfj  where z > 100
['SELECT', ['*'], 'FROM', 'xyz', 'INNER', 'JOIN', 'dhf', 'ON', ['df', '=', 'hfj'], 'WHERE', ['z', '>', '100']]
- columns: ['*']
- table: [['xyz'], ['dhf']]
  [0]:
    ['xyz']
  [1]:
    ['dhf']
- where_expr: ['z', '>', '100']

【讨论】:

  • 感谢 Paul 的回复,它完全按预期工作。我正在从 SQL 中获取所有表名。
  • 是否也可以从 SQL 查询中获取所有连接列?
  • 为什么是“table*”?我可以说它允许多个,但我找不到任何文档。
  • 该行为在setResultsName (pythonhosted.org/pyparsing/…) 的文档中的listAllMatches 参数下进行了描述,然后'*' 在__call__ 文档字符串(pythonhosted.org/pyparsing/…) 中进行了解释
【解决方案2】:

您的问题将取决于您使用的 Sql 平台。

假设您使用的是 MsSql,我会回答。尽管语法发生了变化,但应该能够在所有 Sql 平台上完成相同的逻辑。

通过所有者和表的组合,表是唯一的。我在 Python 脚本中执行了一个返回 #Owner#TableName# 的选择,该脚本用于将所有表中的所有数据提取到文本文件中。假设您没有多个具有不同所有者的同名表,其基本形式是:

从 xtype = 'U' order by name 的 SysObjects 中选择名称

这将为您提供所有表格的列表。 然后你拿那个清单做一个 “从 [其他查询中的表名] 中选择 *” 循环直到你拥有从 Sysobjects 中选择时找到的所有表。

假设您可以访问系统表,则在所有 Sql 平台上都可以使用相同类型的东西。

【讨论】:

  • 选择 select * from syscolumns 可以给你列名。
  • 你误读了这个问题。 OP 不想在数据库中查询表名,他们想从发布的 SQL 语句中提取表名。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-19
  • 2015-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多