我有一个已经存在的表:
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))
)
Run Code Online (Sandbox Code Playgroud)
我通过运行这个创建了这个表:
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)
Run Code Online (Sandbox Code Playgroud)
它第一次工作,我能够创建表.但是,第二次我遇到了这个错误:
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.
Run Code Online (Sandbox Code Playgroud)
这是有道理的,因为该表users已经存在.我能够看到表是否存在如下:
TABLE_EXISTS = CONN.dialect.has_table(CONN, "users")
Run Code Online (Sandbox Code Playgroud)
但是,我如何实际获取现有的表对象?我在文档中的任何地方都找不到这个.请帮忙.
Aza*_*kov 13
我们在这里有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']
Run Code Online (Sandbox Code Playgroud)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)
Run Code Online (Sandbox Code Playgroud)假设我们保留了反射表,如果之前通过将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)
Run Code Online (Sandbox Code Playgroud)哪一个选择?取决于你的用例,但我更喜欢第二个,因为它看起来你没有使用反射,也是最简单的修改:只是从MetaData初始化程序中删除标志.
我们总是可以在MetaData使用MetaData.reflect方法初始化对象后进行反射:
META_DATA.reflect()
Run Code Online (Sandbox Code Playgroud)
我们也可以指定哪些表用only参数反映(可以是任何可迭代的str对象):
META_DATA.reflect(only=['users'])
Run Code Online (Sandbox Code Playgroud)
和许多更多.
这对我来说非常有效 -
import sqlalchemy as db
engine = db.create_engine("your_connection_string")
meta_data = db.MetaData(bind=engine)
db.MetaData.reflect(meta_data)
USERS = meta_data.tables['users']
# View the columns present in the users table
print(USERS.columns)
# You can run sqlalchemy queries
query = db.select([
USERS.c.id,
USERS.c.first_name,
USERS.c.last_name,
])
result = engine.execute(query).fetchall()
Run Code Online (Sandbox Code Playgroud)
请注意,不推荐使用reflect参数 in Metadata(bind=engine, reflect=True),并将在未来版本中删除。上面的代码就解决了这个问题。