如何将含列表型配料与步骤的食谱JSON数据逐行导入MySQL表
解决食谱JSON数据迁移到MySQL的分步指南
嘿,作为刚接触SQL和JSON的新手,别担心,这个问题其实很清晰,咱们一步步来搞定它~
首先要明确:配料和步骤是列表形式的多行内容,不能直接塞进主食谱表的一个字段里——这样不仅违反数据库设计的归一化原则,后续想单独查询某步骤、统计配料使用率都会超级麻烦。正确的做法是用「主表+关联子表」的结构来存储。
1. 先设计MySQL表结构
咱们需要3张表,通过关联关系来存储嵌套的列表数据:
食谱主表(recipes)
用来存每个食谱的核心单值信息,字段如下:
recipe_id:INT,自增主键(唯一标识每个食谱)cuisine:VARCHAR(100),菜系cook_time:INT,制作时长(比如分钟数)dish_name:VARCHAR(200),菜名(按需调整,根据你的JSON字段来)
配料表(recipe_ingredients)
每个配料单独占一行,和主表通过recipe_id关联:
ingredient_id:INT,自增主键recipe_id:INT,外键(关联recipes.recipe_id)ingredient_content:TEXT,单条配料内容(比如"2勺生抽")
步骤表(recipe_instructions)
同理,每个步骤单独占一行:
instruction_id:INT,自增主键recipe_id:INT,外键(关联recipes.recipe_id)instruction_content:TEXT,单条步骤内容(比如"热锅倒油,放入蒜末爆香")
你可以用下面的SQL语句创建这些表(直接在MySQL客户端执行):
-- 创建主表 CREATE TABLE IF NOT EXISTS recipes ( recipe_id INT AUTO_INCREMENT PRIMARY KEY, cuisine VARCHAR(100) NOT NULL, cook_time INT, dish_name VARCHAR(200) NOT NULL ); -- 创建配料表 CREATE TABLE IF NOT EXISTS recipe_ingredients ( ingredient_id INT AUTO_INCREMENT PRIMARY KEY, recipe_id INT NOT NULL, ingredient_content TEXT NOT NULL, FOREIGN KEY (recipe_id) REFERENCES recipes(recipe_id) ON DELETE CASCADE ); -- 创建步骤表 CREATE TABLE IF NOT EXISTS recipe_instructions ( instruction_id INT AUTO_INCREMENT PRIMARY KEY, recipe_id INT NOT NULL, instruction_content TEXT NOT NULL, FOREIGN KEY (recipe_id) REFERENCES recipes(recipe_id) ON DELETE CASCADE );
ON DELETE CASCADE的作用是:如果主表的某个食谱被删除,对应的配料和步骤也会自动删除,避免残留脏数据。
2. Python代码实现数据迁移
接下来用Python读取你的JSON文件,把数据分批插入到三张表里。先安装必要的依赖:
mysql-connector-python(或者pymysql,二选一即可):用来连接MySQLjson是Python内置库,无需额外安装
安装命令:
pip install mysql-connector-python
核心代码(带详细注释,你可以直接替换参数使用):
import json import mysql.connector from mysql.connector import Error def migrate_recipes(json_file_path): # 1. 读取本地JSON文件 with open(json_file_path, 'r', encoding='utf-8') as f: recipes_data = json.load(f) # 2. 连接MySQL数据库 try: connection = mysql.connector.connect( host='localhost', # 本地数据库一般是localhost,远程的话填对应IP database='你的数据库名', # 替换成你要使用的数据库名称 user='你的用户名', # 比如默认的root password='你的数据库密码' ) if connection.is_connected(): cursor = connection.cursor() # 3. 遍历每个食谱,依次插入数据 for recipe in recipes_data: # 先插入主表,获取当前食谱的唯一ID insert_recipe_sql = """ INSERT INTO recipes (cuisine, cook_time, dish_name) VALUES (%s, %s, %s) """ # 这里的键要和你的JSON字段完全对应,比如JSON里菜名是"name"就改成recipe["name"] recipe_params = ( recipe.get("cuisine"), recipe.get("cook_time"), recipe.get("dish_name") ) cursor.execute(insert_recipe_sql, recipe_params) current_recipe_id = cursor.lastrowid # 获取刚插入的自增ID # 4. 插入配料表:遍历配料列表,逐个插入 if "ingredients" in recipe and recipe["ingredients"]: insert_ingredient_sql = """ INSERT INTO recipe_ingredients (recipe_id, ingredient_content) VALUES (%s, %s) """ for ing in recipe["ingredients"]: cursor.execute(insert_ingredient_sql, (current_recipe_id, ing)) # 5. 插入步骤表:遍历步骤列表,逐个插入 if "instructions" in recipe and recipe["instructions"]: insert_instruction_sql = """ INSERT INTO recipe_instructions (recipe_id, instruction_content) VALUES (%s, %s) """ for inst in recipe["instructions"]: cursor.execute(insert_instruction_sql, (current_recipe_id, inst)) # 提交所有修改到数据库(很重要,不提交的话数据不会保存) connection.commit() print("所有食谱数据迁移完成!") except Error as e: print(f"数据库操作出错:{e}") # 如果出错,回滚所有未提交的修改,避免数据混乱 if connection: connection.rollback() finally: # 最后关闭数据库连接 if connection and connection.is_connected(): cursor.close() connection.close() # 调用函数,替换成你的JSON文件路径 migrate_recipes("你的食谱文件.json")
3. 新手必看注意事项
- 先拿1-2条测试数据试手,没问题再批量迁移,避免出错后返工
- 确保你的JSON格式正确:每个食谱的
ingredients和instructions是数组类型(比如["2勺糖", "1个鸡蛋"]) - 如果JSON里还有其他字段,直接在主表添加对应字段,然后在插入主表的代码里补充参数即可
- 数据量特别大的话,可以改用
executemany批量插入来提高效率,新手先从单条插入开始更稳妥
内容的提问来源于stack exchange,提问作者sm29




