将二维数组插入 Table 而不导入 sqlalchemy Table 列等对象?
Insert 2d Array into Table without importing sqlalchemy Table Column etc objects?
我正在 Python 中编写一个应用程序,其中一部分包含需要与 MySQL 数据库交互的 api。从 sqlite3 转到 sqlalchemy,工作流程的某些部分对我来说似乎有点过于冗长,不确定是否有简化流程的方法。
Sqlite3 工作流
如果我想从 Python 中获取一个列表并将其插入到 table 中,我会使用下面的方法
# connect to db
con = sqlite3.connect(":memory:")
cur = con.cursor()
# create table
cur.execute("create table lang (name, first_appeared)")
# prep data to be inserted
lang_list = [
("Fortran", 1957),
("Python", 1991),
("Go", 2009)
]
# add data to table
cur.executemany("insert into lang values (?, ?)", lang_list)
con.commit()
SqlAlchemy 工作流
在 sqlalchemy 中,我必须导入 Table、列、字符串、整数元数据等对象并执行类似这样的操作
# connect to db
engine = create_engine("mysql+pymysql://....")
# (re)create table, seems like this needs to be
# done every time I want to insert anything into it?
metadata = MetaData()
metadata.reflect(engine, only=['lang'])
table = Table('lang', meta,
Column('name', String),
Column('first_appeared', Integer),
autoload=True, autoload_with=engine)
# prep data to be inserted
lang_list = [
{'first_appeared': 1957, 'name': 'Fortran'},
{'first_appeared': 1991, 'name': 'Python'},
{'first_appeared': 2009, 'name': 'Go'}
]
# add data to table
engine.execute(table.insert(), lang_list)
问题
有没有一种方法可以将数据添加到 sqlalchemy 中的 table 而无需使用元数据、Table 和 Column 对象?特别是只使用连接、语句和列表,所以需要执行的所有 运行 都是 execute?
我想在 Python 中做尽可能少的 sql 工作,这对我来说似乎太冗长了。
可能的不同路线
我可以使用列表理解将列表转换为一个长的 INSERT 语句,因此最终查询如下所示
statement = """
INSERT INTO lang
VALUES ("Fortran", 1957),
("Python", 1991),
("Go", 2009);"""
con.execute(statement)
- 但不确定 sqlalchemy 是否有一个简单的等同于 sqlite3 的 executemany 用于插入和列表,而不必每次都合并所有这些对象才能这样做。
如果列表理解 -> 大语句 -> execute
是在这方面最简单的方法,那很好,我只是 sqlalchemy 的新手并且一直在使用 sqlite3 到此为止。
为了澄清,在我的实际代码中,连接已经在使用适当的数据库并且 table 本身存在 - 上面使用的代码片段与实际的 data/tables 我无关我和我一起工作只是为了 reproducibility/testing。当我不得不用导入的对象重建 tables 只是为了添加到它们时,添加到它们的工作流程感觉很冗长。
我不知道 SQLite 允许弱类型列,正如您在示例中所展示的那样。据我所知,大多数其他数据库 mysql 和 postgresql 都需要强类型列。通常 table 元数据会被反映或 pre-defined 并使用。有点像静态类型语言中的类型定义。 SQLAlchemy 将使用这些类型来确定如何正确格式化 SQL 语句。 IE。用引号包裹字符串而不用引号包裹整数。
在您的 mysql 示例中,您应该能够直接使用 table 元数据和 metadata.tables["lang"]
,他们称之为 reflecting-all-tables-at-once in the docs. This assumes the table is already defined in the mysql database. You only need to define the table columns if you need to override the reflected table's definition, as they do in the overriding-reflected-columns 文档。
文档指出这应该使用 executemany,如果您从已经定义它的数据库中反射 table 应该可以工作:
engine = create_engine("mysql+pymysql://....")
metadata = MetaData()
# Pull in table definitions from database, only lang table.
metadata.reflect(engine, only=['lang'])
# prep data to be inserted
lang_list = [
{'first_appeared': 1957, 'name': 'Fortran'},
{'first_appeared': 1991, 'name': 'Python'},
{'first_appeared': 2009, 'name': 'Go'}
]
# add data to table
engine.execute(metadata.tables["lang"].insert(), lang_list)
我正在 Python 中编写一个应用程序,其中一部分包含需要与 MySQL 数据库交互的 api。从 sqlite3 转到 sqlalchemy,工作流程的某些部分对我来说似乎有点过于冗长,不确定是否有简化流程的方法。
Sqlite3 工作流
如果我想从 Python 中获取一个列表并将其插入到 table 中,我会使用下面的方法
# connect to db
con = sqlite3.connect(":memory:")
cur = con.cursor()
# create table
cur.execute("create table lang (name, first_appeared)")
# prep data to be inserted
lang_list = [
("Fortran", 1957),
("Python", 1991),
("Go", 2009)
]
# add data to table
cur.executemany("insert into lang values (?, ?)", lang_list)
con.commit()
SqlAlchemy 工作流
在 sqlalchemy 中,我必须导入 Table、列、字符串、整数元数据等对象并执行类似这样的操作
# connect to db
engine = create_engine("mysql+pymysql://....")
# (re)create table, seems like this needs to be
# done every time I want to insert anything into it?
metadata = MetaData()
metadata.reflect(engine, only=['lang'])
table = Table('lang', meta,
Column('name', String),
Column('first_appeared', Integer),
autoload=True, autoload_with=engine)
# prep data to be inserted
lang_list = [
{'first_appeared': 1957, 'name': 'Fortran'},
{'first_appeared': 1991, 'name': 'Python'},
{'first_appeared': 2009, 'name': 'Go'}
]
# add data to table
engine.execute(table.insert(), lang_list)
问题
有没有一种方法可以将数据添加到 sqlalchemy 中的 table 而无需使用元数据、Table 和 Column 对象?特别是只使用连接、语句和列表,所以需要执行的所有 运行 都是 execute?
我想在 Python 中做尽可能少的 sql 工作,这对我来说似乎太冗长了。
可能的不同路线
我可以使用列表理解将列表转换为一个长的 INSERT 语句,因此最终查询如下所示
statement = """
INSERT INTO lang
VALUES ("Fortran", 1957),
("Python", 1991),
("Go", 2009);"""
con.execute(statement)
- 但不确定 sqlalchemy 是否有一个简单的等同于 sqlite3 的 executemany 用于插入和列表,而不必每次都合并所有这些对象才能这样做。
如果列表理解 -> 大语句 -> execute
是在这方面最简单的方法,那很好,我只是 sqlalchemy 的新手并且一直在使用 sqlite3 到此为止。
为了澄清,在我的实际代码中,连接已经在使用适当的数据库并且 table 本身存在 - 上面使用的代码片段与实际的 data/tables 我无关我和我一起工作只是为了 reproducibility/testing。当我不得不用导入的对象重建 tables 只是为了添加到它们时,添加到它们的工作流程感觉很冗长。
我不知道 SQLite 允许弱类型列,正如您在示例中所展示的那样。据我所知,大多数其他数据库 mysql 和 postgresql 都需要强类型列。通常 table 元数据会被反映或 pre-defined 并使用。有点像静态类型语言中的类型定义。 SQLAlchemy 将使用这些类型来确定如何正确格式化 SQL 语句。 IE。用引号包裹字符串而不用引号包裹整数。
在您的 mysql 示例中,您应该能够直接使用 table 元数据和 metadata.tables["lang"]
,他们称之为 reflecting-all-tables-at-once in the docs. This assumes the table is already defined in the mysql database. You only need to define the table columns if you need to override the reflected table's definition, as they do in the overriding-reflected-columns 文档。
文档指出这应该使用 executemany,如果您从已经定义它的数据库中反射 table 应该可以工作:
engine = create_engine("mysql+pymysql://....")
metadata = MetaData()
# Pull in table definitions from database, only lang table.
metadata.reflect(engine, only=['lang'])
# prep data to be inserted
lang_list = [
{'first_appeared': 1957, 'name': 'Fortran'},
{'first_appeared': 1991, 'name': 'Python'},
{'first_appeared': 2009, 'name': 'Go'}
]
# add data to table
engine.execute(metadata.tables["lang"].insert(), lang_list)