Как анализировать синтаксис SQL, маркировать SQL в Python

#python #sql #tokenize

#python #sql #маркировать

Вопрос:

Мне нужно проанализировать синтаксис SQL, чтобы получить имя таблицы в FROM и ключевое слово WHERE, если оно существует (корневой уровень, включить вложенный запрос). Например:

 Select * 
---
From a
Inner join b on a.c = b.c
---
Where a.o in (
  select o 
  from z
  where z.l in (
      select l 
      from a
  )
)

Output: From = [a,b], Where = [z,a]
 

Я должен обработать все типы: выбрать, вставить, обновить, удалить, выбрать в, создать

У меня есть некоторые идеи, такие как:

  • маркировать sql-оператор
  • найти индекс корня ИЗ, корень, ГДЕ, если существует (включить подзапрос)
  • разделить запрос на 2 части: откуда, ОТКУДА и ОТКУДА до конца
  • для каждого найдите имя таблицы с помощью regrex или некоторых библиотек

Я пробую некоторые библиотеки: sqlparse, sql_metadata, moz_sql_parser. Но это не удается, когда запрос сложный. С помощью sql_metadata я буду пропускать имя таблицы, когда comment — существует, если удалить комментарий с помощью sqlparse, я где-то пропущу ‘)’ … и т.д.

Как разделить часть FROM и часть WHERE Как найти имя таблицы в каждом

Как это решить? Спасибо

Комментарии:

1. Этот блог должен помочь вам в некотором роде, grisha.org/blog/2016/11/14/table-names-from-sql

Ответ №1:

Веб-класс CS50 в Гарварде содержит следующий код, который, я думаю, поможет вам в последних двух строках. В основном вызывается требуемый результат с помощью result .поле

   import os

  from sqlalchemy import create_engine
  from sqlalchemy.orm import scoped_session, sessionmaker

  engine = create_engine(os.getenv("DATABASE_URL")) # database engine object from SQLAlchemy that manages connections to the database
                                                    # DATABASE_URL is an environment variable that indicates where the database lives
  db = scoped_session(sessionmaker(bind=engine))    # create a 'scoped session' that ensures different users' interactions with the
                                                    # database are kept separate

  flights = db.execute("SELECT origin, destination, duration FROM flights").fetchall() # execute this SQL command and return all of the results
  
  for flight in flights
          print(f"{flight.origin} to {flight.destination}, {flight.duration} minutes.") # for every flight, print out the flight info