MySQL学习笔记

MySQL学习笔记

访问量 0

安装&配置&启动

1、MySQL安装

到官网进行下载MySQL安装包,下载网站是:https://downloads.mysql.com/archives/installer

进入网站,选择与本地安装包一致的版本,点击下载;

 

双击安装包:

 

等待程序加载:

 

 

加载成功后选择Custom,点击Next(用于自定义安装):

 

弹出新界面组件为空,点击Back:

 

再点击Full,点击Next:

 

再点击Back:

 

选中Custom,点击Next:

 

选择组件,点击Advanced Options(可以自定义下载目录):

 

自定义目录,此处需要注意,默认路径如下所示:

 

修改路径时,将C盘改为D盘,ProgramData可去掉,修改后路径如下(之后各组件修改全都类似),修改后,点击OK:

 

选择第二个组件,点击Advanced Options:

 

按照如下方式修改路径,点击OK:

 

选择第三个组件,点击Advanced Options:

 

按照如下方式修改路径,点击OK:

 

选择第四个组件,点击Advanced Options:

 

按照如下方式修改路径,点击OK:

 

选择第五个组件,点击Advanced Options:

 

按照如下方式修改路径,点击OK:

 

选择第六个组件,点击Advanced Options:

 

按照如下方式修改路径,点击OK:

 

所有组件完成自定义路径之后点击Next。

 

再点击Execute,等待执行:

 

下载完成之后,点击Next:

 

再点击Execute,等待执行:

 

下载完成后,点击Next:

 

再点击Next:

 

再点击Next:

 

再点击Next:

 

设置密码,重复密码,点击Next:

 

记住名称,后续会用,点击Next:

 

点击Next:

 

点击Execute:

 

执行完成后点击Finish:

 

点击Cancel:

 

点击Yes:

 

电脑下方搜索cmd,右击命令提示符,以管理员身份运行:

 

输入net start mysql80(此处名字即为之前所记名字):

 

点击回车启动:

 

之后关闭该命令提示符。

在搜索框搜索MySQL,点击MySQL 8.0 Command Line,

 

输入密码:

 

回车,显示如下,则连接成功:

 

找到自定义MYSQL下载目录,定位到D:\MySQL\MySQL Server 8.0\bin路径,bin文件夹下,复制路径:

 

右键点击此电脑-属性-搜索高级系统设置-点击查看高级系统设置-点击环境变量-找到Path-点击编辑:

 

点击新建,将路径粘贴,之后层层点确定:

 

关闭之前的命令提示符,再次搜索cmd,右击命令提示符,以管理员身份运行:

 

输入mysql -u root -p,回车,输入密码,回车:

 

 

2、python虚拟环境安装pymysql

进入对应虚拟环境输入如下指令:

text
pip install pymysql

3、启动MySQL

输入如下指令,让MySQL 后台服务运行起来(监听端口):

text
net start MySQL80

执行如下指令,关闭让MySQL 后台服务:

text
net stop MySQL80

执行如下指令,让客户端程序去连接正在运行的服务:

text
mysql -u root -p

指令&操作

认识MySQL

如果将数据库管理系统与文件管理做类比的话:

数据库管理系统文件管理
数据库文件夹
数据表文件夹下的excel文件

数据库管理

内置客户端操作

当连接上MYSQL之后,执行如下指令(一般称为SQL语句),就可以对MYSQL的数据库进行操作。

  • 查看当前所有的数据库
sql
show databases;
  • 创建数据库
sql
create database db1 default charset utf8 collate utf8_general_ci;
  • 切换进入数据库
sql
use 数据库名;
  • 删除数据库
sql
drop database db1;
  • 查看当前库下所有表
sql
show tables;

python代码操作

python
import pymysql


# 连接MySQL (socket)

conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='root123', charset="utf8")

cursor = conn.cursor()

  

# 1. 查看数据库

# 发送指令

cursor.execute("show databases")

# 获取指令的结果

result = cursor.fetchall()

print(result)  # (('information_schema',), ('mysql',), ('performance_schema',), ('sys',))

  

# 2. 创建数据库 (新增、删除、修改)

# 发送指令

cursor.execute("create database db3 default charset utf8 collate utf8_general_ci")

conn.commit()

  

# 3. 查看数据库

# 发送指令

cursor.execute("show databases")

# 获取指令的结果

result = cursor.fetchall()

print(result)  # (('information_schema',), ('db3',), ('mysql',), ('performance_schema',), ('sys',))

  

# 4. 删除数据库

# 发送指令

cursor.execute("drop database db3")

conn.commit()

  

# 3. 查看数据库

# 发送指令

cursor.execute("show databases")

# 获取指令的结果

result = cursor.fetchall()

print(result)  # (('information_schema',), ('mysql',), ('performance_schema',), ('sys',))

  

# 5. 进入数据库,查看表

# 发送指令

cursor.execute("use mysql")

cursor.execute("show tables")

result = cursor.fetchall()

print(result)  # (('columns_priv',), ('db',), ('engine_cost',), ('event',), ('func',), ('general_log',),.....

  

# 关闭连接

cursor.close()

conn.close()

数据表管理

内置客户端操作

表操作
  • 创建表 语法模板
sql

create table 表名(
    列名 类型,
    列名 类型,
    列名 类型
)default charset=utf8;

示例

sql
create table tbl1(
    id int,
    name varchar(16)
)default charset=utf8;
sql
create table tbl2(
    id int primary key,    -- 主键(不允许为空,不允许重复)
    name varchar(16) not null,    -- 不允许为空
    email varchar(32) null,    -- 允许为空
    age int default 3    -- 插入数据时,未给age设值,则默认为3 
)default charset=utf8;

主键一般用于表示当前这条数据的ID编号(类似于人的身份证),需要我们自己来维护一个不重复的值,比较繁琐。所以,在数据库中一般会将主键和自增结合。

注意:一个表中,只能有一个自增列,一般都是主键。

sql
create table tbl3(
    id int not null auto_increment primary key,    -- 主键(不允许为空,不允许重复),自增
    name varchar(16) not null,    -- 不允许为空
    email varchar(32) null,    -- 允许为空
    age int default 3    -- 插入数据时,未给age设值,则默认为3 
)default charset=utf8;
  • 查看表结构
sql
desc 表名;
  • 删除表
sql
drop table 表名;
  • 插入数据
sql
insert into 表名(1,2) values(1,2);

示例

sql
insert into tbl1(id,name) values(1,"张三");
  •  查询表全部数据
sql
select * from 表名;
  •  更新修改数据
sql
update 表名 set 1=1 where 条件;
  •  删除行数据
sql
delete from 表名 where 条件;
sql
truncate table 表名;

- 修改表-新增列

sql
alter table 表名 add 列名 类型;
alter table 表名 add 列名 类型 DEFAULT 默认值;
alter table 表名 add 列名 类型 not null default 默认值;
alter table 表名 add 列名 类型 not null primary key auto_increment;
  •  修改表-修改列
sql
alter table 表名 modify 列名 新类型;
  •  修改表-重命名列
sql
alter table 表名 change 旧列名 新列名 类型;

alter table tb change id nid int not null;
alter table tb change id id int not null default 5;
alter table tb change id id int not null primary key auto_increment;

alter table tb change id id int; --允许为空,删除默认值,删除自增。
  •  修改表-删除列
sql
alter table 表名 drop 列名;
数据类型
整型
  • int[(m)][unsigned][zerofill]
  • tinyint[(m)] [unsigned] [zerofill]
    • 有符号,取值范围 : -128~127.
    • 无符号,取值范围:0~255
  • bigint[ (m) ] [unsigned] [zerofill]
    • 有符号,取值范围 :- 9223372036854775808~9223372036854775807
    • 无符号,取值范围:0 ~ 18446744073709551615
类型说明
int表示有符号,取值范围 :- 2147483648 ~ 2147483647
int unsigned表示无符号,取值范围:0~4294967295
int(5) zerofill仅用于显示,当不满足5位时,按照左边补0,例如:00002;满足时,正常显示。
sql

mysql> create table L1(id int, uid int unsigned, zid int(5) zerofill)

default charset=utf8;

Query OK, 0 rows affected (0.03 sec)

  

mysql> insert into L1(id,uid,zid) values(1,2,3);

Query OK, 1 row affected (0.00 sec)

  

mysq1> insert into L1(id,uid,zid) values(2147483641,4294967294,300000) ;

Query OK, 1 row affected (0.00 sec)

  

mysql> select * from L1;

+------------+------------+--------+
| id         | uid        | zid    |
+------------+------------+--------+
|          1 |          2 |  00003 |
| 2147483641 | 4294967294 | 300000 |
+------------+------------+--------+
2 rows in set (0.00 sec)



mysql> insert into L1(id,uid,zid) values(214748364100,4294967294,300000) ;

ERROR 1264 (22003): Out of range value for column 'id' at row 1
小数
  • decimal[(m[,d])] [unsigned] [zerofill]

    • 准确的小数值,m是数字总个数(负号不算),d是小数点后个数。m最大值为65,d最大值为30。
  • FLOAT[ (M,D) ] [UNSIGNED] [ZEROFILL]

    • 单精度浮点数,非准确小数值,m是数字总个数,d是小数点后个数。
  • DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]

    • 双精度浮点数(非准确小数值),m是数字总个数,d是小数点后个数。

    例如:

sql
create table L2(
id int not null primary key auto_increment,
salary decimal(8,2)
)default charset=utf8;
sql
mysql> create table L2(id int not null primary key auto_increment, salary decimal(8,2))default charset=utf8;

Query OK, 0 rows affected (0.03 sec)

  

mysql> insert into L2(salary) values(1.28);

Query OK, 1 row affected (0.01 sec)

  

mysql> insert into L2(salary) values(5.289);

Query OK, 1 row affected, 1 warning (0.00 sec)

  

mysql> insert into L2(salary) values(5.282);

Query OK, 1 row affected, 1 warning (0.00 sec)

  

mysql> insert into L2(salary) values(512132.28) ;

Query OK, 1 row affected (0.00 sec)

  

mysql> insert into L2(salary) values(512132.283) ;

Query OK, 1 row affected, 1 warning (0.00 sec)

  

mysql> select * from L2;

+----+-----------+
| id | salary    |
+----+-----------+
|  1 |      1.28 |
|  2 |      5.29 |
|  3 |      5.28 |
|  4 | 512132.28 |
|  5 | 512132.28 |
+----+-----------+
5 rows in set (0.00 sec)



mysql> insert into L2(salary) values(5121321.283);
ERROR 1264 (22003): Out of range value for column 'salary' at row 1
字符串

char (m)

定长字符串,m代表字符串的长度,最多可容纳255个字符。

定长的体现:即使内容长度小于m,也会占用m长度。例如:char(5),数据是:yes,底层也会占用5个字符;如果超出m长度限制(默认MySQL是严格模式,所以会报错)。如果在配置文件中加入如下配置,`sql-mode="NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"`保存并重启,此时MySQL则是非严格模式,此时超过长度则自动截断(不报错)。

注意:默认底层存储是固定的长度(不够则用空格补齐),但是查询数据时,会自动将空白去除。如果想要保留空白,在sql-mode中加入 PAD_CHAR_TO_FULL_LENGTH 即可。 查看模式sql-mode,执行命令:show variables like 'sql_mode'; 一般适用于:固定长度的内容。

varchar (m)

变长字符串,m代表字符串的长度,最多可容纳65535个字节。

变长的体现:内容小于m时,会按照真实数据长度存储;如果超出m长度限制(默认MySQL是严格模式,所以会报错)。如果在配置文件中加入如下配置,sql-mode="NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"保存并重启,此时MySQL则是非严格模式,此时超过长度则自动截断(不报错)。

例如:

sql
create table L3(id int not null primary key auto_increment,name varchar(5),depart char(3))default charset=utf8;

text

text数据类型用于保存变长的大字符串,可以组多到65535(2 ** 16-1)个字符。一般情况下,长文本会用text类型。例如:文章、新闻等。

sql
create table L4(id int not null primary key auto_increment,title varchar(128),content text)default charset=utf8;

mediumtext

A TEXT column with a maximum length of 16,777,215 (2 ** 24 - 1) characters.

longtext

A TEXT column with a maximum length of 4,294,967,295 or 4GB (2 ** 32 - 1)

时间

datetime

YYYY-MM-DD HH:MM:SS (1000-01-01 00:00:00/9999-12-31 23:59:59)

timestamp

YYYY-MM-DD HH:MM:SS (1970-01-01 00:00:00/2037)

对于TIMESTAMP,它把客户端插入的时间从当前时区转化为UTC(世界标准时间)进行存储,查询时,将其又转化为客户端当前时区进行返回。对于DATETIME,不做任何改变,原样输入和输出。

sql
mysql> create table L5(id int not null primary key auto_increment,dt datetime,tt timestamp)default charset=utf8;

Query OK, 0 rows affected (0.03 sec)



mysql> insert into L5(dt,tt) values("2025-11-11 11:11:44", "2025-11-11 11:11:44");

Query OK, 1 row affected (0.00 sec)



mysql> select * from L5;

+----+---------------------+---------------------+
| id | dt                  | tt                  |
+----+---------------------+---------------------+
|  1 | 2025-11-11 11:11:44 | 2025-11-11 11:11:44 |
+----+---------------------+---------------------+
1 row in set (0.00 sec)

date

YYYY-MM-DD (1000-01-01/9999-12-31)

time

HH:MM:SS (’-838:59:59’ /‘838: 59:59 ‘)

MySQL还有很多其他的数据类型,例如:set、enum、TinyBlob、Blob、MediumBlob、LongBlob等,详细见官方文档:https://dev.mysql.com/doc/refman/5.7/en/data-ty.pes.html

python代码操作

python
import pymysql


# 连接MySQL
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='root123', charset="utf8")
cursor = conn.cursor()

# 1. 创建数据库
"""
cursor.execute("create database db4 default charset utf8 collate utf8_general_ci")
conn.commit()
"""

# 2. 进入数据库、查看数据表
"""
cursor.execute("use db4")
cursor.execute("show tables")
result = cursor.fetchall()
print(result)
"""

# 3. 进入数据库创建表
cursor.execute("use db4")
sql = 
"""
create table L4(
    id int not null primary key auto_increment,
    title varchar(128),
    content text,
    ctime datetime
)default charset=utf8;
"""
cursor.execute(sql)
conn.commit()

# 4. 插入单条数据
"""
cursor.execute("use db4")
sql = "insert into L4(title,content,ctime) values(%s,%s,%s)"
cursor.execute(sql, ("标题1","内容文本","2026-08-17 16:48:35"))
conn.commit()
"""

# 5. 批量插入多条数据
"""
cursor.execute("use db4")
sql = "insert into L4(title,content,ctime) values(%s,%s,%s)"
data_list = [
    ("标题2","内容2","2026-08-17 17:00:00"),
    ("标题3","内容3","2026-08-17 17:05:00")
]
cursor.executemany(sql, data_list)
conn.commit()
"""

# 6. 查询全部数据 fetchall()
"""
cursor.execute("use db4")
cursor.execute("select * from L4")
result = cursor.fetchall()
print(result)
"""

# 7. 查询单条数据 fetchone()
"""
cursor.execute("use db4")
cursor.execute("select * from L4 where id=1")
result = cursor.fetchone()
print(result)
"""

# 8. 修改更新数据 update
"""
cursor.execute("use db4")
sql = "update L4 set title=%s where id=%s"
cursor.execute(sql, ("修改后的标题",1))
conn.commit()
"""
# 9. 删除数据 delete
"""
cursor.execute("use db4")
sql = "delete from L4 where id=%s"
cursor.execute(sql,(1,))
conn.commit()
"""

# 10. 删除表
"""
cursor.execute("use db4")
cursor.execute("drop table if exists L4")
conn.commit()
"""

# 11. 删除数据库
"""
cursor.execute("drop database if exists db4")
conn.commit()
"""

# 12. 关闭游标、关闭连接
"""
cursor.close()
conn.close()
"""

数据行管理

内置客户端操作

新增数据
sql
--语法
insert into 表名 (列名,列名,列名) values(对应列的值,对应列的值,对应列的值);
--示例
insert into tbl(name,password) values('武沛齐','123123');
insert into l1(uid,zid) values('10','123123');
--批量插入多行
insert into tbl(name,password) values('武沛齐','123123'),('alex','123');

--省略列名:表字段顺序和values值顺序完全一致,表只有2列时可简写
insert into tbl values('武沛齐','123123'),('alex','123');
删除数据
sql
--语法
delete from 表名;
delete from 表名 where 条件;
--示例
delete from tbl; --清空整张表全部数据(不会重置自增主键)
delete from tbl where name="wupeiqi";
delete from tbl where name="wupeiqi" and password="123";
delete from tbl where id>9;
修改数据
sql
--语法
update 表名 set 列名=;
update 表名 set 列名= where 条件;
--示例
update l1 set id=3 where uid=10;
update tbl set name="wupeiqi"; --不带where,全表所有行全部修改,慎用!
update tbl set name="wupeiqi" where id=1;
update tbl set age=age+1 where id=2; --基于原有值做运算
update users set name=concat(name,"123") where id=2; --concat()字符串拼接函数
查询数据
sql
--语法
select * from 表名;
select 列名,列名,列名 from 表名;
--扩展常用示例
select * from tbl; --查询表全部列全部数据
select name,password from tbl; --只查询指定列
select * from tbl where id>2; --带条件查询
select * from tbl order by id desc; --排序
select * from tbl limit 0,10; --分页

python代码操作

相关操作
python
import pymysql


#连接数据库
conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='root123',charset="utf8")
cursor = conn.cursor()

#切换数据库
cursor.execute("use db4")

# ==========1.新增数据 insert==========
"""
#单条插入
sql = "insert into tbl(name,password) values(%s,%s)"
cursor.execute(sql,("武沛齐","123123"))

#批量插入
sql2 = "insert into tbl(name,password) values(%s,%s)"
data = [("武沛齐","123123"),("alex","123")]
cursor.executemany(sql2,data)

conn.commit()
"""

# ==========2.删除数据 delete==========
"""
sql = "delete from tbl where name=%s"
cursor.execute(sql,("wupeiqi",))
conn.commit()
"""

# ==========3.修改数据 update==========
"""
sql = "update tbl set name=%s where id=%s"
cursor.execute(sql,("wupeiqi",1))
conn.commit()
"""

# ==========4.查询数据 select==========
"""
cursor.execute("select * from tbl")
res = cursor.fetchall()
print(res)
cursor.execute("select name,password from tbl where id>%s",(2,))
res2 = cursor.fetchall()
print(res2)
"""
#关闭
cursor.close()
conn.close()
用户管理系统案例

第一步:MySQL 客户端执行,创建数据库和表结构

mysql
-- 创建数据库 
userdb create database userdb default charset utf8 collate utf8_general_ci; 
-- 创建 users 用户表 
create table users( id int not null primary key auto_increment, name varchar(32), password varchar(64) )default charset=utf8;

Python 代码实现注册功能(存在 SQL 注入漏洞,仅作学习演示,禁止生产使用)

python
import pymysql


def register():
    print("用户注册")
    user = input("请输入用户名:")
    password = input("请输入密码:")

    # 连接指定数据库
    conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', charset="utf8", db="userdb")
    cursor = conn.cursor()

    # 执行sql语句(有sql注入风险)
    sql = 'insert into users(name,password) values("{}","{}")'.format(user, password)
    cursor.execute(sql)
    conn.commit()

    # 关闭数据库连接
    cursor.close()
    conn.close()

    print("注册成功, 用户名: {},密码:{}".format(user, password))


def login():
    """原版风格登录,同样使用format拼接,存在注入漏洞"""
    print("用户登录")
    user = input("请输入用户名:")
    password = input("请输入密码:")

    conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='root123', charset="utf8", db="userdb")
    cursor = conn.cursor()

    # format拼接SQL,存在SQL注入
    sql = 'select * from users where name="{}" and password="{}"'.format(user, password)
    cursor.execute(sql)
    result = cursor.fetchone()

    cursor.close()
    conn.close()

    if result:
        print("登录成功")
    else:
        print("用户名或密码错误")

if __name__ == '__main__':
    while True:
        op = input("请选择功能:1注册 | 2登录 | 3退出\n>>>")
        if op == "1":
            register()
        elif op == "2":
            login()
        elif op == "3":
            break
        else:
            print("输入无效")
  • 原代码问题:SQL 注入风险

直接使用format()拼接用户输入到 SQL 字符串,黑客可以构造特殊输入篡改 SQL 逻辑。

注入示例

用户名输入:abc","123");delete from users;--

拼接后 SQL 变成:

sql

text
insert into users(name,password) values("abc","123");delete from users;-- ","xxx")

会直接把 users 表全部数据删除。

SQL注入

在 Python 开发中如何避免 SQL 注入

切记,SQL 语句不要使用 python 的字符串格式化,而是使用 pymysql 的 execute 方法传参。
python
import pymysql

# 输入用户名和密码
user = input("请输入用户名:")
pwd = input("请输入密码:")

conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='root123', charset="utf8", db='userdb')
cursor = conn.cursor()

# 列表传参方式
cursor.execute("select * from users where name=%s and password=%s", [user, pwd])

# 或者字典命名占位符传参方式
# cursor.execute("select * from users where name=%(name)s and password=%(pwd)s", {"name": user, 'pwd': pwd})

result = cursor.fetchone()
print(result)

cursor.close()
conn.close()

安全写法:pymysql 占位符 % s,交给 execute 传参,禁止 format 拼接

用户管理系统完善后的代码:

python
import pymysql

def get_db_conn():
    """封装获取数据库连接,复用代码"""
    conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', charset="utf8", db="userdb")
    cursor = conn.cursor()
    return conn, cursor


def register():
    """安全版本注册"""
    print("====用户注册====")
    user = input("请输入用户名:")
    password = input("请输入密码:")

    conn, cursor = get_db_conn()
    sql = "insert into users(name,password) values(%s,%s)"
    cursor.execute(sql, (user, password))
    conn.commit()

    cursor.close()
    conn.close()
    print(f"注册成功,用户名:{user}")


def login():
    """用户登录"""
    print("====用户登录====")
    user = input("请输入用户名:")
    password = input("请输入密码:")

    conn, cursor = get_db_conn()
    sql = "select * from users where name=%s and password=%s"
    cursor.execute(sql, (user, password))
    res = cursor.fetchone()  # 查询匹配的一行数据

    cursor.close()
    conn.close()

    if res:
        print("登录成功")
    else:
        print("用户名或密码错误")


# 主程序入口
if __name__ == '__main__':
    while True:
        choice = input("请选择功能:1注册  2登录  3退出\n>>>")
        if choice == "1":
            register()
        elif choice == "2":
            login()
        elif choice == "3":
            break
        else:
            print("输入错误,请重新选择!")