当前位置: 首页 > 面试题库 >

使用pyparsing进行SQL解析

弘思聪
2023-03-14
问题内容

我最近几周正在学习PyParsing。我计划使用它从SQL语句获取表名。我看了http://pyparsing.wikispaces.com/file/view/simpleSQL.py。但是我打算使语法保持简单,因为我不是在试图解析select语句的每个部分,而是在寻找表名。同样,为任何市售的现代数据库(如Teradata)定义完整的语法也很费劲。

#!/usr/bin/env python

from pyparsing import *
import sys

semicolon = Combine(Literal(';') + lineEnd)
comma = Literal(',')
lparen = Literal('(')
rparen = Literal(')')

# Keyword definition
update_kw, volatile_kw, create_kw, table_kw, as_kw, from_kw, \
where_kw, join_kw, left_kw, right_kw, cross_kw, outer_kw, \
on_kw , insert_kw , into_kw= \
    map(lambda x: Keyword(x, caseless=True), \
        ['UPDATE', 'VOLATILE', 'CREATE', 'TABLE', 'AS', 'FROM',
         'WHERE', 'JOIN' , 'LEFT', 'RIGHT' , \
         'CROSS', 'OUTER', 'ON', 'INSERT', 'INTO'])

# Teradata SQL allows SELECT and well as SEL keyword
select_kw = Keyword('SELECT', caseless=True) | Keyword('SEL' , caseless=True)

# list of reserved keywords
reserved_words = (update_kw | volatile_kw | create_kw | table_kw | as_kw |
                  select_kw | from_kw | where_kw | join_kw |
                  left_kw | right_kw | cross_kw | on_kw | insert_kw |
                  into_kw)

# Identifier can be used as table or column names. They can't be reserved words
ident = ~reserved_words + Word(alphas, alphanums + '_')

# Recursive definition for table
table = Forward()
# simple table name can be identifer or qualified identifier e.g. schema.table
simple_table = Combine(Optional(ident + Literal('.')) + ident)
# table name can also a complete select statement used as table
nested_table = lparen.suppress() + select_kw.suppress() + SkipTo(from_kw).suppress() + \   
               from_kw.suppress() + table + rparen.suppress()
# table can be simple table or nested table
table << (nested_table | simple_table)
# comma delimited list of tables
table_list = delimitedList(table)
# Building from clause only because table name(s) will always appears after that
from_clause = from_kw.suppress() + table_list


txt = """
SELECT p, (SELECT * FROM foo),e FROM a, d, (SELECT * FROM z), b
"""
for token, start, end in from_clause.scanString(txt):
    print token

这里值得一提。我使用“
SkipTo(from_kw)”跳过SQL语句中的列列表。这主要是为了避免为列列表定义语法,列列表可以是逗号分隔的标识符,许多函数名称,DW分析函数之类的列表,而不能用逗号分隔。通过这种语法,我可以解析上面的语句以及SELECT列列表或表列表中的任何嵌套级别。

['foo']
['a', 'd', 'z', 'b']

当SELECT具有where子句时,我遇到问题:

nested_table = lparen.suppress() + select_kw.suppress() + SkipTo(from_kw).suppress() + \   
               from_kw.suppress() + table + rparen.suppress()

当WHERE子句存在时,相同的语句可能看起来像:SELECT … FROM a,d,(SELECT * FROM z WHERE(c1 = 1)和(c2
= 3)),p我想到了更改“ nested_table”的定义到:

nested_table = lparen.suppress() + select_kw.suppress() + SkipTo(from_kw).suppress() + \   
               from_kw.suppress() + table + Optional(where_kw + SkipTo(rparen)) + rparen

但这不起作用,因为它与“ c = 1”之后的右括号匹配。我想知道的是如何在“ SELECT * FROM z
…”之前跳到与左括号匹配的右括号,我不知道如何使用PyParsing

另外,我还寻求一些建议,这是从复杂的嵌套SQL获取表名的最佳方法。任何帮助,我们真的很感激。

谢谢阿比吉特


问题答案:

考虑到您还试图解析嵌套的SELECT,我认为您将无法避免编写一个相当完整的SQL解析器。幸运的是,Pyparsing
Wiki示例页面上有一个更完整的示例select_parser.py。我希望这能使您走得更远。



 类似资料:
  • 问题内容: 我正在尝试在SQL Server中解析以下xml,以获取所有3个ID 使用查询 我得到的结果为100010011002,但我想将结果显示为一列或CSV格式。 任何帮助都将得到应用。 问题答案: 使用MS SQL Server,这将为您提供行。 如果只需要一个值(如本例中所示),则在节点上切碎的速度要快得多(三倍)。

  • 问题内容: 我正在使用Jesey在Java(JAX-RS)中实现Restful Web Service。我在Tomcat v7.0上运行它,我使用Hibernate将数据映射到数据库(MySQL)。我有一个查询来获取可交付成果的列表: 它给了我一百个可交付成果,但我想在Task表中拥有前三名。感谢您的帮助。如何修改查询? 请注意,这三个可交付成果不应重复。 与@FGreg答案存在冲突。当我使用这些

  • 问题内容: 我有一组一对一的映射A->苹果,B->香蕉,等等。我的表中有一列的值为A,B,C。 现在,我正在尝试使用选择语句,这将给我直接结果 但是我没有得到正确的结果,请帮助我。 问题答案: 这只是case语句的语法,看起来像这样。 提醒一下;不执行赋值,该值成为列内容。(如果您想将其分配给变量,则可以将其放在CASE语句之前)。

  • 问题内容: 我有一个不时更新数据集的数据库。在这里,可能发生的是交付了数据库中已经存在的数据集。 目前,我首先要做的是 检查是否已经存在具有这些数据的数据集(使用WHERE语句中的数据)。如果没有返回任何值,则说明我正在执行INSERT。 但这对我来说似乎有点复杂。所以我的问题是:是否有某种条件式INSERT仅在不存在新数据集的情况下才添加它? 我正在使用 SmallSQL 问题答案: 您几乎可以

  • 问题内容: 我试图与我正在阅读的有关SQL Server查询性能的书的作者联系,但似乎本书中提供的电子邮件地址已不复存在。因此,我决定向社区询问。我正在粘贴我在下面写的消息。提前致谢。 ====== 我已经购买了您的书(蒸馏而成的SQL Server 2008查询性能调优),并且知道我的SQL Server Express Edition将不支持运行必要的性能测试所需的许多重要工具。正如您已经说过

  • 我对使用MySQL非常陌生,我还在学习。 假设我有3个表在一个数据库。表格如下: 包含ID(PK)和Name 包含ID(主键)、姓名等 包含rol_num(PK),student_id和course_id。 student_id参考学生(id)course_id参考课程(id) 基本上学生详情在学生表中,课程详情在课程表中,入学表是学生及其课程的链接表 使用Select query命令,如何获取所