【问题标题】:How to extract the column names from a sql query如何从 sql 查询中提取列名
【发布时间】:2018-06-28 06:14:27
【问题描述】:

我只从这样的查询中提取了列字段

query_split = [query[query.find("select") + len("select"): query.find("from")]]

我得到一个这样的字符串

 query_split = [' service,count(*) as count,round(sum(mrp),2) as sale ']

我想得到一个像这样的列表

[' service','count(*) as count','round(sum(mrp),2) as sale']

这是因为我想获取列名列表

['service','count','sale']

我尝试过其他方法,例如

for file in reader(query_split):
    print(file)

给我输出

[' service', 'count(*) as count', 'round(sum(mrp)', '2) as sale ']

当我在查询中使用使用 round(sum(mrp),2) 类型操作的测试用例时,以下函数在该点失败

def get_column_name(query):
    """
    Extracts the column name from a sql query
    :param query: str
    :return: column_name
    list: Column names which that query will fetch
    """
    column_name=[]
    query_split = query[query.find("select") + len("select"): query.find("from")]
    for i in query_split.split(','):

        if "as" in i:
            column_name.append(i.split('as')[-1])
        else:
            column_name.append(i.split(' ')[-1])
    return column_name

【问题讨论】:

  • 您是否偶然地执行了您想要剖析的查询?如果是这样,并且如果您使用符合 DBAPI 2 的库,则光标的 description attribute 可能会对您有所帮助。
  • 否 @shmee ,此查询将用于 api。
  • 据我了解,您正在尝试通过文本处理来获取列名?假设您没有关于查询的先验信息?
  • 你想走多远?这是一次性工作还是需要自动化的常规工作?
  • @wp78de 它将用于自动化。我已经解决了一点问题,但在这个测试用例中失败了。更新了我的问题,如何获取简单查询的列名,但在查询有一些时失败在查询操作中

标签: python mysql regex


【解决方案1】:

您的问题是这里使用的 SQL 具有嵌套结构。

最有可能最简洁的解决方案是拥有一个能够理解 MySQL 方言的 SQL 解析器。可以说,使用 ANTLR 最容易做到这一点。如果您有兴趣,可以找到MySQL grammar herequick guide here

要使用正则表达式解决这个问题,我们需要在匹配模式中使用递归正则表达式来考虑平衡括号,如下所示:

[^,]+(\((?>[^()]++|(?1))*+\))[^,]+|([^(),]+(?:,|$))

解释

  • [^,]+(\((?>[^()]++|(?1))*+\))[^,]+ 递归正则表达式,用于匹配 () 对以及中间的所有内容(包括逗号),这些内容由一个匹配除逗号之外的所有内容的否定字符类包围。
  • ([^(),]+(?:,|$)) 匹配常规列

Demo

示例代码:

import regex as re
regex = r"[^,]+(\((?>[^()]++|(?1))*+\))[^,]+|([^(),]+(?:,|$))"
test_str = "service,count(*) as count,round(sum(mrp),2) as sale,count(*) as count2,round(sum(mrp),2) as sale2"
matches = re.finditer(regex, test_str, re.MULTILINE)
result = [match.group() for match in matches]

输出:

['service,', 'count(*) as count', 'round(sum(mrp),2) as sale', 'count(*) as count2', 'round(sum(mrp),2) as sale2']

由于我们使用 PCRE 正则表达式功能,您需要安装 Python 的替代 regex 包来运行代码。祝你好运。

【讨论】:

  • 哇!感谢您提供出色的解决方案。您能否建议我从哪里可以理解这个正则表达式,以便我以后可以自己使用它们。
猜你喜欢
  • 2016-06-08
  • 1970-01-01
  • 2012-11-18
  • 2020-10-24
  • 2023-02-25
  • 1970-01-01
  • 2019-05-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多