Парсинг SQL с python, чтобы найти конкретные операторы

Я использую sqlparse, чтобы попытаться найти конкретные заявления.

код:

import sqlparse

text = 'SELECT * FROM dbo.table'
parse = sqlparse.parse(text)
pizza = [t for t in parse[0].tokens if t.ttype in (sqlparse.tokens.Keyword)]

я получил

[<DML 'SELECT' at 0x9f12318>, <Keyword 'FROM' at 0x9f12548>]

но я действительно хочу вернуть имя таблицы:

dbo.table

Как мне это сделать? Моя конечная цель - проанализировать папки сценариев sql и найти ссылки и другие детали.

1 ответ

Если вы печатаете каждый из токенов

>>> pprint(parse[0].tokens)

[<DML 'SELECT' at 0x7fc278c9eb50>,
 <Whitespace ' ' at 0x7fc278c9eba8>,
 <Wildcard '*' at 0x7fc278c9ec00>,
 <Whitespace ' ' at 0x7fc278c9ec58>,
 <Keyword 'FROM' at 0x7fc278c9ecb0>,
 <Whitespace ' ' at 0x7fc278c9ed08>,
 <Identifier 'dbo.ta...' at 0x7fc278cb3628>]

вы увидите, что dbo.table на самом деле это не ключевое слово, а идентификатор

Следующий логический шаг: фильтр по идентификатору

>>> pprint([t for t in parse[0].tokens if t.ttype in (sqlparse.tokens.Identifier)])

но это дает AttributeError: 'module' object has no attribute 'Identifier', Если вы посмотрите на исходный код sqlparse, вы увидите, что в sql.tokens нет идентификатора, вы не можете фильтровать его. (ошибка в коде? возможно, забыл это реализовать?)

Тем не менее, если вы печатаете ttype каждого токена

>>> pprint([t.ttype for t in parse[0].tokens])

[Token.Keyword.DML,
 Token.Text.Whitespace,
 Token.Wildcard,
 Token.Text.Whitespace,
 Token.Keyword,
 Token.Text.Whitespace,
 None]

Вы увидите, что все они имеют действительный токен как ttype, за исключением dbo.table, который None,

Зная это, мы можем отфильтровать токены и получить желаемый результат:

>>> print([t for t in parse[0].tokens if t.ttype is None])

[<Identifier 'dbo.ta...' at 0x7f6ae0318628>]

И чтобы получить имя:

>>> print([t.to_unicode() for t in parse[0].tokens if t.ttype is None][0])
u'dbo.table'

или же

>>> print([str(t) for t in parse[0].tokens if t.ttype is None][0])
'dbo.table'

Обратите внимание [0] в конце, чтобы получить первый и единственный элемент в массиве, который производит понимание списка

Другие вопросы по тегам