我正在尝试使用python将多行插入到SQLite DB中。我有三张桌子:
UniversityA:
UniversityB:
CourseMap:
我可以使用以下语法轻松地将单个记录添加到CourseMap表中:
cur.execute('INSERT INTO CourseMap (universityA_id, universityB_id, is_flagged) VALUES ( (SELECT id from universityA WHERE course_code=301 AND course_prefix="AERO"), (SELECT id from universityB WHERE course_code=101 AND course_prefix="ARCH"), 0)')
但是当我尝试将此语句合并到列表中以使用executemany()
执行多个插入时,我收到语法错误:
equivs = [
((SELECT id from universityA WHERE course_code=301 AND course_prefix="AERO"), (SELECT id from universityB WHERE course_code=101 AND course_prefix="ARCH"), 0),
((SELECT id from universityA WHERE course_code=301 AND course_prefix="AERO"), (SELECT id from universityB WHERE course_code=101 AND course_prefix="ARCH"), 0),
((SELECT id from universityA WHERE course_code=301 AND course_prefix="AERO"), (SELECT id from universityB WHERE course_code=101 AND course_prefix="ARCH"), 0)
]
# Fill the table
cur.executemany('INSERT INTO courseMap (universityA_id, universityB_id, is_flagged) VALUES (?,?,?)', equivs)
我得到的错误是“语法错误:语法无效”,插入符号位于第一个插入符号的布尔is_flagged
值之前。
我在executemany()
的多重插入语法中遗漏了什么?我的SQLite 3版本是3.10.0。
答案 0 :(得分:1)
您不能将DDL / DML SQL语句(即SELECT
语句)作为参数传递。事实上,这是参数化的非常原因!回想一下Bobby Tables注入问题。参数设计为每次执行的调用接收单个绑定值。
根据您的需要,考虑一个联合交叉连接的已执行语句,您可以使用逗号分隔的SELECT
语句或显式CROSS JOIN
来完成。以下假设每个查询SELECT
仅返回一个 id 值),否则您将附加笛卡尔交叉产品。
INSERT INTO CourseMap (universityA_id, universityB_id, is_flagged)
SELECT * FROM
(SELECT id from universityA WHERE course_code=301 AND course_prefix="AERO"),
(SELECT id from universityB WHERE course_code=101 AND course_prefix="ARCH"), (SELECT 0)
UNION ALL
SELECT * FROM
(SELECT id from universityA WHERE course_code=301 AND course_prefix="AERO"),
(SELECT id from universityB WHERE course_code=101 AND course_prefix="ARCH"), (SELECT 0)
UNION ALL
SELECT * FROM
(SELECT id from universityA WHERE course_code=301 AND course_prefix="AERO"),
(SELECT id from universityB WHERE course_code=101 AND course_prefix="ARCH"), (SELECT 0)
除此之外 - 重新考虑这个模式,因为像两个大学那样的重复结构化表偏离了最佳实践,因为两个表都可以附加到一个带有指示符字段(“A”或“B”)的表中,以便有效存储,查询和缩放。
答案 1 :(得分:1)
在SQL中,您可以在VALUES子句中使用多个元组;这需要多次编写子查询:
INSERT INTO CourseMap (universityA_id, universityB_id, is_flagged)
VALUES ( (SELECT ...), (SELECT ...), 0),
( (SELECT ...), (SELECT ...), 0),
( (SELECT ...), (SELECT ...), 0);
Python executemany()
使用不同的参数值多次执行相同的语句。因此,您唯一可以更改的是子查询中使用的实际值:
args = [ (301, "AERO", 101, "ARCH"), (...) ]
db.executemany("""INSERT INTO CourseMap (universityA_id, universityB_id, is_flagged)
VALUES ( (SELECT id from universityA WHERE course_code=? AND course_prefix=?),
(SELECT id from universityB WHERE course_code=? AND course_prefix=?),
0)""", args)
如果这不是您想要更改的内容,则必须单独执行子查询,并将结果提供给executemany
。