基于python语言给出mysql调用数据库实现增删改查功能
Python 操作 MySQL 实现增删改查(CRUD)
这里使用
pymysql库(Python 主流 MySQL 连接库),分环境准备、完整代码、分步讲解,附带数据表、异常处理、事务,可直接运行。一、环境准备
1. 安装依赖
bash
运行
pip install pymysql2. 提前创建测试库和表
先在 MySQL 中执行下面 SQL,创建数据库、学生表:
sql
-- 创建数据库 CREATE DATABASE IF NOT EXISTS python_mysql DEFAULT CHARSET utf8mb4; USE python_mysql; -- 学生表 CREATE TABLE student ( sid INT PRIMARY KEY AUTO_INCREMENT, sname VARCHAR(20) NOT NULL, age INT, gender VARCHAR(10) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
二、完整代码(封装工具类 + 增删改查)
整体说明
- 封装数据库连接、关闭通用方法
- 实现:增、删、改、单条查询、多条查询
- 加入异常捕获、事务处理,防止数据出错
python
运行
import pymysql from pymysql import Error # 数据库配置信息(修改为你自己的 MySQL 账号密码) DB_CONFIG = { "host": "localhost", # 数据库地址 "user": "root", # 用户名 "password": "123456", # 你的 MySQL 密码 "database": "python_mysql", # 数据库名 "charset": "utf8mb4" } class MySQLUtil: """MySQL 工具类:连接、关闭、CRUD""" def __init__(self): # 初始化连接和游标 self.connection = None self.cursor = None def connect(self): """建立数据库连接""" try: self.connection = pymysql.connect(**DB_CONFIG) # 创建游标(默认元组格式,也可使用 DictCursor 返回字典) self.cursor = self.connection.cursor(pymysql.cursors.DictCursor) print("数据库连接成功") except Error as e: print(f"连接失败:{e}") def close(self): """关闭游标和连接""" if self.cursor: self.cursor.close() if self.connection: self.connection.close() print("数据库连接已关闭") def insert_data(self, sname, age, gender): """新增数据""" try: sql = "INSERT INTO student(sname, age, gender) VALUES (%s, %s, %s)" self.cursor.execute(sql, (sname, age, gender)) self.connection.commit() # 提交事务 print(f"新增成功,受影响行数:{self.cursor.rowcount}") except Error as e: self.connection.rollback() # 出错回滚 print(f"新增失败:{e}") def delete_data(self, sid): """根据学号删除数据""" try: sql = "DELETE FROM student WHERE sid = %s" self.cursor.execute(sql, sid) self.connection.commit() print(f"删除成功,受影响行数:{self.cursor.rowcount}") except Error as e: self.connection.rollback() print(f"删除失败:{e}") def update_data(self, sid, new_age): """根据学号更新年龄""" try: sql = "UPDATE student SET age = %s WHERE sid = %s" self.cursor.execute(sql, (new_age, sid)) self.connection.commit() print(f"修改成功,受影响行数:{self.cursor.rowcount}") except Error as e: self.connection.rollback() print(f"修改失败:{e}") def query_one(self, sid): """查询单条数据(根据学号)""" try: sql = "SELECT * FROM student WHERE sid = %s" self.cursor.execute(sql, sid) result = self.cursor.fetchone() # 获取一条结果 print("单条查询结果:", result) return result except Error as e: print(f"查询失败:{e}") def query_all(self): """查询所有数据""" try: sql = "SELECT * FROM student" self.cursor.execute(sql) result = self.cursor.fetchall() # 获取全部结果 print("全部数据:") for row in result: print(row) return result except Error as e: print(f"查询失败:{e}") if __name__ == "__main__": # 实例化工具类 db = MySQLUtil() # 1. 连接数据库 db.connect() # 2. 新增 db.insert_data("张三", 18, "男") db.insert_data("李四", 19, "女") # 3. 查询所有 db.query_all() # 4. 修改(把 sid=1 的年龄改为 20) db.update_data(1, 20) # 5. 单条查询 db.query_one(1) # 6. 删除(删除 sid=2) db.delete_data(2) # 7. 再次查询所有 db.query_all() # 8. 关闭连接 db.close()
三、核心知识点讲解
1. 关键对象
- connection:数据库连接对象,负责通信、事务提交 / 回滚
- cursor :游标对象,执行 SQL、获取结果
2. 占位符说明
pymysql统一使用%s作为参数占位符,不要拼接字符串,防止 SQL 注入。python
运行
# 安全写法(推荐) sql = "INSERT INTO student(sname) VALUES (%s)" cursor.execute(sql, ("张三",)) # 危险写法(禁止,SQL注入) name = input() sql = f"INSERT INTO student(sname) VALUES ('{name}')"3. 事务操作(重点)
connection.commit():提交事务,增 / 删 / 改必须提交才生效connection.rollback():事务回滚,SQL 执行异常时撤销操作,保证数据安全4. 查询取值方法
fetchone():获取第一条查询结果fetchall():获取全部查询结果fetchmany(n):获取指定n条结果5. 游标格式
DictCursor:返回字典,键为字段名,可读性强(示例使用)- 默认游标:返回元组,只有值没有字段名
四、分步运行效果说明
- 连接数据库 → 打印
数据库连接成功- 插入两条学生数据
- 查询全表,展示两条记录
- 修改
sid=1年龄为 20- 单独查询
sid=1数据- 删除
sid=2记录- 再次查询,只剩
sid=1一条数据- 关闭连接
五、拓展:简易原生写法(不封装类)
适合入门练习,代码更简短:
python
运行
import pymysql # 连接数据库 conn = pymysql.connect( host="localhost", user="root", password="123456", database="python_mysql", charset="utf8mb4" ) cur = conn.cursor() # 增 cur.execute("INSERT INTO student(sname,age) VALUES (%s,%s)", ("王五", 21)) conn.commit() # 查 cur.execute("SELECT * FROM student") print(cur.fetchall()) # 改 cur.execute("UPDATE student SET age=22 WHERE sid=3") conn.commit() # 删 cur.execute("DELETE FROM student WHERE sid=3") conn.commit() # 关闭 cur.close() conn.close()
六、常见报错排查
- 连接失败:检查 MySQL 服务是否启动、账号 / 密码 / 库名是否正确
- 中文乱码 :连接时指定
charset="utf8mb4"- 增删改无效果 :忘记执行
commit()提交事务- 外键 / 约束报错:参照之前外键规则,保证数据合法
给出html的前端页面部分,数据交互基于python实现
结合前面 Python + MySQL 后端,实现 HTML 前端页面 + 前后端数据交互 ,采用 Flask 轻量框架 (简单易上手,适合教学演示),完成学生信息增删改查全流程。
一、整体架构
- 后端:Python + Flask + pymysql(接口、数据库 CRUD)
- 前端:原生 HTML + 简单 CSS(页面表单、列表展示)
- 交互方式:前端通过 AJAX(JavaScript) 调用后端接口,实现无刷新数据交互
二、环境准备
- 安装依赖
bash
运行
pip install pymysql flask
- 沿用之前 MySQL 库和表
sql
CREATE DATABASE IF NOT EXISTS python_mysql DEFAULT CHARSET utf8mb4; USE python_mysql; CREATE TABLE student ( sid INT PRIMARY KEY AUTO_INCREMENT, sname VARCHAR(20) NOT NULL, age INT, gender VARCHAR(10) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
三、后端代码(Flask + MySQL)
文件名:
app.py提供 新增、查询、修改、删除 接口,统一接收前端请求。python
运行
from flask import Flask, request, jsonify import pymysql from pymysql import Error app = Flask(__name__) # 数据库配置 DB_CONFIG = { "host": "localhost", "user": "root", "password": "123456", # 改成你的MySQL密码 "database": "python_mysql", "charset": "utf8mb4" } # 数据库连接工具 def get_db_conn(): return pymysql.connect(**DB_CONFIG) # 1. 查询所有学生 @app.route('/get_student', methods=['GET']) def get_student(): conn = get_db_conn() cursor = conn.cursor(pymysql.cursors.DictCursor) try: cursor.execute("SELECT * FROM student") data = cursor.fetchall() return jsonify({"code": 200, "data": data}) except Error as e: return jsonify({"code": 500, "msg": "查询失败"}) finally: cursor.close() conn.close() # 2. 新增学生 @app.route('/add_student', methods=['POST']) def add_student(): data = request.get_json() sname = data.get('sname') age = data.get('age') gender = data.get('gender') conn = get_db_conn() cursor = conn.cursor() try: sql = "INSERT INTO student(sname, age, gender) VALUES (%s, %s, %s)" cursor.execute(sql, (sname, age, gender)) conn.commit() return jsonify({"code": 200, "msg": "新增成功"}) except Error as e: conn.rollback() return jsonify({"code": 500, "msg": "新增失败"}) finally: cursor.close() conn.close() # 3. 修改学生年龄 @app.route('/update_student', methods=['POST']) def update_student(): data = request.get_json() sid = data.get('sid') age = data.get('age') conn = get_db_conn() cursor = conn.cursor() try: sql = "UPDATE student SET age = %s WHERE sid = %s" cursor.execute(sql, (age, sid)) conn.commit() return jsonify({"code": 200, "msg": "修改成功"}) except Error as e: conn.rollback() return jsonify({"code": 500, "msg": "修改失败"}) finally: cursor.close() conn.close() # 4. 删除学生 @app.route('/del_student', methods=['POST']) def del_student(): data = request.get_json() sid = data.get('sid') conn = get_db_conn() cursor = conn.cursor() try: sql = "DELETE FROM student WHERE sid = %s" cursor.execute(sql, sid) conn.commit() return jsonify({"code": 200, "msg": "删除成功"}) except Error as e: conn.rollback() return jsonify({"code": 500, "msg": "删除失败"}) finally: cursor.close() conn.close() if __name__ == '__main__': # 启动后端服务 app.run(debug=True)
四、前端 HTML 页面
文件名:
index.html包含:新增表单、数据列表、修改 / 删除按钮、AJAX 交互,纯原生 JS,无需额外框架。html
预览
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>学生信息管理</title> <style> *{margin: 10px;} table{border-collapse: collapse; width: 500px;} th,td{border: 1px solid #333; padding: 6px; text-align: center;} button{cursor: pointer; padding: 4px 10px;} .form-box{margin-bottom: 20px;} </style> </head> <body> <h2>学生信息管理系统</h2> <!-- 新增学生表单 --> <div class="form-box"> 姓名:<input type="text" id="sname" placeholder="请输入姓名"> 年龄:<input type="number" id="age" placeholder="请输入年龄"> 性别:<input type="text" id="gender" placeholder="请输入性别"> <button onclick="addStudent()">新增</button> </div> <!-- 学生列表 --> <table> <tr> <th>学号</th> <th>姓名</th> <th>年龄</th> <th>性别</th> <th>操作</th> </tr> <tbody id="tableBody"> <!-- 数据由JS动态渲染 --> </tbody> </table> <script> // 页面加载完成自动查询数据 window.onload = function(){ getStudentList(); } // 1. 查询所有学生 function getStudentList(){ fetch("/get_student") .then(res => res.json()) .then(result => { let tbody = document.getElementById("tableBody"); tbody.innerHTML = ""; if(result.code === 200){ let list = result.data; list.forEach(item => { let tr = document.createElement("tr"); tr.innerHTML = ` <td>${item.sid}</td> <td>${item.sname}</td> <td>${item.age}</td> <td>${item.gender}</td> <td> <button onclick="updateAge(${item.sid})">改年龄</button> <button onclick="delStudent(${item.sid})">删除</button> </td> `; tbody.appendChild(tr); }) } }) } // 2. 新增学生 function addStudent(){ let sname = document.getElementById("sname").value; let age = document.getElementById("age").value; let gender = document.getElementById("gender").value; fetch("/add_student",{ method: "POST", headers: {"Content-Type":"application/json"}, body: JSON.stringify({sname, age, gender}) }) .then(res => res.json()) .then(result => { alert(result.msg); // 清空表单 + 刷新列表 document.getElementById("sname").value = ""; document.getElementById("age").value = ""; document.getElementById("gender").value = ""; getStudentList(); }) } // 3. 修改年龄 function updateAge(sid){ let newAge = prompt("请输入新年龄:"); if(!newAge) return; fetch("/update_student",{ method: "POST", headers: {"Content-Type":"application/json"}, body: JSON.stringify({sid, age: newAge}) }) .then(res => res.json()) .then(result => { alert(result.msg); getStudentList(); }) } // 4. 删除学生 function delStudent(sid){ if(!confirm("确定要删除该数据吗?")) return; fetch("/del_student",{ method: "POST", headers: {"Content-Type":"application/json"}, body: JSON.stringify({sid}) }) .then(res => res.json()) .then(result => { alert(result.msg); getStudentList(); }) } </script> </body> </html>
五、运行步骤(完整流程)
- 启动 MySQL 服务,保证数据库、数据表已创建
- 运行后端
app.py,控制台提示:Running on http://127.0.0.1:5000- 用浏览器直接打开
index.html文件- 功能测试:
- 输入姓名 / 年龄 / 性别,点击【新增】,数据存入 MySQL 并实时刷新列表
- 点击【改年龄】,弹窗输入新年龄,完成数据修改
- 点击【删除】,确认后删除数据库对应记录
六、核心交互说明
- 前后端通信
- 后端 Flask 提供 REST 风格接口
- 前端使用原生
fetch(AJAX)发送请求,传递 JSON 数据- 数据流向前端表单 → JS 组装数据 → 调用后端接口 → Python 操作 MySQL → 结果返回前端 → 页面刷新
- 关键要点
- 增 / 删 / 改 后端必须执行
commit()提交事务- 前端发送 POST 请求,必须指定请求头
Content-Type:application/json- 所有数据库操作增加异常捕获,保证程序稳定
七、常见问题排查
- 页面无数据:检查 MySQL 是否启动、账号密码、数据库名是否正确
- 新增 / 修改无反应:查看后端控制台报错,优先检查 SQL 语句
- 跨域问题:本案例前后端同源,无需额外配置跨域;若分开部署需加装
flask-cors- 中文乱码:确认数据库、连接配置均为
utf8mb4flask
结合上一节前后端学生管理案例 ,精讲 Flask 基础 + 路由、请求、响应、模板使用,搭配代码示例,适配学习与实训。
一、Flask 简介
Flask 是 Python 轻量级 Web 框架,短小精悍、上手简单,适合快速开发接口、小型网站。
- 核心特点:极简、灵活、扩展性强
- 本项目用途:搭建 Web 接口,接收前端请求、操作数据库、返回数据
1. 安装
bash
运行
pip install flask二、Flask 最小入门示例(HelloWorld)
新建
app.py,最基础运行代码:python
运行
# 导入Flask类 from flask import Flask # 实例化Flask对象,__name__代表当前模块名 app = Flask(__name__) # 路由:访问根路径 / 执行下面函数 @app.route('/') def index(): return "Hello Flask!" # 启动服务 if __name__ == '__main__': # debug=True 开启调试模式,代码修改自动重启 app.run(debug=True)运行后访问:
http://127.0.0.1:5000,页面输出文本。
三、核心知识点(结合 CRUD 项目讲解)
1. 路由
@app.route()作用:URL 地址 和 后端函数 绑定
基础用法
python
运行
# 访问 http://127.0.0.1:5000/user @app.route('/user') def user_list(): return "学生列表页面"指定请求方式
默认支持
GET,如需接收POST(前端提交数据必备):python
运行
# 仅允许 GET / POST 请求 @app.route('/add', methods=['GET', 'POST']) def add(): return "新增接口"
2. 请求对象
request用于获取前端提交的数据,常用两种格式:
- JSON 数据(前后端分离 AJAX/fetch 主流用法)
- 表单 form 数据(传统 form 表单)
2.1 获取 JSON 数据(项目中使用)
前端用
fetch传JSON,后端用request.get_json()接收:python
运行
from flask import Flask, request, jsonify app = Flask(__name__) @app.route('/test_json', methods=['POST']) def test_json(): # 获取前端json数据 data = request.get_json() name = data.get("sname") age = data.get("age") return f"姓名:{name},年龄:{age}"2.2 获取表单数据
python
运行
@app.route('/test_form', methods=['POST']) def test_form(): name = request.form.get("sname") return name
3. 响应
jsonify前端 AJAX 一般接收 JSON 格式数据 ,Flask 使用
jsonify()快速构造标准 JSON 响应:python
运行
from flask import jsonify @app.route('/get_data') def get_data(): # 字典转json返回给前端 return jsonify({ "code": 200, "msg": "查询成功", "data": [{"sid":1, "sname":"张三"}] })
4. 结合 MySQL 接口(复用之前学生项目核心)
整合 路由 + 请求 + MySQL,就是完整后端接口,拆分核心代码讲解:
python
运行
from flask import Flask, request, jsonify import pymysql app = Flask(__name__) # 数据库配置 DB_CONFIG = { "host": "localhost", "user": "root", "password": "123456", "database": "python_mysql", "charset": "utf8mb4" } # 数据库连接函数 def get_conn(): return pymysql.connect(**DB_CONFIG) # 1. 查询所有学生 GET接口 @app.route('/get_student', methods=['GET']) def get_student(): conn = get_conn() cur = conn.cursor(pymysql.cursors.DictCursor) cur.execute("SELECT * FROM student") res = cur.fetchall() cur.close() conn.close() return jsonify({"code":200, "data":res}) # 2. 新增学生 POST接口 @app.route('/add_student', methods=['POST']) def add_student(): data = request.get_json() sname = data["sname"] age = data["age"] gender = data["gender"] conn = get_conn() cur = conn.cursor() sql = "INSERT INTO student(sname,age,gender) VALUES(%s,%s,%s)" cur.execute(sql, (sname, age, gender)) conn.commit() cur.close() conn.close() return jsonify({"code":200, "msg":"新增成功"}) if __name__ == '__main__': app.run(debug=True)
四、Flask 模板(HTML 页面渲染,拓展知识点)
前面案例是前后端分离 (HTML 独立文件),Flask 也支持模板渲染,适合传统页面开发。
目录结构(固定格式)
plaintext
项目文件夹 ├── app.py # 后端主程序 └── templates # 必须命名为 templates └── index.html # 前端页面1. 后端渲染模板
python
运行
from flask import Flask, render_template app = Flask(__name__) # 访问 / 自动渲染 templates/index.html @app.route('/') def index(): # 向页面传变量 name = "张三" return render_template("index.html", username=name) if __name__ == '__main__': app.run(debug=True)2. 模板中接收变量(index.html)
html
预览
<!DOCTYPE html> <html> <body> <h3>欢迎 {{ username }}</h3> </body> </html>
五、启动与运行说明
- 执行
python app.py启动服务- 默认地址:
http://127.0.0.1:5000debug=True:代码修改后自动重启服务,开发必备,生产环境关闭
六、常用报错 & 解决
- 端口被占用
python
运行
# 修改端口 app.run(port=8080, debug=True)
- 前端 POST 接收不到数据
- 前端没设置
Content-Type: application/json- 后端误用
request.form接收 JSON,改用request.get_json()
- 中文乱码 数据库、连接字符串统一使用
utf8mb4
七、整体流程总结(考试 / 实训简答)
- Flask 编写路由,定义接口地址与请求方式;
- 前端发起 GET/POST 请求,传递参数;
- 后端通过
request获取前端数据;- 结合
pymysql操作 MySQL 完成增删改查;- 使用
jsonify将结果转为 JSON 返回前端;- 前端 JS 解析 JSON,动态渲染页面。
self.connection = pymysql.connect(**DB_CONFIG)这行代码是 Python 使用 PyMySQL 连接 MySQL 数据库 的核心代码,我给你讲清楚它的作用、参数含义,以及和你刚才问的字符集有什么关系。
一、代码作用
python
运行
self.connection = pymysql.connect(**DB_CONFIG)简单解释
pymysql.connect()PyMySQL 库提供的创建数据库连接的方法。**DB_CONFIG把字典DB_CONFIG里的配置自动拆分成关键字参数传给 connect。self.connection把创建好的数据库连接对象保存下来,后面执行 SQL 都会用它。
二、
DB_CONFIG长什么样?(最关键)这行代码能运行,前提是你前面定义了
DB_CONFIG字典,通常长这样:python
运行
DB_CONFIG = { "host": "localhost", # 数据库地址 "port": 3306, # 端口 "user": "root", # 用户名 "password": "123456", # 密码 "database": "test_db", # 要连接的库名 "charset": "utf8mb4" # 字符集(非常重要!) }
三、和你刚才问的「字符集」直接相关
这行代码里
charset必须和 MySQL 数据库的字符集一致 ,否则会出现中文乱码。正确写法
python
运行
"charset": "utf8mb4" # 推荐,支持 emoji错误写法
python
运行
"charset": "utf-8" # 错!MySQL 里叫 utf8mb4,不是 utf-8
四、完整可运行示例
python
运行
import pymysql # 数据库配置 DB_CONFIG = { "host": "127.0.0.1", "port": 3306, "user": "root", "password": "你的密码", "database": "你的库名", "charset": "utf8mb4" # 字符集必须写对 } # 创建连接 self.connection = pymysql.connect(**DB_CONFIG) # 测试连接是否成功 print("数据库连接成功!")
五、常见问题
报错:Unknown charset 'utf-8' 改成
utf8mb4即可。中文乱码 确保:
- 代码里
charset=utf8mb4- 数据库字符集也是
utf8mb4连接失败 检查 host、port、user、password、database 是否正确。
总结
**DB_CONFIG= 自动解包数据库配置charset="utf8mb4"= 防止中文乱码、支持 emoji(最推荐)- 这行代码的作用就是拿到一个可用的 MySQL 连接对象
如果你需要,我还能帮你写完整的增删改查工具类。
解释python (**字典)语法
Python ** 字典 语法(超通俗解释)
**字典是 Python 里的关键字参数解包 ,专门用来把字典里的键值对 ,自动变成函数的参数名=参数值形式。
1. 一句话看懂
python
运行
函数(**字典)= 把字典拆成一堆参数,直接喂给函数
2. 超简单例子
你有一个字典:
python
运行
info = { "name": "小明", "age": 20 }有一个函数:
python
运行
def show(name, age): print(name, age)用 ** 解包,一行搞定传参:
python
运行
show(**info) # 等价于:show(name="小明", age=20)结果:
plaintext
小明 20
3. 回到你数据库代码
你写的:
python
运行
self.connection = pymysql.connect(**DB_CONFIG)等价于 手动写一长串参数:
python
运行
self.connection = pymysql.connect( host="localhost", port=3306, user="root", password="123456", database="test", charset="utf8mb4" )
**DB_CONFIG就是帮你自动展开字典,代码更干净、更好维护。
4. 必须满足的规则(很重要)
- 字典的 key 必须和函数参数名完全一样
- 函数要
host,字典就必须写"host"- 写错名字会直接报错
- 不能多传、不能少传必填参数
- 只能用在函数调用里
5. 小补充:* 和 ** 的区别
*列表:解包位置参数**字典:解包关键字参数(参数名 = 值)
总结
**字典= 字典 → 自动拆成 参数名 = 参数值- 让代码更简洁,不用手写一长串参数
- 你数据库那行代码就是用它批量传连接信息
需要我再给你几个实战小练习巩固一下吗?
好的
练习 1:基础 ** 解包
python
运行
def connect_db(host, user, pwd): print(f"地址:{host},账号:{user},密码:{pwd}") cfg = {"host":"127.0.0.1", "user":"root", "pwd":"123456"} # **把字典拆成 host=...,user=...,pwd=... connect_db(**cfg)运行等价:
connect_db(host="127.0.0.1",user="root",pwd="123456")练习 2:混合传参(固定参数 + ** 字典)
python
运行
def connect_db(host, user, pwd, charset): print(host, user, pwd, charset) cfg = {"user":"root", "pwd":"123456"} # 固定写host,剩余从字典解包 connect_db("localhost",**cfg, charset="utf8mb4")练习 3:函数定义时 **kwargs(收集多余关键字参数)
python
运行
def test(a,**kwargs): print(a) print(kwargs) # 多余参数自动装进字典 test(100,name="张三",age=18) # kwargs = {"name":"张三","age":18}练习 4:pymysql 场景仿写(对应你原来代码)
python
运行
def connect(**config): print(config["host"],config["charset"]) DB_CONFIG = { "host":"127.0.0.1", "port":3306, "user":"root", "charset":"utf8mb4" } connect(**DB_CONFIG)关键口诀
- 函数调用里:
**dict→ 字典拆成 key=value 实参- 函数形参:
**kwargs→ 零散 key=value 打包成字典
py连接数据库创建游标的含义与作用我用最通俗、最直白 的方式给你讲清楚: Python 连接 MySQL 后,为什么要创建游标(cursor)?它到底是干嘛的?
一、一句话解释
游标(cursor)就是你和数据库之间的 "传令兵 / 执行器"。
- 你有了
connection(连接)= 你打通了到数据库的路- 但你不能直接对着路发号施令
- 必须创建一个 cursor(游标) ,让它帮你执行 SQL、拿结果
二、官方一点的解释
python
运行
# 1. 创建连接(修路) conn = pymysql.connect(**DB_CONFIG) # 2. 创建游标(派传令兵) cursor = conn.cursor() # 这就是创建游标的代码 # 3. 游标执行SQL(传令兵去干活) cursor.execute("SELECT * FROM user") # 4. 游标拿回数据(传令兵把结果带回来) data = cursor.fetchall()游标到底做什么?(核心作用)
执行 SQL 语句
SELECT / INSERT / UPDATE / DELETE都必须通过游标执行。接收 / 存储查询结果 数据库返回的数据,先放在游标里,你再从游标取。
控制事务 提交、回滚都和它相关。
遍历查询结果 像指针一样,一行一行读取数据。
三、超形象比喻(一看就懂)
- 连接(connection) = 电话线
- 游标(cursor) = 电话听筒
- 你不拿起听筒,就不能说话、不能听对方声音
- 不创建游标,就不能执行 SQL、不能拿数据
四、创建游标的标准代码
python
运行
import pymysql DB_CONFIG = { "host": "localhost", "user": "root", "password": "123456", "database": "test", "charset": "utf8mb4" } # 1. 建立连接 conn = pymysql.connect(**DB_CONFIG) # 2. 创建游标 【重要步骤】 cursor = conn.cursor() # 3. 用游标执行SQL cursor.execute("SELECT * FROM user") # 4. 获取结果 result = cursor.fetchall() print(result) # 5. 关闭游标和连接 cursor.close() conn.close()
五、最常用的游标方法
python
运行
cursor.execute(sql) # 执行SQL cursor.fetchone() # 拿1条数据 cursor.fetchall() # 拿全部数据 cursor.fetchmany(n) # 拿n条数据 cursor.close() # 关闭游标
六、你必须记住的结论
- 有连接不一定能操作数据库
- 有游标才能操作数据库
- 一个连接可以创建多个游标
- 用完一定要关闭游标(好习惯)
总结
- connection = 建立到数据库的连接
- cursor = 真正执行 SQL、获取数据的工具
- 没有游标,你有连接也无法操作数据库
pymysql.cursors.DictCursor一句话讲懂
pymysql.cursors.DictCursor它就是让数据库查询结果直接返回【字典】而不是【元组】 的游标类型,写代码更方便、更直观。
1. 普通游标 vs DictCursor
① 普通游标(默认)
python
运行
cursor = conn.cursor() cursor.execute("SELECT id,name FROM user") print(cursor.fetchone())返回结果:元组 tuple
plaintext
(1, "张三")取值必须用下标:
python
运行
data[0] # id data[1] # name缺点:不知道下标对应哪个字段,容易写错。
② DictCursor 字典游标(推荐)
python
运行
from pymysql.cursors import DictCursor cursor = conn.cursor(cursor=DictCursor)返回结果:字典 dict
plaintext
{"id": 1, "name": "张三"}取值用字段名,一目了然:
python
运行
data["id"] data["name"]
2. 完整代码示例(你直接复制就能用)
python
运行
import pymysql from pymysql.cursors import DictCursor # 导入 # 数据库配置 DB_CONFIG = { "host": "localhost", "user": "root", "password": "123456", "database": "test", "charset": "utf8mb4" } # 1. 建立连接 conn = pymysql.connect(**DB_CONFIG) # 2. 创建【字典游标】 ✅ cursor = conn.cursor(cursor=DictCursor) # 3. 查询 cursor.execute("SELECT id,name,age FROM user WHERE id=1") # 4. 获取结果(字典格式) result = cursor.fetchone() print(result) # {'id':1, 'name':'张三', 'age':20} print(result["name"]) # 直接用字段名取值 ✅ # 关闭 cursor.close() conn.close()
3. 为什么推荐用 DictCursor?
代码可读性极高
data["name"]比data[1]清楚一万倍不用记字段顺序
返回多条数据 = 列表里包字典 (最常用)
python
运行
[ {"id":1,"name":"张三"}, {"id":2,"name":"李四"} ]直接可以转 JSON(接口开发必备)
4. 最简单写法(不用单独导入)
你也可以这样写,更短:
python
运行
cursor = conn.cursor(pymysql.cursors.DictCursor)
总结
- 普通游标 → 返回
(1, "张三")元组- DictCursor → 返回
{"id":1, "name":"张三"}字典- 实际开发 99% 都用 DictCursor
代码解析 + 完善优化 + 配套函数实现
这段 JS 代码作用:通过 fetch 请求后端接口
/get_student获取学生列表,动态渲染到表格 tbody 中,绑定【修改年龄】【删除】按钮点击事件。一、原代码说明
javascript
运行
function getStudentList(){ fetch("/get_student") // 请求后端学生接口 .then(res => res.json()) // 响应转JSON .then(result => { let tbody = document.getElementById("tableBody"); tbody.innerHTML = ""; // 清空表格旧数据 if(result.code === 200){ // 后端返回成功 let list = result.data; // 学生数组 list.forEach(item => { // 遍历学生 let tr = document.createElement("tr"); tr.innerHTML = ` <td>${item.sid}</td> <td>${item.sname}</td> <td>${item.age}</td> <td>${item.gender}</td> <td> <button onclick="updateAge(${item.sid})">改年龄</button> <button onclick="delStudent(${item.sid})">删除</button> </td> `; tbody.appendChild(tr); // 添加行到表格 }) } }) }字段说明
sid:学生编号(主键,数字)sname:学生姓名age:年龄gender:性别- 按钮绑定全局方法:
updateAge(sid)修改年龄、delStudent(sid)删除学生二、配套缺失函数(补充修改年龄 + 删除学生)
javascript
运行
// 删除学生 function delStudent(sid) { if(!confirm("确定删除该学生?")) return; fetch(`/del_student?sid=${sid}`, {method:"DELETE"}) .then(res=>res.json()) .then(res=>{ if(res.code===200){ alert("删除成功"); getStudentList(); // 刷新列表 }else{ alert(res.msg||"删除失败"); } }) } // 修改年龄 function updateAge(sid) { let newAge = prompt("请输入新年龄:"); if(!newAge || isNaN(newAge)) return alert("年龄格式错误"); fetch(`/update_age?sid=${sid}&age=${newAge}`,{method:"PUT"}) .then(res=>res.json()) .then(res=>{ if(res.code===200){ alert("修改成功"); getStudentList(); }else{ alert(res.msg||"修改失败"); } }) }三、配套 HTML 表格结构
html
预览
<table border="1" cellpadding="6"> <thead> <tr> <th>学号</th> <th>姓名</th> <th>年龄</th> <th>性别</th> <th>操作</th> </tr> </thead> <tbody id="tableBody"></tbody> </table> <!-- 页面加载自动渲染列表 --> <script> window.onload = getStudentList; // 上面三个JS函数放这里 </script>四、优化建议(可选优化写法,避免 onclick 全局污染)
原代码
onclick="updateAge(${item.sid})"依赖全局函数,推荐使用事件绑定代替:js
// 替换tr内按钮写法,改用addEventListener let btnEdit = document.createElement("button"); btnEdit.innerText = "改年龄"; btnEdit.onclick = ()=>updateAge(item.sid); let btnDel = document.createElement("button"); btnDel.innerText = "删除"; btnDel.onclick = ()=>delStudent(item.sid); let td = document.createElement("td"); td.append(btnEdit, btnDel); tr.append(td);五、后端接口约定(前后端统一)
表格
接口 请求方式 参数 功能 /get_studentGET 无 查询所有学生 /del_studentDELETE sid 根据学号删除 /update_agePUT sid、age 修改学生年龄 后端返回格式统一: {code:200, data:[...], msg:"xxx"}需要我帮你补全后端 Python/Java 接口代码吗?
fetch
fetch 详解(结合你上面学生列表代码)
fetch是浏览器原生 AJAX,用来发网络请求(GET/POST/PUT/DELETE),不用引 jQuery。1. 基础语法
js
fetch(请求地址, [配置项]) .then(响应对象 => 响应.json()) // 解析JSON .then(data => {}) // 拿到后端数据 .catch(err=>{}) // 捕获网络错误① 默认 GET 请求(你原来代码就是 GET)
js
// GET 无参数 fetch("/get_student") .then(res=>res.json()) .then(result=>{...})② GET 拼接参数
js
// /del_student?sid=1 fetch(`/del_student?sid=${sid}`)③ POST / PUT / DELETE(需要配置 method、body)
js
fetch('/add_student',{ method:'POST', // PUT/DELETE headers:{ 'Content-Type':'application/json' }, body: JSON.stringify({ sname:'张三',age:18,gender:'男' }) }) .then(res=>res.json())2. 拆解你原有代码的 fetch 流程
js
fetch("/get_student") // 第一步:拿到http原始响应 .then(res => res.json()) // res.json():把后端返回的json字符串→js对象(异步Promise) .then(result => { // result就是后端 {code:200,data:[学生数组]} })注意:
fetch**只有网络断网才进catch**,http 404/500不会报错,需要手动判断res.ok`js
fetch('/xxx') .then(res=>{ if(!res.ok) throw new Error('请求失败'+res.status) return res.json() })3. async/await 简化写法(推荐替换原来链式 then)
js
async function getStudentList(){ try{ let res = await fetch("/get_student") let result = await res.json() let tbody = document.getElementById("tableBody") tbody.innerHTML="" if(result.code===200){ let list=result.data // 渲染表格... } }catch(err){ console.error('请求出错',err) } }4. 常用配置项汇总
js
fetch(url,{ method:"GET|POST|PUT|DELETE", headers:{ "Content-Type":"application/json" }, body:JSON.stringify(数据), // POST/PUT传参 credentials:"include" // 携带cookie })
MySQL-综合应用(Python+Html)
XZ-0700012026-06-03 14:23
相关推荐
噜噜噜阿鲁~1 小时前
python学习笔记 | 11.4、面向对象高级编程-定制类站大爷IP1 小时前
Python闭包变量作用域踩坑实录,原来我们都想错了XZ-0700011 小时前
MySQL-聚簇索引zzj_2626101 小时前
实验七 Python 文件操作与异常处理菜到离谱但坚持1 小时前
零门槛学LangChain:AI开发从入门到实战databook1 小时前
一次函数图像工厂:用 SymPy 自动生成 y=kx+b 对比动画测试老哥1 小时前
接口测试详解geovindu1 小时前
python: N-Barrier Pattern浮生望2 小时前
Python 入门 + 调用 LLM API:从 List 切片到商品文案生成