MySQL篇 面试题参考答案
·
1. Python 操作 MySQL 需要安装什么第三方库?分别写出安装命令
常用库:
-
pymysql(纯Python实现)
-
mysql-connector-python(官方驱动)
-
SQLAlchemy(ORM框架)
安装命令:
bash
pip install pymysql pip install mysql-connector-python pip install sqlalchemy
2. 用pymysql库写出 Python 连接 MySQL 的核心代码
python
import pymysql
# 建立数据库连接
conn = pymysql.connect(
host='localhost', # 数据库主机地址
user='root', # 用户名
password='123456', # 密码
database='test_db', # 数据库名
port=3306, # 端口号
charset='utf8mb4' # 字符集
)
# 测试连接
try:
print("连接成功")
cursor = conn.cursor()
cursor.execute("SELECT VERSION()")
version = cursor.fetchone()
print(f"MySQL版本:{version[0]}")
finally:
conn.close() # 关闭连接
3. 连接MySQL时各参数的含义
-
host:MySQL服务器地址(本地为localhost或127.0.0.1)
-
user:登录用户名
-
password:登录密码
-
database:要连接的数据库名称
-
port:MySQL服务端口号
默认端口:3306
4. 为什么用完MySQL连接后必须关闭?更优雅的方式
必须关闭的原因:
-
释放数据库服务器资源
-
避免达到最大连接数限制
-
防止内存泄漏
-
保持连接池的可用性
更优雅的方式(使用上下文管理器):
python
import pymysql
from contextlib import closing
# 方式1:使用with语句(需要pymysql支持)
with pymysql.connect(
host='localhost',
user='root',
password='123456',
database='test_db'
) as conn:
with conn.cursor() as cursor:
cursor.execute("SELECT * FROM user")
result = cursor.fetchall()
# 自动关闭游标和连接
# 方式2:使用closing
with closing(pymysql.connect(
host='localhost',
user='root',
password='123456',
database='test_db'
)) as conn:
with closing(conn.cursor()) as cursor:
cursor.execute("SELECT * FROM user")
result = cursor.fetchall()
5. execute()和executemany()的区别
-
execute():执行单条SQL语句
-
executemany():执行同一条SQL语句多次,用于批量操作
python
# execute() - 插入单条数据
cursor.execute(
"INSERT INTO user(name, age) VALUES(%s, %s)",
('张三', 20)
)
# executemany() - 批量插入多条数据
data = [
('李四', 21),
('王五', 22),
('赵六', 23)
]
cursor.executemany(
"INSERT INTO user(name, age) VALUES(%s, %s)",
data
)
6. 查询类和修改类SQL获取结果的区别
python
# 查询类SQL(SELECT)
cursor.execute("SELECT * FROM user WHERE age > 18")
results = cursor.fetchall() # 需要获取结果集
# 修改类SQL(INSERT/UPDATE/DELETE)
cursor.execute(
"UPDATE user SET age = %s WHERE id = %s",
(25, 1)
)
conn.commit() # 需要提交事务
affected_rows = cursor.rowcount # 获取受影响的行数
7. 什么是SQL注入?如何避免
SQL注入:通过在输入中嵌入恶意SQL代码,篡改原SQL语句的执行逻辑。
注入示例:
python
# 危险写法(容易SQL注入)
name = "小明' OR '1'='1"
cursor.execute(f"SELECT * FROM user WHERE name = '{name}'")
# 实际执行:SELECT * FROM user WHERE name = '小明' OR '1'='1'
# 安全写法(参数化查询)
name = "小明' OR '1'='1"
cursor.execute(
"SELECT * FROM user WHERE name = %s",
(name,)
)
# 参数会被转义,不会执行SQL注入
8. 查询user表所有字段的核心代码
python
import pymysql
# 创建连接
conn = pymysql.connect(
host='localhost',
user='root',
password='123456',
database='test_db'
)
try:
# 创建游标
cursor = conn.cursor()
# 执行SQL查询
sql = "SELECT * FROM user"
cursor.execute(sql)
# 获取所有结果
results = cursor.fetchall()
# 打印结果
for row in results:
print(row)
finally:
cursor.close()
conn.close()
9. 批量插入3条用户数据的实现
python
import pymysql
conn = pymysql.connect(
host='localhost',
user='root',
password='123456',
database='test_db'
)
try:
cursor = conn.cursor()
# 准备批量数据
users_data = [
(1, '张三', 20),
(2, '李四', 21),
(3, '王五', 22)
]
# 批量插入
sql = "INSERT INTO user(id, name, age) VALUES(%s, %s, %s)"
cursor.executemany(sql, users_data)
# 提交事务
conn.commit()
print(f"成功插入 {cursor.rowcount} 条数据")
except Exception as e:
conn.rollback() # 出错回滚
print(f"插入失败:{e}")
finally:
cursor.close()
conn.close()
10. 插入一条数据的完整代码
python
import pymysql
def insert_user():
"""插入一条用户数据"""
conn = None
cursor = None
try:
# 连接数据库
conn = pymysql.connect(
host='localhost',
user='root',
password='123456',
database='test_db'
)
# 创建游标
cursor = conn.cursor()
# 插入数据
sql = "INSERT INTO user(name, age) VALUES(%s, %s)"
data = ('小明', 20)
cursor.execute(sql, data)
# 提交事务
conn.commit()
print(f"插入成功,影响行数:{cursor.rowcount}")
print(f"新记录的ID:{cursor.lastrowid}")
except Exception as e:
if conn:
conn.rollback()
print(f"插入失败:{e}")
finally:
if cursor:
cursor.close()
if conn:
conn.close()
# 调用函数
insert_user()
11. 根据id查询单条数据
python
import pymysql
def get_user_by_id(user_id):
"""根据ID查询用户"""
conn = pymysql.connect(
host='localhost',
user='root',
password='123456',
database='test_db'
)
try:
cursor = conn.cursor()
# 查询SQL
sql = "SELECT id, name, age FROM user WHERE id = %s"
cursor.execute(sql, (user_id,))
# 获取单条数据
user = cursor.fetchone()
if user:
print(f"ID:{user[0]},姓名:{user[1]},年龄:{user[2]}")
return user
else:
print(f"ID为 {user_id} 的用户不存在")
return None
finally:
cursor.close()
conn.close()
# 调用函数
user = get_user_by_id(1)
12. 修改用户年龄并确认修改生效
python
import pymysql
def update_user_age(user_id, new_age):
"""更新用户年龄"""
conn = pymysql.connect(
host='localhost',
user='root',
password='123456',
database='test_db'
)
try:
cursor = conn.cursor()
# 更新数据
sql = "UPDATE user SET age = %s WHERE id = %s"
cursor.execute(sql, (new_age, user_id))
# 提交事务
conn.commit()
# 通过rowcount确认修改生效
if cursor.rowcount > 0:
print(f"修改成功,影响了 {cursor.rowcount} 行数据")
# 查询验证
cursor.execute("SELECT id, name, age FROM user WHERE id = %s", (user_id,))
user = cursor.fetchone()
print(f"更新后数据:{user}")
return True
else:
print("修改失败,可能没有找到对应的用户")
return False
except Exception as e:
conn.rollback()
print(f"更新失败:{e}")
return False
finally:
cursor.close()
conn.close()
# 调用函数
update_user_age(1, 22)
13. 删除用户记录的核心代码及注意事项
python
import pymysql
def delete_user_by_name(name):
"""根据姓名删除用户"""
conn = pymysql.connect(
host='localhost',
user='root',
password='123456',
database='test_db'
)
try:
cursor = conn.cursor()
# 先查询确认要删除的数据
cursor.execute("SELECT id, name FROM user WHERE name = %s", (name,))
users_to_delete = cursor.fetchall()
if users_to_delete:
print(f"即将删除以下用户:")
for user in users_to_delete:
print(f"ID:{user[0]},姓名:{user[1]}")
# 确认删除(实际应用中可能需要用户二次确认)
confirm = input("确认删除?(y/n):")
if confirm.lower() == 'y':
# 执行删除
sql = "DELETE FROM user WHERE name = %s"
cursor.execute(sql, (name,))
conn.commit()
print(f"删除成功,共删除 {cursor.rowcount} 条记录")
else:
print("取消删除")
else:
print(f"没有找到姓名为 {name} 的用户")
except Exception as e:
conn.rollback()
print(f"删除失败:{e}")
finally:
cursor.close()
conn.close()
# 注意事项:
# 1. 删除前最好备份数据或先查询确认
# 2. 考虑外键约束
# 3. 建议添加软删除字段(is_deleted)替代物理删除
# 4. 批量删除时注意事务控制
14. 查询年龄在18到30之间的用户
python
import pymysql
def get_users_by_age_range():
"""查询年龄在18-30之间的用户"""
conn = pymysql.connect(
host='localhost',
user='root',
password='123456',
database='test_db'
)
try:
cursor = conn.cursor()
# 查询SQL
sql = "SELECT id, name, age FROM user WHERE age > %s AND age < %s"
cursor.execute(sql, (18, 30))
# 获取所有结果
users = cursor.fetchall()
if users:
print(f"共找到 {len(users)} 条符合条件的数据:")
for user in users:
print(f"ID:{user[0]},姓名:{user[1]},年龄:{user[2]}")
else:
print("没有找到符合条件的数据")
return users
finally:
cursor.close()
conn.close()
# 调用函数
get_users_by_age_range()
15. 什么是游标?为什么必须创建游标?
游标(Cursor):
-
数据库操作的一个指针或句柄
-
用于执行SQL语句和管理查询结果
必须创建游标的原因:
-
执行SQL语句的入口
-
管理查询结果集(逐行获取数据)
-
控制事务边界
-
获取受影响行数等信息
python
# 游标的作用示例 cursor = conn.cursor() # 创建游标 cursor.execute(sql) # 执行SQL cursor.fetchone() # 获取一行 cursor.fetchall() # 获取所有行 cursor.rowcount # 获取影响行数 cursor.lastrowid # 获取最后插入ID cursor.close() # 关闭游标
16. fetchone()、fetchall()、fetchmany()的区别
python
import pymysql
conn = pymysql.connect(
host='localhost',
user='root',
password='123456',
database='test_db'
)
cursor = conn.cursor()
cursor.execute("SELECT id, name, age FROM user ORDER BY id")
# 1. fetchone() - 获取单条数据
print("===== fetchone() =====")
row1 = cursor.fetchone()
print(f"第一条:{row1}") # 返回第一条数据
# 适合场景:查询单条记录,如根据ID查询用户详情
# 2. fetchmany(2) - 获取指定条数
print("===== fetchmany(2) =====")
rows2 = cursor.fetchmany(2) # 获取接下来的2条
for row in rows2:
print(row)
# 适合场景:分页查询,分批处理大量数据
# 3. fetchall() - 获取所有剩余数据
print("===== fetchall() =====")
all_rows = cursor.fetchall() # 获取剩余所有数据
for row in all_rows:
print(row)
# 适合场景:数据量较小,需要全部处理的情况
cursor.close()
conn.close()
三种方法的对比:
| 方法 | 返回值 | 适用场景 | 内存占用 |
|---|---|---|---|
| fetchone() | 单条数据(元组) | 单条查询、逐条处理 | 低 |
| fetchmany(n) | 列表(最多n条) | 分批处理、分页 | 中等 |
| fetchall() | 列表(全部数据) | 数据量小、需要全部数据 | 高 |
注意事项:
-
游标是单向的,只能向前获取数据
-
fetchall()在数据量大时可能占用大量内存
-
使用fetchmany()可以平衡内存和性能
更多推荐
所有评论(0)