能否在循环中连续执行两次SQL INSERT实现关联表数据插入?
可以实现,只要注意以下几个要点即可:
- 自增ID的获取要准确
不同数据库有不同的官方推荐方法获取当前会话最后插入的自增ID,比如:
- MySQL用
2925232,或者对应语言驱动封装的方法(比如Python的pymysql中用cursor.lastrowid) - PostgreSQL在INSERT语句后加
RETURNING tree_header_id直接返回ID - SQL Server用
SCOPE_IDENTITY()
绝对不要用SELECT MAX(tree_header_id) FROM tree_header的方式取ID,高并发场景下会拿到其他会话插入的ID,导致关联错误。
- 多所有者场景要调整遍历逻辑
如果和示例数据一样,一个树种对应多个所有者,不要重复插入相同的树种到tree_header表,应该插入一次主表拿到ID后,循环该树种对应的所有所有者批量插入明细表,避免主表产生冗余数据。 - 加事务保证数据一致性
把同一次循环的两次插入操作放在同一个事务中,只要有任意一步执行失败就回滚整个事务,避免出现主表插了明细表没插,或者反过来的数据不一致问题。
附Python操作MySQL的参考实现代码:
import pymysql conn = pymysql.connect(host='你的数据库地址', user='用户名', password='密码', database='库名') cursor = conn.cursor() trees = [ {"t_type": "magnolia", "t_owner": ["Bill"]}, {"t_type": "spruce", "t_owner": ["Susan", "Roger"]} ] for tree in trees: tree_type = tree["t_type"] tree_owners = tree["t_owner"] # 开启事务 conn.begin() try: # 插入主表 cursor.execute("INSERT INTO tree_header(tree_type) VALUES (%s)", (tree_type,)) # 获取刚插入的自增ID last_header_id = cursor.lastrowid # 插入明细表 for owner in tree_owners: cursor.execute("INSERT INTO tree_detail(tree_id, tree_owner) VALUES (%s, %s)", (last_header_id, owner)) # 全部执行成功提交事务 conn.commit() except Exception as e: # 出错回滚 conn.rollback() print(f"插入{tree_type}相关数据失败:{e}") cursor.close() conn.close()
如果你的单次循环输出就是一个树种对应一个所有者,直接去掉内层的所有者循环即可,完全符合你给出的逻辑。
内容的提问来源于stack exchange,提问作者uncrayon
相关产品推荐
相关产品推荐

