用 Python 解析 SQL

问题描述 投票:0回答:6

我想在非关系数据存储之上创建一个 SQL 接口。非关系数据存储,但以关系方式访问数据是有意义的。

我正在研究使用 ANTLR 生成将 SQL 表示为关系代数表达式的 AST。然后通过评估/遍历树返回数据。

我以前从未实现过解析器,因此我想要一些关于如何最好地实现 SQL 解析器和求值器的建议。

  • 上述方法听起来是否正确?
  • 我应该研究其他工具/库吗?像 PLYPyparsing.
  • 感谢对我有帮助的文章、书籍或源代码的指针。

更新:

我使用 pyparsing 实现了一个简单的 SQL 解析器。结合针对我的数据存储实现关系操作的 Python 代码,这非常简单。

正如我在其中一条评论中所说,练习的目的是使数据可供报告引擎使用。为此,我可能需要实施 ODBC 驱动程序。这可能是很多工作。

python sql parsing pyparsing
6个回答
46
投票

我已经非常广泛地研究了这个问题。 Python-sqlparse 是一个非验证解析器,它并不是您真正需要的。 antlr 中的示例需要大量工作才能转换为 python 中的漂亮 ast。 sql 标准语法在here,但是自己转换它们将是一项全职工作,并且您可能只需要它们的一个子集,即没有连接。您也可以尝试查看 gadfly(一个 Python SQL 数据库),但我避免了它,因为他们使用了自己的解析工具。

就我而言,我基本上只需要一个 where 子句。我尝试了用 pyparsing 编写的 booleneo(一个布尔表达式解析器),但最终从头开始使用 pyparsing。 Mark Rushakoff 的 reddit 帖子中的第一个链接给出了一个使用它的 SQL 示例。 Whoosh 全文搜索引擎也使用它,但我没有查看源代码以了解如何使用它。

Pyparsing 非常易于使用,您可以非常轻松地将其自定义为与 SQL 不完全相同(您不需要的大部分语法)。我不喜欢 ply,因为它使用了一些使用命名约定的魔法。

简而言之,试试 pyparsing,它很可能足够强大,可以满足您的需求,并且与 python 的简单集成(具有简单的回调和错误处理)将使体验变得非常轻松。


13
投票

这篇 reddit 帖子 建议将 python-sqlparse 作为现有的实现,以及其他几个链接。


5
投票

TwoLaid 的 Python SQL 解析器非常适合我的目的。它是用 C 编写的,需要编译。它很坚固。它解析出每个子句的各个元素。

https://github.com/TwoLaid/python-sqlparser

我正在使用它来解析要在报告标题中使用的查询列名称。这是一个例子。

import sqlparser

def get_query_columns(sql):
   '''Return a list of column headers from given sqls select clause'''

   columns = []

   parser = sqlparser.Parser()

   # Parser does not like new lines
   sql2 = sql.replace('\n', ' ')

   # Check for syntax errors
   if parser.check_syntax(sql2) != 0:
      raise Exception('get_query_columns: SQL invalid.')

   stmt = parser.get_statement(0)
   root = stmt.get_root()
   qcolumns = root.__dict__['resultColumnList']
   for qcolumn in qcolumns.list:
      if qcolumn.aliasClause:
         alias = qcolumn.aliasClause.get_text()
         columns.append(alias)
      else:
         name = qcolumn.get_text()
         name = name.split('.')[-1] # remove table alias
         columns.append(name)

   return columns

sql = '''
SELECT 
   a.a,
   replace(coalesce(a.b, 'x'), 'x', 'y') as jim,
   a.bla as sally  -- some comment
FROM
   table_a as a
WHERE
   c > 20
'''

print get_query_columns(sql)

# output: ['a', 'jim', 'sally']

1
投票

当然,最好利用 python-sqlparse on Google Code

更新:现在我看到有人建议这样做——我同意这是值得的:


1
投票

我正在使用

python-sqlparse
取得了巨大的成功。

在我的例子中,我正在处理已经验证过的查询,我的 AST-walking 代码可以对结构做出一些理智的假设。


0
投票

SQLGlot 是一个无依赖的 SQL 解析器、转译器、优化器和引擎。突出显示语法错误。但是,应该注意 SQL 验证不是 SQLGlot 的目标,因此一些语法错误可能不会被注意到。 (基准

sqltree 是 SQL 的实验性解析器,为 SQL 查询提供语法树。

sqloxidesqlparser-rs 的 Rust 绑定包装到 python 包中。

© www.soinside.com 2019 - 2024. All rights reserved.