【发布时间】:2021-12-05 04:45:44
【问题描述】:
可以生成原始 SQL 语句来创建任何 SQLAlchemy 表as shown here。
但是,我想生成创建所有表的原始 SQL,而不仅仅是一个。
假设我有这样的表格(这个表格设计不是真实世界的,但它很好地说明了问题):
import sqlalchemy
from sqlalchemy import Column, Integer, Text, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.schema import CreateTable
from sqlalchemy.dialects import postgresql
engine = sqlalchemy.create_engine('postgresql://postgres:postgres@127.0.0.1:5432/postgres', echo=True)
Base = declarative_base()
class Product(Base):
__tablename__ = "product"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(Text, nullable=True)
user_id = Column(Integer, ForeignKey('user.id'), nullable=True)
class User(Base):
__tablename__ = "user"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(Text, nullable=True)
product_id = Column(Integer, ForeignKey('product.id'), nullable=True)
open("create_tables.sql", 'w').close() # to clear the file
for table in Base.metadata.tables.values():
table_sql = str(CreateTable(table).compile(dialect=postgresql.dialect()))
with open("create_tables.sql", "a") as myfile:
myfile.write(table_sql)
Base.metadata.create_all(engine)
(这是完整的程序,您可以按原样运行)
在上面的代码中你可以看到我使用for循环来生成原始SQL:
for table in Base.metadata.tables.values():
table_sql = str(CreateTable(table).compile(dialect=postgresql.dialect()))
with open("create_tables.sql", "a") as myfile:
myfile.write(table_sql)
生成的文件包含:
CREATE TABLE product (
id SERIAL NOT NULL,
name TEXT,
user_id INTEGER,
PRIMARY KEY (id),
FOREIGN KEY(user_id) REFERENCES "user" (id)
)
CREATE TABLE "user" (
id SERIAL NOT NULL,
name TEXT,
product_id INTEGER,
PRIMARY KEY (id),
FOREIGN KEY(product_id) REFERENCES product (id)
)
但是我不能执行这个 SQL 代码,由于循环引用它会给我错误。 (而且我至少需要添加一些;)
SQLAlchemy 在我使用时可以毫无问题地创建这些表:
Base.metadata.create_all(engine)
echo=True 生成的 SQL 在日志中可见:
2021-10-18 05:37:24,442 INFO sqlalchemy.engine.Engine select version()
2021-10-18 05:37:24,443 INFO sqlalchemy.engine.Engine [raw sql] {}
2021-10-18 05:37:24,447 INFO sqlalchemy.engine.Engine select current_schema()
2021-10-18 05:37:24,447 INFO sqlalchemy.engine.Engine [raw sql] {}
2021-10-18 05:37:24,449 INFO sqlalchemy.engine.Engine show standard_conforming_strings
2021-10-18 05:37:24,450 INFO sqlalchemy.engine.Engine [raw sql] {}
2021-10-18 05:37:24,454 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2021-10-18 05:37:24,455 INFO sqlalchemy.engine.Engine select relname from pg_class c join pg_namespace n on n.oid=c.relnamespace where pg_catalog.pg_table_is_visible(c.oid) and relname=%(name)s
2021-10-18 05:37:24,456 INFO sqlalchemy.engine.Engine [generated in 0.00073s] {'name': 'product'}
2021-10-18 05:37:24,459 INFO sqlalchemy.engine.Engine select relname from pg_class c join pg_namespace n on n.oid=c.relnamespace where pg_catalog.pg_table_is_visible(c.oid) and relname=%(name)s
2021-10-18 05:37:24,460 INFO sqlalchemy.engine.Engine [cached since 0.004542s ago] {'name': 'user'}2021-10-18 05:37:24,463 INFO sqlalchemy.engine.Engine
CREATE TABLE product (
id SERIAL NOT NULL,
name TEXT,
user_id INTEGER,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
PRIMARY KEY (id)
)
2021-10-18 05:37:24,464 INFO sqlalchemy.engine.Engine [no key 0.00116s] {}
2021-10-18 05:37:24,480 INFO sqlalchemy.engine.Engine
CREATE TABLE "user" (
id SERIAL NOT NULL,
name TEXT,
product_id INTEGER,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
PRIMARY KEY (id)
)
2021-10-18 05:37:24,481 INFO sqlalchemy.engine.Engine [no key 0.00128s] {}
2021-10-18 05:37:24,494 INFO sqlalchemy.engine.Engine ALTER TABLE product ADD FOREIGN KEY(user_id)
REFERENCES "user" (id)
2021-10-18 05:37:24,495 INFO sqlalchemy.engine.Engine [no key 0.00053s] {}
2021-10-18 05:37:24,497 INFO sqlalchemy.engine.Engine ALTER TABLE "user" ADD FOREIGN KEY(product_id) REFERENCES product (id)
2021-10-18 05:37:24,497 INFO sqlalchemy.engine.Engine [no key 0.00047s] {}
2021-10-18 05:37:24,500 INFO sqlalchemy.engine.Engine COMMIT
我的问题是如何获取这条 SQL,它在上面的日志中可见,并且能够在一个事务中创建所有表,作为 Python 字符串(或.sql 文件)?
我希望能够对其进行检查/审查,然后手动将其(或部分)应用到生产服务器。
【问题讨论】:
标签: python python-3.x postgresql sqlalchemy alembic