Release: 1.4.25 | Release Date: September 22, 2021

SQLAlchemy 1.4 Documentation

反映数据库对象

A Table 对象可以被指示从数据库中已经存在的相应数据库架构对象加载关于其自身的信息。此过程称为 反射 。在最简单的情况下,您只需指定表名,即 MetaData 对象,而 autoload_with 参数::

>>> messages = Table('messages', meta, autoload_with=engine)
>>> [c.name for c in messages.columns]
['message_id', 'message_name', 'date']

上面的操作将使用给定的引擎查询数据库以获取有关 messages 表,然后将生成 ColumnForeignKey 以及与此信息相对应的其他对象, Table 对象是用python手工构建的。

当表被反射时,如果一个给定的表通过外键引用另一个表,则为一秒。 Table 对象是在 MetaData 表示连接的对象。下面,假设表格 shopping_cart_items 引用名为的表 shopping_carts . 反映 shopping_cart_items 表的作用是 shopping_carts 还将加载表:

>>> shopping_cart_items = Table('shopping_cart_items', meta, autoload_with=engine)
>>> 'shopping_carts' in meta.tables:
True

这个 MetaData 有一个有趣的“单例”行为,如果您单独请求两个表, MetaData 确保只有一个 Table 对象是为每个不同的表名创建的。这个 Table 构造函数实际上返回给您已经存在的 Table 对象(如果已存在具有给定名称的对象)。如下图所示,我们可以访问已经生成的 shopping_carts 表的名称:

shopping_carts = Table('shopping_carts', meta)

当然,这是一个好主意,可以使用 autoload_with=engine 不管上面的表是什么。这样,如果表的属性尚未加载,则它们将被加载。仅当表尚未加载时,才会对其执行自动加载操作;一旦加载,就会对 Table 不会重新发出任何反射查询。

覆盖反射列

在反射表时,可以用显式值覆盖各个列;这对于指定自定义数据类型、约束(如数据库中可能未配置的主键等)非常方便:

>>> mytable = Table('mytable', meta,
... Column('id', Integer, primary_key=True),   # override reflected 'id' to have primary key
... Column('mydata', Unicode(50)),    # override reflected 'mydata' to be Unicode
... # additional Column objects which require no change are reflected normally
... autoload_with=some_engine)

参见

使用自定义类型和反射 -说明了上述列重写技术如何应用于具有表反射的自定义数据类型的使用。

反射视图

反射系统也可以反射视图。基本用法与表的用法相同:

my_view = Table("some_view", metadata, autoload_with=engine)

上面, my_view 是一个 Table 对象与 Column 对象,表示视图“某些视图”中每个列的名称和类型。

通常,在反射视图时希望至少有主键约束(如果不是外键的话)。视图反射不会推断这些约束。

为此,请使用“重写”技术,显式指定属于主键的一部分或具有外键约束的列:

my_view = Table("some_view", metadata,
                Column("view_id", Integer, primary_key=True),
                Column("related_thing", Integer, ForeignKey("othertable.thing_id")),
                autoload_with=engine
)

同时反射所有表

这个 MetaData 对象还可以获取表列表并反映完整集。这是通过使用 reflect() 方法。调用后,所有定位的表都出现在 MetaData 对象的表字典:

metadata_obj = MetaData()
metadata_obj.reflect(bind=someengine)
users_table = metadata_obj.tables['users']
addresses_table = metadata_obj.tables['addresses']

metadata.reflect() 还提供了清除或删除数据库中所有行的简便方法:

metadata_obj = MetaData()
metadata_obj.reflect(bind=someengine)
for table in reversed(metadata_obj.sorted_tables):
    someengine.execute(table.delete())

带检查员的细颗粒反射

还提供了一个低级接口,它提供了从给定数据库加载模式、表、列和约束描述列表的后端不可知系统。这就是所谓的“检查员”::

from sqlalchemy import create_engine
from sqlalchemy import inspect
engine = create_engine('...')
insp = inspect(engine)
print(insp.get_table_names())
Object Name Description

Inspector

执行数据库架构检查。

class sqlalchemy.engine.reflection.Inspector(bind)

执行数据库架构检查。

检查器充当的反射方法的代理 Dialect ,为以前提取的元数据提供一致的接口和缓存支持。

A Inspector 对象通常是通过 inspect() 函数,它可以传递一个 Engine 或A Connection ::

from sqlalchemy import inspect, create_engine
engine = create_engine('...')
insp = inspect(engine)

在上面的地方, Dialect 与发动机相关联的可选择返回 Inspector 提供特定于方言目标数据库的其他方法的子类。

method sqlalchemy.engine.reflection.Inspector.__init__(bind)

初始化新的 Inspector .

1.4 版后已移除: 上的 Inspector 已弃用,将在将来的版本中删除。请使用 inspect() 上的函数 EngineConnection 为了获得 Inspector .

参数

bind -- 一 Connectable ,这通常是 EngineConnection .

对于特定方言的实例 InspectorInspector.from_engine()

attribute sqlalchemy.engine.reflection.Inspector.default_schema_name

返回当前引擎数据库用户的方言提供的默认架构名称。

例如,这通常是 public 对于PostgreSQL和 dbo 对于SQLServer。

method sqlalchemy.engine.reflection.Inspector.classmethod from_engine(bind)

从给定的引擎或连接构造一个新的方言特定的检查器对象。

1.4 版后已移除: 上的from_engine()方法 Inspector 已弃用,将在将来的版本中删除。请使用 inspect() 上的函数 EngineConnection 为了获得 Inspector .

参数

bind -- 一 Connectable ,这通常是 EngineConnection .

此方法不同于直接调用 Inspector 在那 Dialect 有机会提供特定方言 Inspector 实例,可以提供其他方法。

参见中的示例 Inspector .

method sqlalchemy.engine.reflection.Inspector.get_check_constraints(table_name, schema=None, **kw)

返回有关签入约束的信息 table_name .

给定字符串 table_name 和可选字符串 schema ,将检查约束信息作为具有以下键的dict列表返回:

  • name -检查约束的名称

  • sqltext -check约束的SQL表达式

  • dialect_options -可能存在,也可能不存在;为该检查约束提供了附加方言特定选项的字典

    1.3.8 新版功能.

参数
  • table_name -- 表的字符串名称。对于特殊报价,使用 quoted_name .

  • schema -- 字符串架构名称;如果省略,则使用数据库连接的默认架构。对于特殊报价,使用 quoted_name .

1.1.0 新版功能.

method sqlalchemy.engine.reflection.Inspector.get_columns(table_name, schema=None, **kw)

返回有关中列的信息 table_name .

给定字符串 table_name 和可选字符串 schema ,将列信息作为具有以下键的dict列表返回:

  • name -列的名称

  • type - the type of this column; an instance of TypeEngine

  • nullable -如果列为空或非空,则为布尔标志

  • default -列的服务器默认值-此值作为字符串SQL表达式返回。

  • autoincrement -指示列是自动递增的-这将作为布尔值或“auto”返回

  • comment -(可选)列上的注释。只有一些方言会返回这个键

  • computed -(可选)如果存在,则表示此列由数据库计算。只有一些方言会返回这个键。以dict形式返回:

    • sqltext -用于生成此列的表达式作为字符串SQL表达式返回

    • persisted -(可选)指示列是否存储在表中的布尔值

    1.3.16 新版功能: -增加了对计算反射的支持。

  • identity -(可选)当出现时,它指示此列是生成的始终列。只有一些方言会返回这个键。有关此dict的关键字列表,请参见 Identity .

    1.4 新版功能: -增加了对标识列反射的支持。

  • dialect_options -(可选)带有方言特定选项的dict

参数
  • table_name -- 表的字符串名称。对于特殊报价,使用 quoted_name .

  • schema -- 字符串架构名称;如果省略,则使用数据库连接的默认架构。对于特殊报价,使用 quoted_name .

返回

字典列表,每个字典表示数据库列的定义。

method sqlalchemy.engine.reflection.Inspector.get_foreign_keys(table_name, schema=None, **kw)

返回有关中的外键的信息 table_name .

给定字符串 table_name 和可选字符串 schema ,将外键信息作为带有这些键的dict列表返回:

  • constrained_columns -构成外键的列名列表

  • referred_schema -引用架构的名称

  • referred_table -引用表的名称

  • referred_columns -引用表中与受约束的列相对应的列名列表

  • name -外键约束的可选名称。

参数
  • table_name -- 表的字符串名称。对于特殊报价,使用 quoted_name .

  • schema -- 字符串架构名称;如果省略,则使用数据库连接的默认架构。对于特殊报价,使用 quoted_name .

method sqlalchemy.engine.reflection.Inspector.get_indexes(table_name, schema=None, **kw)

返回有关中索引的信息 table_name .

给定字符串 table_name 和可选字符串 schema ,将索引信息作为具有以下键的dict列表返回:

  • name -索引的名称

  • column_names -按顺序列出列名

  • unique -布尔型

  • column_sorting -可选的dict将列名映射到排序关键字的元组,其中可能包括 ascdescnulls_firstnulls_last .

    1.3.5 新版功能.

  • dialect_options -方言特定索引选项的dict。可能不是所有的方言都有。

    1.0.0 新版功能.

参数
  • table_name -- 表的字符串名称。对于特殊报价,使用 quoted_name .

  • schema -- 字符串架构名称;如果省略,则使用数据库连接的默认架构。对于特殊报价,使用 quoted_name .

method sqlalchemy.engine.reflection.Inspector.get_pk_constraint(table_name, schema=None, **kw)

返回有关上主键约束的信息 table_name .

给定字符串 table_name 和可选字符串 schema ,将主键信息作为具有以下键的字典返回:

  • constrained_columns -构成主键的列名列表

  • name -主键约束的可选名称。

参数
  • table_name -- 表的字符串名称。对于特殊报价,使用 quoted_name .

  • schema -- 字符串架构名称;如果省略,则使用数据库连接的默认架构。对于特殊报价,使用 quoted_name .

method sqlalchemy.engine.reflection.Inspector.get_schema_names()

返回所有架构名称。

method sqlalchemy.engine.reflection.Inspector.get_sequence_names(schema=None)

返回中的所有序列名 schema .

参数

schema -- 可选,从非默认架构中检索名称。对于特殊报价,使用 quoted_name .

method sqlalchemy.engine.reflection.Inspector.get_sorted_table_and_fkc_names(schema=None)

返回特定架构中引用的依赖项排序表和外键约束名。

这将产生2个 (tablename, [(tname, fkname), (tname, fkname), ...]) 由创建顺序中的表名组成,与未检测到属于循环的外键约束名分组。最后一个元素是 (None, [(tname, fkname), (tname, fkname), ..]) 它将由剩余的外键约束名组成,这些约束名将根据表之间的依赖关系在事实之后需要单独的创建步骤。

1.0.- 新版功能.

参见

Inspector.get_table_names()

sort_tables_and_constraints() -类似的方法,在已经给定的 MetaData .

method sqlalchemy.engine.reflection.Inspector.get_table_comment(table_name, schema=None, **kw)

返回有关的表注释的信息 table_name .

给定字符串 table_name 和可选字符串 schema ,将表注释信息作为带有以下键的字典返回:

  • text -

    注释文本。

加薪 NotImplementedError 不支持评论的方言。

1.2 新版功能.

method sqlalchemy.engine.reflection.Inspector.get_table_names(schema=None)

返回特定架构中引用的所有表名。

名称只能是实表,不能是视图。而是使用返回视图 Inspector.get_view_names() 方法。

参数

schema -- 架构名称。如果 schema 留在 None ,将使用数据库的默认架构,否则将搜索命名架构。如果数据库不支持命名架构,则如果 schema 不是作为 None . 对于特殊报价,使用 quoted_name .

method sqlalchemy.engine.reflection.Inspector.get_table_options(table_name, schema=None, **kw)

返回在创建给定名称的表时指定的选项字典。

这当前包括一些应用于MySQL表的选项。

参数
  • table_name -- 表的字符串名称。对于特殊报价,使用 quoted_name .

  • schema -- 字符串架构名称;如果省略,则使用数据库连接的默认架构。对于特殊报价,使用 quoted_name .

method sqlalchemy.engine.reflection.Inspector.get_temp_table_names()

返回当前绑定的临时表名列表。

大多数方言都不支持此方法;目前只有sqlite实现它。

1.0.0 新版功能.

method sqlalchemy.engine.reflection.Inspector.get_temp_view_names()

返回当前绑定的临时视图名称列表。

大多数方言都不支持此方法;目前只有sqlite实现它。

1.0.0 新版功能.

method sqlalchemy.engine.reflection.Inspector.get_unique_constraints(table_name, schema=None, **kw)

返回有关中唯一约束的信息 table_name .

给定字符串 table_name 和可选字符串 schema ,返回唯一约束信息作为具有以下键的dict列表:

  • name -唯一约束的名称

  • column_names -按顺序列出列名

参数
  • table_name -- 表的字符串名称。对于特殊报价,使用 quoted_name .

  • schema -- 字符串架构名称;如果省略,则使用数据库连接的默认架构。对于特殊报价,使用 quoted_name .

method sqlalchemy.engine.reflection.Inspector.get_view_definition(view_name, schema=None)

返回的定义 view_name .

参数

schema -- 可选,从非默认架构中检索名称。对于特殊报价,使用 quoted_name .

method sqlalchemy.engine.reflection.Inspector.get_view_names(schema=None)

返回所有视图名称 schema .

参数

schema -- 可选,从非默认架构中检索名称。对于特殊报价,使用 quoted_name .

method sqlalchemy.engine.reflection.Inspector.has_sequence(sequence_name, schema=None)

如果后端具有给定名称的表,则返回True。

参数
  • sequence_name -- 要检查的表的名称

  • schema -- 要查询的架构名称,如果不是默认架构。

1.4 新版功能.

method sqlalchemy.engine.reflection.Inspector.has_table(table_name, schema=None)

如果后端具有给定名称的表,则返回True。

参数
  • table_name -- 要检查的表的名称

  • schema -- 要查询的架构名称,如果不是默认架构。

1.4 新版功能: -The Inspector.has_table() 方法取代了 Engine.has_table() 方法。

method sqlalchemy.engine.reflection.Inspector.reflect_table(table, include_columns, exclude_columns=(), resolve_fks=True, _extend_on=None)

给出了一个 Table 对象,加载基于内省的内部构造。

这是大多数方言用来产生表反射的基本方法。直接使用如下:

from sqlalchemy import create_engine, MetaData, Table
from sqlalchemy import inspect

engine = create_engine('...')
meta = MetaData()
user_table = Table('user', meta)
insp = inspect(engine)
insp.reflect_table(user_table, None)

在 1.4 版更改: 更名为 reflecttablereflect_table

参数
  • table -- 一 Table 实例。

  • include_columns -- 要包含在反射过程中的字符串列名列表。如果 None ,将反射所有列。

method sqlalchemy.engine.reflection.Inspector.reflecttable(*args, **kwargs)

请参见反射表。此方法名已弃用

1.4 版后已移除: 这个 Inspector.reflecttable() 方法在SQLAlchemy的1.x系列中被认为是遗留的,并将在2.0中删除。这个 Inspector.reflecttable() 方法已重命名为 Inspector.reflect_table() . 此不推荐使用的别名将在将来的版本中删除。(SQLAlchemy 2.0的背景: 迁移到Alchemy

使用数据库不可知类型反映

当映射表的列时,使用 Table.autoload_with 的参数 Table 或者 Inspector.get_columns() 一种方法 Inspector ,则数据类型将尽可能特定于目标数据库。这意味着,如果MySQL数据库反映了“整数”数据类型,则该类型将由 sqlalchemy.dialects.mysql.INTEGER 类,它包括特定于MySQL的属性,如“display_width”。或在PostgreSQL上,是特定于PostgreSQL的数据类型,例如 sqlalchemy.dialects.postgresql.INTERVALsqlalchemy.dialects.postgresql.ENUM 可能会被退回。

反射有一个用例,即给定的 Table 将被转移到不同的供应商数据库。为了适应这个用例,有一种技术可以在飞翔上将这些特定于供应商的数据类型转换为SQLAlChemy后端无关的数据类型的实例,例如上面的类型 IntegerIntervalEnum 。这可以通过使用 DDLEvents.column_reflect() 事件与 TypeEngine.as_generic() 方法。

在MySQL中给定表(之所以选择,是因为MySQL有许多特定于供应商的数据类型和选项):

CREATE TABLE IF NOT EXISTS my_table (
    id INTEGER PRIMARY KEY AUTO_INCREMENT,
    data1 VARCHAR(50) CHARACTER SET latin1,
    data2 MEDIUMINT(4),
    data3 TINYINT(2)
)

上表包括仅限MySQL的整数类型 MEDIUMINTTINYINT 以及一个 VARCHAR 这包括仅限MySQL的 CHARACTER SET 选项。如果我们正常地反映这个表,它会产生一个 Table 对象,该对象将包含那些特定于MySQL的数据类型和选项:

>>> from sqlalchemy import MetaData, Table, create_engine
>>> mysql_engine = create_engine("mysql://scott:tiger@localhost/test")
>>> metadata_obj = MetaData()
>>> my_mysql_table = Table("my_table", metadata_obj, autoload_with=mysql_engine)

上面的示例将上面的表架构反映到一个新的 Table 对象。出于演示目的,我们可以使用以下命令打印特定于MySQL的“CREATE TABLE”语句 CreateTable 构造:

>>> from sqlalchemy.schema import CreateTable
>>> print(CreateTable(my_mysql_table).compile(mysql_engine))
CREATE TABLE my_table ( id INTEGER(11) NOT NULL AUTO_INCREMENT, data1 VARCHAR(50) CHARACTER SET latin1, data2 MEDIUMINT(4), data3 TINYINT(2), PRIMARY KEY (id) )ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

上面,保留了特定于MySQL的数据类型和选项。如果我们想要一个 Table 我们可以干净利落地将其转移到另一家数据库供应商,替换特殊的数据类型 sqlalchemy.dialects.mysql.MEDIUMINTsqlalchemy.dialects.mysql.TINYINT 使用 Integer ,我们可以选择“泛化”该表上的数据类型,或者以任何我们想要的方式更改它们,方法是使用 DDLEvents.column_reflect() 事件。自定义处理程序将利用 TypeEngine.as_generic() 方法将上述特定于MySQL的类型对象转换为泛型对象,方法是将 "type" 传递给事件处理程序的列字典条目中的条目。本词典的格式在 Inspector.get_columns()

>>> from sqlalchemy import event
>>> metadata_obj = MetaData()

>>> @event.listens_for(metadata_obj, "column_reflect")
>>> def genericize_datatypes(inspector, tablename, column_dict):
...     column_dict["type"] = column_dict["type"].as_generic()

>>> my_generic_table = Table("my_table", metadata_obj, autoload_with=mysql_engine)

我们现在有了一个新的 Table 它是通用的,并且使用 Integer 用于这些数据类型。例如,我们现在可以在PostgreSQL数据库上发出“CREATE TABLE”语句:

>>> pg_engine = create_engine("postgresql://scott:tiger@localhost/test", echo=True)
>>> my_generic_table.create(pg_engine)
CREATE TABLE my_table ( id SERIAL NOT NULL, data1 VARCHAR(50), data2 INTEGER, data3 INTEGER, PRIMARY KEY (id) )

还请注意,SQLAlChemy通常会对其他行为做出不错的猜测,比如MySQL AUTO_INCREMENT 指令在PostgreSQL中使用 SERIAL 自动递增数据类型。

1.4 新版功能: 添加了 TypeEngine.as_generic() 方法,并额外改进了 DDLEvents.column_reflect() 事件,以便它可以应用于 MetaData 为方便起见反对。

反射的局限性

需要注意的是,反射过程会重新创建 Table 仅使用关系数据库中表示的信息的元数据。根据定义,此进程无法还原数据库中实际未存储的架构的各个方面。反射不可用的状态包括但不限于:

  • 客户端默认值,可以是python函数,也可以是使用 default 关键字 Column (注意,这与 server_default 这是通过反射可以得到的)。

  • 列信息,例如可能放入 Column.info 词典

  • 的值 .quote 设置为 ColumnTable

  • 特定的联系 Sequence 用给定的 Column

在许多情况下,关系数据库还以与SQLAlchemy中指定的格式不同的格式报告表元数据。这个 Table 从反射返回的对象不能总是依赖于生成与原始python定义的相同的ddl Table 物体。出现这种情况的区域包括服务器默认值、与列关联的序列以及有关约束和数据类型的各种特性。服务器端默认值可以用CAST指令返回(通常PostgreSQL将包括 ::<type> 或不同于最初指定的引用模式。

另一类限制包括模式结构,反射仅部分定义或尚未定义。最近对反射的改进允许反射视图、索引和外键选项等内容。在撰写本文时,检查约束、表注释和触发器等结构不会反映出来。

Previous: 用元数据描述数据库 Next: 列插入/更新默认值