Парсинг 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]
в конце, чтобы получить первый и единственный элемент в массиве, который производит понимание списка