【问题标题】:How to get base from existing sql DDL file?如何从现有的 sql DDL 文件中获取基础?
【发布时间】:2019-10-19 15:00:54
【问题描述】:

我正在为 MySQL 使用 SQLAlchemy。

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

【问题讨论】:

    标签: python sqlalchemy


    【解决方案1】:

    SQLAlchemy 不是 SQL 解析器,而是完全相反;它的反射仅适用于现有数据库。换句话说,您必须执行 DDL,然后使用反射/自动映射来创建必要的 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,这当然可能会失败,因此您也必须处理这种情况。另一个可能的警告是,如果您的 ddl.sql 恰好包含多个 CREATE TABLE 语句等,某些 DB-API 驱动程序可能不喜欢一次执行多个语句。

    ...但我想从原始 SQL 文件中获取映射器对象。

    好的,在这种情况下,您需要的是前面提到的解析器。粗略的搜索产生了两个候选人:

    • sqlparse:通用,但issue tracker 证明了解析 SQL 的重要性。经常被混淆,例如将 ... COMMENT 'card', `card_company_id` ... 解析为关键字和标识符列表,而不是关键字、文字、标点和标识符(或者更好的是,将列定义作为它们自己的节点)。
    • mysqlparse:一个 MySQL 特定的解决方案,但对几乎任何东西的支持有限,而且似乎已被废弃。

    不过,解析只是第一步。然后,您必须将生成的树转换为模型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-03
      • 2016-06-07
      • 2017-12-12
      • 2011-05-12
      相关资源
      最近更新 更多