MySQL入门
-MySQL入门
学习步骤
1. 安装MySQL软件
2. 基本配置并启动服务
3. 创建数据库(类似于创建文件夹)
4. 创建表结构(类似于创建文件夹下的excle文件)
5. 创建账户并授权(让程序使用此账户访问数据库中的表)
6. 安装pymysql模块(python操作MySQL)
7. 基于pymysql模块连接MySQL
8. 基于pymysql模块发送指令
win系统安转
1.下载官网:https://downloads.mysql.com/archives/community/
免安装软件,只要解压即可。
2.创建配置文件my.ini, 放在安装目录下
[mysqld] # port port = 3306 # set basedir to your installation path basedir = D:\\Program Files\\mysql-8.0.29-winx64 -安装目录 # set datadir to the location of yourdata directory datadir = D:\\Program Files\\mysql-8.0.29-winx64\\data -数据目录
配置文件的查询机制
cmd:>"D:\\Program Files\\mysql-8.0.29-winx64\bin\mysqld.exe" --help --verbose

图1 数据库配置查询
3.初始化cmd
"D:\\Program Files\\mysql-8.0.29-winx64\bin\mysqld.exe" --initialize-insecure
初始化本质做了两件事:
1)根据配置文件,创建data目录,在data目录里面初始化一些数据库必备的数据;
2)除此以外还会帮助我们创建一些账户,比如root(没有密码)。
如果报错:
下载vcredist:https://www.mircrosoft.com/zh-cn/download/confirmation.aspx?id=40784 (主要)
下载dirctx: https://www.mircrosoft.com/zh-CN/download/details.aspx?id=35
4.启动
临时启动
"D:\\Program Files\\mysql-8.0.29-winx64\bin\mysqld.exe"
注意,这个地方的双引号的作用是将引号中的内容视为一个整体,避免出现空格时默认命令结束了。
制作服务管理(需要管理员权限)
"D:\Program Files\mysql-8.0.29-winx64\bin\mysqld.exe" --install mysql8029
通过服务开启
net start mysql8029
通过服务关闭
net stop mysql8029
删除服务
"D:\Program Files\mysql-8.0.29-winx64\bin\mysqld.exe" --remove mysql8029 (可以不写名字,需要管理员权限)
5.测试链接上服务
"D:\\Program Files\\mysql-8.0.29-winx64\bin\mysql.exe" -h 127.0.0.1 -P 3307 -u root -p (如果是本机,可以不写-h和-P)
6.加环境变量
指令学习
1.查看数据库
show databases;
2.退出
exit;
关于配置
关于密码
1.设置密码(可登录的情况)
set password='root123'
2.忘记密码
修改配置文件
skip-grant-tables=1
重启服务
net stop mysql8029
net start mysql8029
重启后进入
mysql -u root -p
进入后修改密码
use mysql;
updata user set authentication_string = '新密码',password_last_changed=now() whele user = 'root';
退出修改配置文件
# skip-grant-tables=1
再次重启。
数据库管理系统(DBMS)
注意两个概念:
数据库:相当于文件夹
数据表:相当于文件夹下excel表格
数据库(文件夹)的操作指令
数据库的操作指令必须以分号结尾,表示指令结束。
show databases; 查看数据库。
show databases;
create database 数据库名; 创建的数据库。
create database db25;
但是这样是不够的,我们在创建文件的时候一般需要考虑它的编码。
create database db24 default charset utf8 collate utf8_general_ci;
注意,数据库不区分大小写,包括文件名或者表格名等,默认小写字母。
drop database 数据库名;删除数据库。
drop database db25;
use 数据库名;进入数据库,相当于进入文件夹,可以不写分号。
use db24;
基于python操作:
# 导入pymysql库 import pymysql # 打开数据库连接(socket) conn = pymysql.connect(host='localhost',port=3306,user='root',password='WENPENG1994325',charset='utf8') # 使用cursor()方法获取操作游标 cursor = conn.cursor() # 1.查看数据库 # 发送指令 cursor.execute('show databases') # 获取指令的结果 result = cursor.fetchall() print(result) # (('day25',), ('information_schema',), ('mysql',), ('performance_schema',), ('sakila',), ('sys',), ('world',)) # 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) # (('day25',), ('db3',), ('information_schema',), ('mysql',), ('performance_schema',), ('sakila',), ('sys',), ('world',)) # 4.删除数据库 cursor.execute('drop database db3') conn.commit() # 5.查看数据库 cursor.execute('show databases') result = cursor.fetchall() print(result) # (('day25',), ('information_schema',), ('mysql',), ('performance_schema',), ('sakila',), ('sys',), ('world',)) # 进入数据库 cursor.execute('use day25') cursor.execute('show tables') result = cursor.fetchall() print(result) # () # 关闭连接 cursor.close() conn.close()
运用python操作数据库,其根本和终端操作类似,python扮演着第三方模块的角色。需要掌握下面几个知识点。
1)python和数据的链接需要通过pymysql库来实现;
2)-.connect(host='localhost',user='root',password='WENPENG1994325',charset='utf8') 建立链接,相当于接口。host:表示id,如果是本机,可以写127.0.0.1或者localhost,port: 表示接口,默认3306; 如果是本机,上述两个参数均可以不写;user: 用户,主用户为root;password: 登陆密码;charset: 操作文件的编码,一般情况下都用utf8;database: 指定数据库(文件夹)。
3)有了接口还不够,还需要一个游标,表示当前所在位置,作用相当于鼠标。游标直接通过接口生成conn.cursor()。默认游标在根目录下,如果链接时指定数据库(文件夹),则初始游标在该目录下。
4)-.execute() 发送指令,这是python与数据库交流的桥梁,python可以通过它发送指令给数据库。
5)发送增加,删除,修改数据库的命令时,需要用conn.commit()指示接口执行。
6)发送查看数据库或者数据时,需要用-.fetchall(),-.fetchone()来解析数据。
7)-.close()关闭游标或者数据库接口。
数据表(excle表格)的操作指令
表格的创建以及数据列操作
0)进入数据库用use 数据库; 查看数据库下的数据表用show tables;
1)创建数据表:
create table 表名( 列名 类型, 列名 类型, 列名 类型 )default charset=utf8;
注意:这里的编码不用字符串。
create table tb1( id int; name varchar(16) )default charset=utf8;
有的时候需要指定一些要求,比如是否运行数据为空。
create table tb2( id int, name varchar(16) not null, --不允许为空 email varchar(32) null, --允许为空(默认) age int )default charset=utf8;
当然还有时需要默认值。
create table tb3( id int, name varchar(16) not null, --不允许为空 email varchar(32) null, --允许为空(默认) age int default 3 --插入数据时,如果不给age列设置值,默认为:3 )default charset=utf8;
注意:在mysql中双横线表示注释。
主键(用于区别数据条的列,不允许为空,也不能重复),一般用于当前数据的ID编号(类似于人的身份证),用于区分不同的数据。
create table tb4( id int primary key, --主键(不允许为空、不能重复) name varchar(16) not null, --不允许为空 email varchar(32) null, --允许为空(默认) age int default 3 --插入数据时,如果不给age列设置值,默认为:3 )default charset=utf8;
怎么样做到不重复呢?自增!
create table tb5( 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;
一般情况下,一张表里有且只有一个自增列,用于标识数据。
2)删除表:drop table 表名;
3)清空表:delete from 表名;或 truncate table 表名;
两者的区别:truncate table 表名; 比 delete from 表名 的清空速度要快,但是用它清楚后的数据不可恢复。
4)修改表
- 添加列
alter table 表名 add 列名 类型; alter table 表名 add 列名 类型 default 默认值; alter table 表名 add 列名 类型 not null default 默认值; alter table 表名 add 列名 类型 not null primary key auto_increment;
- 删除列
alter table 表名 drop column 列名;
- 修改列 类型
alter table 表名 modify column 列名 类型
- 修改列 类型 + 名称
alter table 表名 change 原列名 新列名 新类型;
alter table tb1 change id id int not null; alter table tb1 change id id int not null default 5; alter table tb1 change id id int not null primary key auto_increment; alter table tb1 change id id int;
- 修改列 默认值
alter table 表名 alter 列名 set default 1000;
- 删除列 默认值
alter table 表名 alter 列名 drop default;
- 添加主键
alter table 表名 add primary key(列名)
- 删除主键
alter table 表名 drop primary key;
注意:主键只能出现一个,故只能设置一次,重复设置会抛出异常:ERROR 1068 (42000): Multiple primary key defined,如果想修改需要先删除主键。
5) 查看表格的列(类型):desc 表名;
常见列类型
整形系列
int[(m)][unsigned][zerofill]
m: 字符长度,有符号限制:-2147483648~2147483647,有符号限制:0~4294967295
unsigned: 标识无符号
zerofill: 是否填充零
mysql> create table L1( -> id int, -> uid int unsigned, -> zid int(5) zerofill -> )default charset=utf8; Query OK, 0 rows affected, 3 warnings (0.02 sec) mysql> insert into L1(id,uid,zid) values (1,2,3); Query OK, 1 row affected (0.01 sec) mysql> insert into L1(id,uid,zid) values (2147483641,4294967294,30000); Query OK, 1 row affected (0.01 sec) mysql> select * from L1; +------------+------------+-------+ | id | uid | zid | +------------+------------+-------+ | 1 | 2 | 00003 | | 2147483641 | 4294967294 | 30000 | +------------+------------+-------+ 2 rows in set (0.00 sec) mysql> insert into L1(id,uid,zid) values (214748364100,4294967294,30000); ERROR 1264 (22003): Out of range value for column 'id' at row 1
mysql> insert into L1(id,uid,zid) values (2147483641,4294967294,300000); Query OK, 1 row affected (0.01 sec) mysql> select * from L1; +------------+------------+--------+ | id | uid | zid | +------------+------------+--------+ | 1 | 2 | 00003 | | 2147483641 | 4294967294 | 30000 | | 2147483641 | 4294967294 | 300000 | +------------+------------+--------+ 3 rows in set (0.00 sec)
注意:严格模式和非严格模式,非严格模式会出现截断。
另外,对于具体的使用,还有两种整形,tinyint和bigint。
tinyint [(m)][unsigned][zerofill]
有符号限制:-128~127,有符号限制:0~255
bigint[(m)][unsigned][zerofill]
有符号限制:-9223372036854775808~9223372036854775807,有符号限制:0~18446744073709551615
小数系列
decimal [(m[,d])][unsigned][zerofill]
准确小数值。
m: 数字总个数(负号不算)。
d: 小数点后个数。
m最大值为65,d的最大值为30。
mysql> create table L2( -> id int not null primary key auto_increment, -> salary decimal(8,2) -> )default charset=utf8; Query OK, 0 rows affected, 1 warning (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.01 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(5121732.283); ERROR 1264 (22003): Out of range value for column 'salary' at row 1
需要注意的是,当小数点后的位数超出范围时,将发生四舍五入截断,不会报错,但是当整数部分超出范围时,严格意义下会报错。
类似的,小数也有其他的函数。
float[(m,d)][unsigned][zerofill]
单精浮点数,非准确小数值,32位存储。
double[(m,d)][unsigned][zerofill]
双精度浮点数,非准确小数值,64位存储。
非准确小数值,位数越多越不准确,所以不常用。
字符串系列
char(m)
定长字符串,会占用相应的字符数,少于这个数系统会补齐,多于这个数,严格模式下会报错。非严格模式,进行截断。m具有限制最多可容纳255个字符。如果想查看补齐的元素,通过下面的语句修改配置文件即可。
sql-mode="NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH"
varchar(m)
变长字符串,不同于char(m)的是,数据实际有多少就占多少,少于m时不会补齐,但是多于m的时候和char一样。不一样的是,varchar最多可容纳65535个字节。
严格模式和非严格模式。默认是严格模式,可以通过修改配置文件变成非严格模式。
sql-mode="NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
除了char和varchar以为还有一些类型是存储字符串的。比如text,mediumtext,longtext。不同的是,它们可容纳的字符串长度是不一样的。
text:用于保存变长的大字符串,最多可容纳65535(2**16-1)个字符。一般情况下,长文本会使用text,比如:新闻,文章等。
nediumtext: 最多可容纳16,777,215(2**24-1)个字符。
longtext: 最多可容纳4,294,967,295 或 4GB(2**32-1)个字符。
时间
datatime
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还与时区有关系,具体看下面的实验。
mysql> create table L5( -> id int not null primary key auto_increment, -> dt datetime, -> tt timestamp -> )default charset=utf8; Query OK, 0 rows affected, 1 warning (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.01 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) mysql> show variables like '%time_zone%'; -- 查看时区设置 +------------------+--------+ | Variable_name | Value | +------------------+--------+ | system_time_zone | | | time_zone | SYSTEM | +------------------+--------+ 2 rows in set, 1 warning (0.04 sec) mysql> set time_zone='+0:00'; -- 修改时区设置 Query OK, 0 rows affected (0.00 sec) mysql> show variables like '%time_zone%'; +------------------+--------+ | Variable_name | Value | +------------------+--------+ | system_time_zone | | | time_zone | +00:00 | +------------------+--------+ 2 rows in set, 1 warning (0.00 sec) mysql> select * from L5; +----+---------------------+---------------------+ | id | dt | tt | +----+---------------------+---------------------+ | 1 | 2025-11-11 11:11:44 | 2025-11-11 03:11:44 | +----+---------------------+---------------------+ 1 row in set (0.00 sec)
系统默认的时区就是我们当前的时区,默认情况下,二者的区别就是范围,由于datatime的范围比较大,所以我们倾向于使用datatime。
除此以外单独使用日期的时候,我们用date,单独使用时间的时候用time。
date YYYY-MM-DD(1000-01-01/9999-12-31)
time HH:MM:SS(-838:59:59/ 838:59:59)
小结
MySQL还有很多其他的数据类型,例如:set、enum、TinyBlob、MediumBlob、LongBlob等,详见官方文档:https://dev.mysql.com/doc/refman/5.7/en/data-types.huml
python代码实现
import pymysql # 连接数据库 conn = pymysql.connect(host='localhost', port=3306, user='root', password='WENPENG1994325!', charset='utf8' ) cursor = conn.cursor() # 1.创建数据库 cursor.execute('drop database db26') cursor.execute('create database db26 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('drop table L4') 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('show tables') result = cursor.fetchall() print(result) # 5.其他drop table ... 略过 # 关闭连接 cursor.close() conn.close()
数据行操作 *****
1)新增数据
insert into 表名(列名,列名,列名) values(对应列的值,对应列的值,对应列的值)
mysql> insert into tb1(name,password) values('吴佩琪','123123'); Query OK, 1 row affected (0.01 sec) mysql> insert into values('吴佩琪','123123'),('alex','123'); Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> insert into tb1 values('吴佩琪','123123'),('alex','123'); --这种情况仅仅限于表中只有2列的情况 Query OK, 2 rows affected (0.01 sec) Records: 2 Duplicates: 0 Warnings: 0
2)删除数据
delete from 表名; delete from 表名 where 条件;
delete from tb1; delete from tb1 where name="wupeiqi"; delete from tb1 where name="wupeiqi" and password="123"; delete from tb1 where id>9;
注意:这里的条件与其他地方的不一样,这个地方等于用的是等号,而不是双等号。
3)修改数据
update 表名 set 列名=值; update 表名 set 列名=值 where 条件;
update tb1 set name="wupeiqi"; update tb1 set name="wupeiqi" where id=1; update tb1 set age=age+1 where id=2; -- age必须是整形,字符串不可以直接相加,需要用到下面的concat函数 update users set name=concat(name,"123") where id=2; --concat函数:可以拼接字符串
4)查询数据
select * from 表名; select 列名,列名,列名 from 表名; select 列名,列名 as 列名,列名 from 表名;-- 查询的时候修改列名 select * from 表名 where 条件;
select * from tb1; --这里的*代指所有的列 select id,name,age from tb1; -- select 选择列 select id,name as N from tb1; --数据库采用的是就近原则,修改后面修改后面一个列的名字。 select id,name,111 as N from tb1; --额外显示一列111,值默认为111
select id,name,111 as age from tb1; --将111这一列的的列名改为age select * from tb1 where id=1; --where条件选择行 select * from tb1 where id>1; select * from tb1 where id!=1; select * from tb1 where name="wupeiqi" and password="123";
python实现数据行增删改查
import pymysql # 数据行的增删改查 # 连接mysql conn = pymysql.connect( host='localhost', port=3306, user='root', password='WENPENG1994325', charset='utf8', database='db24' # 自动执行use db24 --进入数据库 ) cursor = conn.cursor() # 1.新增(需commit) cursor.execute('insert into tb1(name,password) values("吴佩琪","123123")') conn.commit() # 增加id自增列主键 # cursor.execute('alter table tb1 add id int not null primary key auto_increment') # 2.删除(需commit) cursor.execute('delete from tb1 where id =1 ') conn.commit() # 3.修改(需commit) cursor.execute('update tb1 set name = "wu" where id=2') conn.commit() # 4.查询 cursor.execute('select * from tb1') data = cursor.fetchall() print(data) # 关闭连接 cursor.close() conn.close()
应用案例
其实真正做项目开发时,流程如下:
第一步:根据项目的功能来设计相应的数据库&表结构(不会经常变动,在项目设计之初就确定好了)。
第二步:操作表中的数据,已达到实现业务逻辑的目的。
例子:实现一个用户管理系统。
先使用MySQL自带的客户端创建相关数据库和表结构(相当于创建好Excel结构)。
mysql> create database userdb default charset utf8 collate utf8_general_ci; Query OK, 1 row affected, 2 warnings (0.01 sec)
mysql> use userdb Database changed mysql> create table users( -> id int not null primary key auto_increment, -> name varchar(32), -> password varchar(64) -> )default charset=utf8; Query OK, 0 rows affected, 1 warning (0.02 sec)
再在程序中执行编写相应的功能实现注册、登陆等功能。
import pymysql def register(): print("用户注册") name = input("请输入用户名:") password = input("请输入密码:") # 连接指定的数据库 conn = pymysql.connect( host='localhost', port=3306, user='root', password="WENPENG1994325", database='userdb', charset='utf8' ) cursor = conn.cursor() # 发送命令保存用户名和密码 # sql = insert into user(name,password) values("name","password") cursor.execute('insert into users(name,password) values("{name}","{password}")'.format(name=name,password=password)) conn.commit() # 关闭数据库连接 cursor.close() conn.close() def login(): print('用户登陆') name = input("请输入用户名:") password = input("请输入密码:") # 连接指定的数据库 conn = pymysql.connect( host='localhost', port=3306, user='root', password="WENPENG1994325", database='userdb', charset='utf8' ) cursor = conn.cursor() # 发送命令查询数据 # sql = select * from users where name = "name" and password="password" cursor.execute('select * from users where name = "{name}" and password="{password}"'.format(name=name,password=password)) result = cursor.fetchone() # fetchone, 如果指令(SQL语句)执行后获得了很多行数据,只拿第一行。 # 没有:None # 有的话以元组的形式出现,表示第一行的数据 # fetchall, 如果指令(SQL语句)执行后获得多行数据,所有的数据都获得到。 # 没有 None # 有的话以元组套元组的形式出现,一个子元组代表一行数据。 # 关闭数据库连接 cursor.close() conn.close() # 判断是否登陆成功 if result: print("登陆成功",result) else: print("登陆失败") def run(): choice = input("1.注册;2.登陆") if choice == '1': register() elif choice == '2': login() else: print('输入错误') if __name__=="__main__": run()
你会发现,在项目开发中,数据库&数据表的操作其实就做一次,最常写的还是对数据行的操作。
关于SQL注入
登陆程序上述程序时,我只要输入用户名为" or 1=1 --,密码任意,就可以登入了。
啊!那是为什么呢?
问题出现在这儿。sql=select * from users where name = "" or 1=1 --" and password="password"
哦!神奇的字符串拼接呀!
明白了吧,所以不要用传统的字符串格式化。用pymysql提供的方法。
cursor.execute('select * from users where name = %s and password=%s',[name, password])
或者
cursor.execute('select * from users where name = %(name)s and password= %(password)s',{'name':name,'password':password})
这样就可以实现,-.execute不但给我们实现转义,还会自动识别其中的引号等非法字符。
哇!太神奇啦!
参考视频
https://www.bilibili.com/video/BV1B34y1R7in?spm_id_from=333.337.search-card.all.click&vd_source=4a12138246864aafc0d59517830e26b6

浙公网安备 33010602011771号