用Python解析SQL

2024-06-06 11:32:47 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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

我以前从未实现过语法分析器,因此我希望得到一些关于如何最好地实现SQL语法分析器和计算器的建议。

  • 上述方法听起来对吗?
  • 是否还有其他工具/库需要我研究?比如PLY或者Pyparsing
  • 我很感激能帮助我的文章、书籍或源代码的指针。

更新:

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

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


Tags: 工具数据方法sql关系表达式方式ast
3条回答

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

对我来说,我只需要一个where子句。我试过用pyparsing编写booleneo(一个布尔表达式解析器),但最终还是从头开始使用pyparsing。Mark Rushakoff的reddit帖子中的第一个链接给出了一个使用它的sql示例。Whoosh一个全文搜索引擎也使用它,但我还没有看到源代码如何使用。

Pyparsing非常容易使用,您可以很容易地将其定制为与sql不完全相同(您不需要的大多数语法)。我不喜欢ply,因为它使用一些使用命名约定的魔术。

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

This reddit post建议将Python-sqlparse作为一个现有实现,以及其他一些链接。

Twolay的PythonSQL解析器对我来说非常有用。它是用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']

相关问题 更多 >