使用SQLAlchemy MetaData获取现有表

时间:2017-05-26 04:48:35

标签: python sqlalchemy

我有一张已经存在的表:

USERS_TABLE = Table("users", META_DATA,
                    Column("id", Integer, Sequence("user_id_seq"), primary_key=True),
                    Column("first_name", String(255)),
                    Column("last_name", String(255))
                   )

我通过运行这个来创建这个表:

CONN = create_engine(DB_URL, client_encoding="UTF-8")
META_DATA = MetaData(bind=CONN, reflect=True)
# ... table code
META_DATA.create_all(CONN, checkfirst=True)

它第一次工作,我能够创建表。但是,第二次我得到了这个错误:

sqlalchemy.exc.InvalidRequestError: Table 'users' is already defined for this MetaData instance.  Specify 'extend_existing=True' to redefine options and columns on an existing Table object.

这是有道理的,因为表users已经存在。我能够看到表格是否存在:

TABLE_EXISTS = CONN.dialect.has_table(CONN, "users")

但是,我如何实际获取现有的表对象?我在文档中的任何地方都找不到这个。请帮忙。

3 个答案:

答案 0 :(得分:11)

我们在这里有3种不同的方法:

  • 假设已经创建了所需的表,反映了它们并获得了MetaData.tables字典字段,如

    from sqlalchemy import MetaData, create_engine
    
    CONN = create_engine(DB_URL, client_encoding="UTF-8")
    
    META_DATA = MetaData(bind=CONN, reflect=True)
    
    USERS_TABLE = META_DATA.tables['users']
    
  • reflect对象初始化中删除MetaData标志,因为我们不使用它,而且 - 尝试创建已经反映过的表:

    from sqlalchemy import MetaData, Table, Column, Integer, String, Sequence, create_engine
    
    CONN = create_engine('sqlite:///db.sql')
    
    META_DATA = MetaData(bind=CONN)
    
    USERS_TABLE = Table("users", META_DATA,
                        Column("id", Integer, Sequence("user_id_seq"), primary_key=True),
                        Column("first_name", String(255)),
                        Column("last_name", String(255))
                        )
    
    META_DATA.create_all(CONN, checkfirst=True)
    
  • 假设我们通过将Table对象初始值设定项keep_existing标记设置为True来创建以前创建的反射表:

    from sqlalchemy import MetaData, Table, Column, Integer, String, Sequence, create_engine
    
    CONN = create_engine('sqlite:///db.sql')
    
    META_DATA = MetaData(bind=CONN, reflect=True)
    
    USERS_TABLE = Table("users", META_DATA,
                        Column("id", Integer, Sequence("user_id_seq"), primary_key=True),
                        Column("first_name", String(255)),
                        Column("last_name", String(255)),
                        keep_existing=True
                        )
    
    META_DATA.create_all(CONN, checkfirst=True)
    

选择哪一个?取决于你的用例,但我更喜欢第二个,因为它看起来你没有使用反射,也是最简单的修改:只需从MetaData初始化程序中删除标记。

P上。 S上。

我们总是可以在使用MetaData.reflect方法初始化MetaData对象后进行反射:

META_DATA.reflect()

我们也可以使用only参数(可能是iterablestr个对象)来指定要反映的表格:

META_DATA.reflect(only=['users'])

many more

答案 1 :(得分:0)

__table_args__ = {'extend_existing': True}

__tablename__下方

答案 2 :(得分:0)

我尝试单独使用checkfirst=True,但是发现在停止给我extend_existing之前,我还必须添加sqlalchemy.exc.InvalidRequestError

        metaData = MetaData(bind=engine, reflect=True)  

        with engine.connect() as connection:

            for dataItem in dataItemList:
                metaData.reflect()
                db.Table('roles_users',
                db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
                db.Column('role_id', db.Integer(), db.ForeignKey('role.id')),
                Column("data_value", String(255)),
                extend_existing=True)
                metaData.create_all(connection, checkfirst=True)