如何获取 SQL 查询的元数据?
How to get metadata of an SQL query?
我知道如何使用 SQL Alchemy 读取现有数据库 table 的元数据:
meta = MetaData(bind=engine)
meta.reflect(schema="schema_name", views=True, resolve_fks=False)
res = meta.tables["table_name"]
问题:
如何获取 SQL 查询 (select * from tab1 join tab2 on tab1.id = tab2.id
) 的元数据或列类型?
这有点 hack,但一种方法是使用查询创建临时 table,然后反映 table。 mssql 示例:
with engine.begin() as con:
original_query = """\
SELECT c.name as firstname, p.lastname
FROM parent p INNER JOIN child c
ON c.parent_id = p.id
"""
con.execute(
sa.text(f"SELECT TOP 1 q.* INTO #tmp FROM ({original_query}) q")
)
con.commit()
tmp = sa.Table("#tmp", sa.MetaData(), autoload_with=engine)
for col in tmp.columns:
print(repr(col))
"""console output:
Column('firstname', NVARCHAR(length=100), table=<#tmp>, nullable=False)
Column('lastname', VARCHAR(length=50, collation='SQL_Latin1_General_CP1_CI_AS'), table=<#tmp>)
"""
当您使用 sqlalchemy Core(不是 ORM)执行查询时,您将返回一个 ResultProxy
对象的实例。
ResultProxy
是底层 DBAPI 游标的包装器,如果您的代码使用的 RDBMS 驱动程序是按照 PEP 249 -- Python Database API Specification v2.0 or PEP 248 -- Python Database API Specification v1.0, you should be access the underlying ResultProxy.cursor
object, which in turn should have .description
属性.
实现的
因此,类似于下面的代码应该可以正常工作:
res = session.execute(my_sql_statement)
columns = res.cursor.description
for col in columns:
print(col.name, col.type_code, col.display_size, col.internal_size, col.precision, col.scale, col.null_ok)
对于像 SELECT "user".id AS user_id, "user".name AS user_name, "group".id AS group_id, "group".name AS group_name FROM "user" JOIN user_group AS user_group_1 ON "user".id = user_group_1.user_id JOIN "group" ON "group".id = user_group_1.group_id
这样的小查询,这是我看到的 PostgreSQL 数据库的输出:
user_id 23 None 4 None None None
user_name 1043 None 250 None None None
group_id 23 None 4 None None None
group_name 1043 None 250 None None None
我知道如何使用 SQL Alchemy 读取现有数据库 table 的元数据:
meta = MetaData(bind=engine)
meta.reflect(schema="schema_name", views=True, resolve_fks=False)
res = meta.tables["table_name"]
问题:
如何获取 SQL 查询 (select * from tab1 join tab2 on tab1.id = tab2.id
) 的元数据或列类型?
这有点 hack,但一种方法是使用查询创建临时 table,然后反映 table。 mssql 示例:
with engine.begin() as con:
original_query = """\
SELECT c.name as firstname, p.lastname
FROM parent p INNER JOIN child c
ON c.parent_id = p.id
"""
con.execute(
sa.text(f"SELECT TOP 1 q.* INTO #tmp FROM ({original_query}) q")
)
con.commit()
tmp = sa.Table("#tmp", sa.MetaData(), autoload_with=engine)
for col in tmp.columns:
print(repr(col))
"""console output:
Column('firstname', NVARCHAR(length=100), table=<#tmp>, nullable=False)
Column('lastname', VARCHAR(length=50, collation='SQL_Latin1_General_CP1_CI_AS'), table=<#tmp>)
"""
当您使用 sqlalchemy Core(不是 ORM)执行查询时,您将返回一个 ResultProxy
对象的实例。
ResultProxy
是底层 DBAPI 游标的包装器,如果您的代码使用的 RDBMS 驱动程序是按照 PEP 249 -- Python Database API Specification v2.0 or PEP 248 -- Python Database API Specification v1.0, you should be access the underlying ResultProxy.cursor
object, which in turn should have .description
属性.
因此,类似于下面的代码应该可以正常工作:
res = session.execute(my_sql_statement)
columns = res.cursor.description
for col in columns:
print(col.name, col.type_code, col.display_size, col.internal_size, col.precision, col.scale, col.null_ok)
对于像 SELECT "user".id AS user_id, "user".name AS user_name, "group".id AS group_id, "group".name AS group_name FROM "user" JOIN user_group AS user_group_1 ON "user".id = user_group_1.user_id JOIN "group" ON "group".id = user_group_1.group_id
这样的小查询,这是我看到的 PostgreSQL 数据库的输出:
user_id 23 None 4 None None None
user_name 1043 None 250 None None None
group_id 23 None 4 None None None
group_name 1043 None 250 None None None