Python解析SQL并查找关系

时间:2016-09-13 01:30:40

标签: python sql parsing pyparsing sql-parser

我已经在字符串中找到了大量的SQL查询列表,它们是为Presto编写的,因此有点格式化为MySQL。

我希望能够梳理出一些查询中写的表关系。

让我们从简单的事情开始:

SELECT e.object_id, count(*)
FROM schema_name.elements AS e
       JOIN schema_name2.quotes AS q ON q.id = e.object_id
WHERE e.object_type = 'something' 
GROUP BY e.object_id, q.query
ORDER BY 2 desc;

可以清楚地看到事物在哪里连接在一起,虽然有别名 - 所以需要扫描并找到别名 - 这很好,因为关键字" AS"使用。

所以我想要返回一个查询关系列表,每个关系看起来都像这个dict:

dict = {'SourceSchema': 'schema_name',
'SourceTable': "elements",
'SourceColumn': "object_id",
'TargetSchema': "schema_name2",
'TargetTable': "quotes",
'TargetColumn': "id"}

我可以想象这样做很容易,但事情变得更加复杂:

SELECT e.object_id, count(*)
FROM schema_name.elements e
        LEFT JOIN schema_name2.quotes q ON q.id = cast(coalesce(nullif(e.object_id,''),'0') as bigint)
WHERE e.object_type = 'something' 
GROUP BY e.object_id, q.query
ORDER BY 2 desc;

需要注意的3件事

  • 缺少" AS"保留字 - 可能使得更难获得
  • 加入时,需要解决这两个表所需的大量内容
  • 这不是一个简单的" JOIN"它是一个左连接

我想知道是否有某种形式的Python SQL解析库可以让我在大约4000个查询中梳理出关系?如果没有,那我怎么能有效地做到这一点?我猜我可能需要扫描查询,找到连接,找到别名,然后看看他们如何加入,同时考虑到需要丢弃的一堆停用词。

1 个答案:

答案 0 :(得分:1)

对select_parser.py(https://sourceforge.net/p/pyparsing/code/HEAD/tree/trunk/src/examples/select_parser.py)进行一些细微的更改,这是pyparsing示例的一部分,我在解析你的第一个例子之后得到了这个:

SELECT e.object_id, count(*) FROM schema_name.elements AS e        JOIN schema_name2.quotes AS q ON q.id = e.object_id WHERE e.object_type = 'something' GROUP BY e.object_id, q.query ORDER BY 2 desc;
['SELECT', [['e.object_id'], ['count', '*']], 'FROM', [['schema_name', '.', 'elements'], 'AS', 'e', ['JOIN'], ['schema_name2', '.', 'quotes'], 'AS', 'q', ['ON', ['q.id', '=', 'e.object_id']]], 'WHERE', ['e.object_type', '=', 'something'], 'GROUP', 'BY', [['e.object_id'], ['q.query']], 'ORDER', 'BY', [['2', 'DESC']], ';']
- columns: [['e.object_id'], ['count', '*']]
  [0]:
    ['e.object_id']
  [1]:
    ['count', '*']
- from: [[['schema_name', '.', 'elements'], 'AS', 'e', ['JOIN'], ['schema_name2', '.', 'quotes'], 'AS', 'q', ['ON', ['q.id', '=', 'e.object_id']]]]
  [0]:
    [['schema_name', '.', 'elements'], 'AS', 'e', ['JOIN'], ['schema_name2', '.', 'quotes'], 'AS', 'q', ['ON', ['q.id', '=', 'e.object_id']]]
    - table_alias: [['e'], ['q']]
      [0]:
        ['e']
      [1]:
        ['q']
- order_by_terms: [['2', 'DESC']]
  [0]:
    ['2', 'DESC']
    - direction: DESC
    - order_key: 2
- where_expr: ['e.object_type', '=', 'something']

所以看起来这个例子可能会帮助你开始。它被编写为SQLite的SELECT格式,因此您需要扩展一些语法。