You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何将含列表型配料与步骤的食谱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,二选一即可):用来连接MySQL
  • json是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格式正确:每个食谱的ingredientsinstructions是数组类型(比如["2勺糖", "1个鸡蛋"]
  • 如果JSON里还有其他字段,直接在主表添加对应字段,然后在插入主表的代码里补充参数即可
  • 数据量特别大的话,可以改用executemany批量插入来提高效率,新手先从单条插入开始更稳妥

内容的提问来源于stack exchange,提问作者sm29

火山引擎 最新活动