MySQL使用python新建表

0 阅读1分钟

使用python新建表

完成MySQL实验,安装MySQLServer、MySQL Workbench。在Pyhon中设计代码,完成新建一个数据库mydb、新建一个student表。完成后给出MySQL Workbench的截图

安装MySQLServer、MySQL Workbench

安装完成后的截图:

image

python代码

import mysql.connector
from mysql.connector import errorcode
import logging

# 配置日志记录
logging.basicConfig(
    level=logging.INFO,  # 设置日志级别为INFO,可以根据需要调整为DEBUG等
    format="%(asctime)s - %(levelname)s - %(message)s",  # 设置日志输出格式
    handlers=[
        logging.StreamHandler()  # 输出到控制台
        # logging.FileHandler("mysql_operations.log") # 如果需要输出到文件,可以添加此行
    ],
)

# 数据库连接配置
# 建议将此配置移至外部配置文件,以避免硬编码敏感信息和提高灵活性。
# 例如,可以使用 configparser 或 os.environ 来读取配置。
# 当前为简化示例,仍保留在此处,但请注意生产环境中应避免硬编码密码。

DB_CONFIG = {
    "host": "200.1.17.17",
    "user": "root",
    "password": "mysql_hwDTeQ",
    "port": 3306,
}

# 数据库名称和表名称
# 建议将这些常量作为参数传递给相关函数,而不是使用全局变量,以提高函数的独立性和可重用性。
DATABASE_NAME = "mydb"
TABLE_NAME = "student"


def create_database(cursor, db_name):
    """创建数据库

    此函数用于在MySQL服务器上创建一个新的数据库。
    它首先尝试执行CREATE DATABASE语句。如果数据库已存在,则捕获特定的MySQL错误并打印提示信息。
    如果发生其他MySQL错误,则打印详细的错误信息。

    Args:
        cursor: MySQL数据库游标对象,用于执行SQL命令。
        db_name: 要创建的数据库的名称 (字符串)。

    Raises:
        mysql.connector.Error: 如果执行SQL语句时发生除数据库已存在以外的错误。


    """
    try:
        # 怎么做的: 执行SQL命令创建数据库
        # 为什么这么做: 确保后续操作所需的数据库存在
        cursor.execute(f"CREATE DATABASE {db_name} DEFAULT CHARACTER SET 'utf8mb4'")
        logging.info(f"数据库 '{db_name}' 创建成功!")
    except mysql.connector.Error as err:
        # 怎么做的: 捕获MySQL错误
        # 为什么这么做: 根据错误类型进行不同的处理,避免程序崩溃
        if err.errno == errorcode.ER_DB_CREATE_EXISTS:
            logging.info(f"数据库 '{db_name}' 已存在。")
        else:
            logging.error(f"创建数据库失败: {err}")
            # 对于更详细的错误,可以打印 err.msg
            # logging.error(f"错误详情: {err.msg}")
            raise err  # 重新抛出异常,让调用者知道发生了错误


def create_table(cursor, db_name, table_name):
    """创建表

    此函数用于在指定的数据库中创建一个新的表。
    它首先尝试执行CREATE TABLE语句。如果表已存在,则捕获特定的MySQL错误并打印提示信息。
    如果发生其他MySQL错误,则打印详细的错误信息。

    Args:
        cursor: MySQL数据库游标对象,用于执行SQL命令。
        db_name: 表所属的数据库名称 (字符串)。
        table_name: 要创建的表的名称 (字符串)。

    Raises:
        mysql.connector.Error: 如果执行SQL语句时发生除表已存在以外的错误。


    """
    # SQL 创建表的语句
    # 怎么做的: 定义创建表的SQL语句
    # 为什么这么做: 描述表的结构和属性
    table_description = f"""
    CREATE TABLE {table_name} (
        id INT AUTO_INCREMENT PRIMARY KEY,
        name VARCHAR(255) NOT NULL,
        age INT,
        major VARCHAR(255),
        enrollment_date DATE
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    """
    try:
        logging.info(f"正在创建表 '{table_name}'...")
        # 怎么做的: 执行SQL命令创建表
        # 为什么这么做: 在数据库中建立数据存储结构
        cursor.execute(f"USE {db_name}")  # 切换到目标数据库
        cursor.execute(table_description)
        logging.info(f"表 '{table_name}' 创建成功!")
    except mysql.connector.Error as err:
        # 怎么做的: 捕获MySQL错误
        # 为什么这么做: 根据错误类型进行不同的处理,避免程序崩溃
        if err.errno == errorcode.ER_TABLE_EXISTS_ERROR:
            logging.info(f"表 '{table_name}' 已存在。")
        else:
            logging.error(f"创建表失败: {err}")
            # 对于更详细的错误,可以打印 err.msg
            # logging.error(f"错误详情: {err.msg}")
            raise err  # 重新抛出异常


def main():
    """主函数

    此函数是程序的入口点,负责建立数据库连接,调用创建数据库和表的函数,并处理连接过程中的错误。
    它使用try...except...finally块来确保数据库连接和游标在程序结束时被正确关闭,即使发生错误。

    怎么做的: 尝试连接数据库,调用创建函数,提交事务,并在发生错误或程序结束时关闭资源。
    为什么这么做: 组织程序的执行流程,管理数据库连接生命周期,并提供基本的错误处理。


    """
    conn = None
    cursor = None
    try:
        # 连接到MySQL服务器(不指定数据库,因为要先创建数据库)
        # 怎么做的: 使用DB_CONFIG字典中的参数建立数据库连接
        # 为什么这么做: 连接到MySQL服务器以便执行后续的数据库操作
        conn = mysql.connector.connect(**DB_CONFIG)
        cursor = conn.cursor()

        # 1. 创建数据库
        # 怎么做的: 调用create_database函数创建数据库
        # 为什么这么做: 确保目标数据库存在
        create_database(cursor, DATABASE_NAME)

        # 在创建表之前,需要先选择或连接到 mydb 数据库
        # 如果数据库是刚刚创建的,则需要重新连接或使用 USE 语句
        # 怎么做的: 调用create_table函数创建表
        # 为什么这么做: 在已存在的数据库中创建所需的数据表结构
        create_table(cursor, DATABASE_NAME, TABLE_NAME)

        # 提交事务
        # 怎么做的: 提交所有挂起的数据库操作
        # 为什么这么做: 确保数据库的更改被永久保存
        conn.commit()
        logging.info("事务已提交。")

    except mysql.connector.Error as err:
        # 怎么做的: 捕获MySQL连接或操作过程中发生的错误
        # 为什么这么做: 根据错误类型提供用户友好的错误信息,并记录详细错误以便调试
        if err.errno == errorcode.ER_ACCESS_DENIED_ERROR:
            logging.error("连接失败: 用户名或密码错误。")
        elif err.errno == errorcode.ER_BAD_DB_ERROR:
            logging.error("连接失败: 数据库不存在。")
        else:
            logging.error(f"连接数据库或执行操作时发生未知错误: {err}")
            # logging.error(f"错误详情: {err.msg}")
    except Exception as e:
        # 怎么做的: 捕获其他可能的异常
        # 为什么这么做: 提供一个通用的错误捕获,防止程序因未预料的错误而崩溃
        logging.error(f"发生未预料的错误: {e}")

    finally:
        # 怎么做的: 无论是否发生错误,都尝试关闭游标和连接
        # 为什么这么做: 释放数据库资源,避免资源泄露
        if cursor:
            cursor.close()
            logging.info("数据库游标已关闭。")
        if conn:
            conn.close()
            logging.info("数据库连接已关闭。")


# 进一步优化建议:
# 1. 配置管理:将数据库连接配置移至外部文件 (如 .ini, .env) 或环境变量。
# 2. 错误处理:考虑使用自定义错误码或更结构化的错误处理方式,而不是仅依赖异常捕获。
# 3. 连接池:对于频繁的数据库操作,考虑使用连接池来提高性能和资源利用率。
# 4. 上下文管理器:为数据库连接和游标创建上下文管理器 (使用 'with' 语句),可以简化资源管理。
# 5. 单元测试:为数据库操作函数编写单元测试,确保其功能正确性。
# 6. 代码规范:使用如 Black, Flake8 等工具进行代码格式化和规范检查。


if __name__ == "__main__":
    main()

代码执行后的结果

image