如何从sql查询中提取表名和列名?

新手上路,请多包涵

所以假设我们有这样一个简单的查询:

 Select a.col1, b.col2 from tb1 as a inner join tb2 as b on tb1.col7 = tb2.col8;

结果应该是这样的:

 tb1 col1
tb1 col7
tb2 col2
tb2 col8

我尝试使用一些 python 库来解决这个问题:

  1. 即使只使用 sqlparse 提取表也可能是一个大问题。例如 ,这本 官方书籍根本无法正常工作。

2)使用正则表达式似乎很难实现。

3)但后来我发现 了这个,这可能会有所帮助。但是问题是我无法连接到任何数据库并执行该查询。

有任何想法吗?

原文由 Rocketq 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.8k
2 个回答

真的,这不是一件容易的事。您可以使用词法分析器(在此示例中为 ply )并定义多个规则以从字符串中获取多个标记。以下代码为 SQL 字符串的不同部分定义了这些规则,并将它们重新组合在一起,因为输入字符串中可能存在别名。结果,您会得到一个字典( result ),其中不同的表名作为键。

 import ply.lex as lex, re

tokens = (
    "TABLE",
    "JOIN",
    "COLUMN",
    "TRASH"
)

tables = {"tables": {}, "alias": {}}
columns = []

t_TRASH = r"Select|on|=|;|\s+|,|\t|\r"

def t_TABLE(t):
    r"from\s(\w+)\sas\s(\w+)"

    regex = re.compile(t_TABLE.__doc__)
    m = regex.search(t.value)
    if m is not None:
        tbl = m.group(1)
        alias = m.group(2)
        tables["tables"][tbl] = ""
        tables["alias"][alias] = tbl

    return t

def t_JOIN(t):
    r"inner\s+join\s+(\w+)\s+as\s+(\w+)"

    regex = re.compile(t_JOIN.__doc__)
    m = regex.search(t.value)
    if m is not None:
        tbl = m.group(1)
        alias = m.group(2)
        tables["tables"][tbl] = ""
        tables["alias"][alias] = tbl
    return t

def t_COLUMN(t):
    r"(\w+\.\w+)"

    regex = re.compile(t_COLUMN.__doc__)
    m = regex.search(t.value)
    if m is not None:
        t.value = m.group(1)
        columns.append(t.value)
    return t

def t_error(t):
    raise TypeError("Unknown text '%s'" % (t.value,))
    t.lexer.skip(len(t.value))

# here is where the magic starts
def mylex(inp):
    lexer = lex.lex()
    lexer.input(inp)

    for token in lexer:
        pass

    result = {}
    for col in columns:
        tbl, c = col.split('.')
        if tbl in tables["alias"].keys():
            key = tables["alias"][tbl]
        else:
            key = tbl

        if key in result:
            result[key].append(c)
        else:
            result[key] = list()
            result[key].append(c)

    print result
    # {'tb1': ['col1', 'col7'], 'tb2': ['col2', 'col8']}

string = "Select a.col1, b.col2 from tb1 as a inner join tb2 as b on tb1.col7 = tb2.col8;"
mylex(string)

原文由 Jan 发布,翻译遵循 CC BY-SA 3.0 许可协议

对于我的简单用例(查询中的一个表,没有连接),我使用了以下调整

lst = "select * from table".split(" ")
lst = [item for item in lst if len(item)>0]
table_name = lst[lst.index("from")+1]

原文由 Idhem 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题