代码之家  ›  专栏  ›  技术社区  ›  codeape

用python解析SQL

  •  40
  • codeape  · 技术社区  · 16 年前

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

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

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

    • 上述方法是否正确?
    • 我是否应该研究其他工具/库?喜欢 PLY Pyparsing .
    • 对于那些能帮助我的文章、书籍或源代码,我们将不胜感激。

    更新:

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

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

    4 回复  |  直到 9 年前
        1
  •  36
  •   Paul    11 年前

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

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

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

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

        2
  •  9
  •   Mark Rushakoff    16 年前

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

        3
  •  2
  •   dlink    9 年前

    对于我来说,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']
    
        4
  •  1
  •   Mathieu Longtin    12 年前

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

    更新:现在我看到这是建议-我同意这是值得的: