Как получить базу из существующего файла sql DDL? - PullRequest
0 голосов
/ 04 июня 2019

Я использую SQLAlchemy для MySQL.

Типичным примером SQLAlchemy является

  1. Определение классов моделей по структуре таблицы.(class User(Base))
  2. Перенос в базу данных с помощью db.create_all (или alembic и т. Д.)
  3. Импортируйте класс модели и используйте его.(db.session.query(User))

Но что, если я хочу использовать необработанный файл SQL вместо определенных классов моделей?Я прочитал automap сделать подобное, но я хочу получить объект сопоставления из необработанного файла SQL, а не из созданной базы данных.

Есть ли лучший способ сделать это?

Этопример DDL

-- ddl.sql
-- This is just an example, so please ignore some issues related to a grammar
CREATE TABLE `card` (
  `card_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'card',
  `card_company_id` bigint(20) DEFAULT NULL COMMENT 'card_company_id',
  PRIMARY KEY (`card_id`),
  KEY `card_ix01` (`card_company_id`),
  KEY `card_ix02` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='card table'

и я хочу сделать как

Base = raw_sql_base('ddl.sql')  # Some kinda automap_base but from SQL file

# engine, suppose it has two tables 'user' and 'address' set up
engine = create_engine("mysql://user@localhost/program")

# reflect the tables
Base.prepare(engine)

# mapped classes are now created with names by sql file
Card = Base.classes.card

session = Session(engine)

session.add(Card(card_id=1, card_company_id=1))
session.commit()  # Insert

1 Ответ

0 голосов
/ 04 июня 2019

SQLAlchemy - не SQL парсер , а полная противоположность;его отражение работает только против существующих баз данных.Другими словами, вы должны выполнить свой DDL и затем использовать рефлексию / automap для создания необходимых моделей Python:

from sqlalchemy.ext.automap import automap_base

# engine, suppose it has two tables 'user' and 'address' set up
engine = create_engine("mysql://user@localhost/program")

# execute the DDL in order to populate the DB
with open('ddl.sql') as ddl:
    engine.execute(ddl)

Base = automap_base()

# reflect the tables
Base.prepare(engine, reflect=True)

# mapped classes are now created with names by sql file
Card = Base.classes.card

session = Session(engine)

session.add(Card(card_id=1, card_company_id=1))
session.commit()  # Insert

Это, конечно, может не сработать, если вы уже выполнили тот же DDL для своей базы данных, поэтому выдолжен был бы справиться и с этим делом.Другое возможное предостережение заключается в том, что некоторым драйверам DB-API может не нравиться выполнять несколько операторов одновременно, если ваш ddl.sql содержит более одного оператора CREATE TABLE и т. Д.

... ноЯ хочу получить объект сопоставления из необработанного файла SQL.

Хорошо, в этом случае вам необходим вышеупомянутый синтаксический анализатор .При беглом поиске было выдвинуто два кандидата:

  • sqlparse : универсальный, но средство отслеживания проблем является свидетельством того, насколько нетривиальным является SQL-анализ.Часто путается, например, анализирует ... COMMENT 'card', `card_company_id` ... как ключевое слово и список идентификаторов, а не как ключевое слово, литерал, пунктуацию и идентификатор (или, что еще лучше, определения столбцов как их собственные узлы).
  • mysqlparse : решение, специфичное для MySQL, но с ограниченной поддержкой практически всего, и оно кажется заброшенным.

Разбор был бы только первым шагом.Затем вам придется конвертировать полученные деревья в модели.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...