(1) 安装
sudo apt-get install mysql-server
(2) 启动服务
sudo service mysql start
(3) 停止服务
sudo service mysql stop
(4) 重启服务
sudo service mysql restart
(1) 安装
下载地址: https://downloads.mysql.com/archives/community/
选择适合你机器的版本和CPU的型号
使用向导安装
一路next, 直到配置的时候选择Use Legacy Password Encryption
下一步输入root用户的密码, 必须8位
查看是否安装成功, 可以在系统偏好设置里面查看, 有mysql就是安装成功了.
(2) 配置mysql
进入配置文件:vi ~/.bash_profile
加入语句:PATH=$PATH:/usr/local/mysql/bin
使配置的语句生效:source ~/.bash_profile
如果配置成功,那么输入命令:mysql -uroot -p,运行效果如下:
输入安装时设定的root用户密码即可登录成功.
MySQL Workbench下载地址: https://dev.mysql.com/downloads/workbench/
选择适合MySQL版本的Workbench下载安装即可
安装后启动可以通过下面的方式创建数据库
创建表
在数据库表中为了更加准确的存储数据,保证数据的正确有效,可以在创建表的时候,为表添加一些强制性的验证,包括数据字段的类型、约束等.
(3) 查看当前使用的数据库
select database();
(4) 创建数据库
create database 数据库名 charset=utf8;
show tables;
首先需要先使用use命令进入对应的数据库,然后再使用show tables命令查看选中的数据库下的所有表.
如果不想切换到其他数据库去查看表, 也可以这样查看
show tables from 要查看的数据库名;
create table 表名(
字段1 字段类型 约束,
字段2 字段类型 约束,
...
字段N 字段类型 约束,
);
alter table 表名 add 字段名 字段类型 约束;
例如修改students表,添加birthday 字段.
change的方式:
alter table 表名 change 旧字段名 新字段名 新字段类型及约束;
modify的方式:
alter table 表名 modify 旧字段名 新的字段类型及约束;
例如将students表中的birthday字段修改为datetime字段
alter table 表名 drop 字段名;
例如将students的birth字段删除.
(1) 添加外键
alter table goods add foreign key (brand_id) references goods_brands(id);
(2) 删除外键
alter table goods drop foreign KEY brand_id;
(1) 查询所有列
select * from 表名;
(2) 查询指定的字段, 可以使用as为字段定别名
select 字段1,字段2 as xxx,...from 表名;
例:
select name as 名字, age as 年龄 from students;
主键列是自动增长,但是在全列插入时需要占位,通常使用0或者 default 或者 null 来占位,插入成功后以实际数据为准.
(1) 全字段插入: 值的插入顺序与表中的字段的顺序对应
insert into 表名 values(值1,值2,..);
例:
insert into students values(null,'李四', 32);
(2) 部分列插入
值的顺序与给出列的顺序对应.
insert into 表名(字段1,...) values(值1,...);
例:
insert into students(name) values('王五');
(3) 同时插入多条记录
前2种语句一次可以向表中插入一行记录,下面这种方式可以一次性插入多行记录,这样可以减少与数据库的通信.
insert into 表名 values(值1,值2...),(值1,值2...)....;
例:
insert into students values(null,'小红',20),(null,'小明',30),(null,'小王',25);
update 表名 set 字段1=值1,字段2=值2...where 条件
例:
update students set name='小小红' age=18 where id=4;
delete from 表名 where 条件
例:
delete from students where id=4;
mysqldump -uroot -p 数据库名 >要保存的数据库名(带路径).sql
例:
mysqldump -uroot -p mydb > ~/mydb_bck.sql
mysql -uroot -p 新的数据库名字(必须存在) < 已备份的数据库名(带路径).sql
例:
mysql -uroot -p mydb_bck < ~/mydb_bck.sql
注意: 在恢复数据库的时候,新的数据库不存在的时候需要提前创建.
-- 创建数据库
create database python_test_1 charset=utf8;
-- 使用数据库
use python_test_1;
-- students表
create table students(
id int unsigned primary key auto_increment not null,
name varchar(20) default '',
age tinyint unsigned default 0,
height decimal(5,2),
gender enum('男','女','中性','保密') default '保密',
cls_id int unsigned default 0,
is_delete bit default 0
);
-- classes表
create table classes (
id int unsigned auto_increment primary key not null,
name varchar(30) not null
);
-- 向students表中插入数据
insert into students values
(0,'小明',18,180.00,2,1,0),
(0,'小月月',18,180.00,2,2,1),
(0,'彭于晏',29,185.00,1,1,0),
(0,'刘德华',59,175.00,1,2,1),
(0,'黄蓉',38,160.00,2,1,0),
(0,'凤姐',28,150.00,4,2,1),
(0,'王祖贤',18,172.00,2,1,1),
(0,'周杰伦',36,NULL,1,1,0),
(0,'程坤',27,181.00,1,2,0),
(0,'刘亦菲',25,166.00,2,2,0),
(0,'金星',33,162.00,3,3,1),
(0,'静香',12,180.00,2,4,0),
(0,'郭靖',12,170.00,1,4,0),
(0,'周杰',34,176.00,2,5,0);
-- 向classes表中插入数据
insert into classes values (0, "python_01期"), (0, "python_02期");
select * from 表名;
例:
select * from students;
select 列1,列2,... from 表名;
例:
select name from students;
select id as 序号, name as 名字, gender as 性别 from students;
-- 如果是单表查询 可以省略表名
select id, name, gender from students;
-- 表名.字段名
select students.id,students.name,students.gender from students;
-- 可以通过 as 给表起别名
select s.id,s.name,s.gender from students as s;
在select后面列前使用distinct可以消除重复的行
select distinct 列1,... from 表名;
例:
select distinct gender from students;
使用where子句对表中的数据筛选,结果为true的行会出现在结果集中
select * from 表名 where 条件;
例:
select * from students where id=1;
where后面支持多种运算符,进行条件的处理
例1:查询编号大于3的学生
select * from students where id > 3;
例2:查询编号不大于4的学生
select * from students where id <= 4;
例3:查询姓名不是“黄蓉”的学生
select * from students where name != '黄蓉';
例4:查询没被删除的学生
select * from students where is_delete=0;
例5:查询编号大于3的女同学
select * from students where id > 3 and gender=0;
例6:查询编号小于4或没被删除的学生
select * from students where id < 4 or is_delete=0;
例7:查询姓黄的学生
select * from students where name like '黄%';
例8:查询姓黄并且“名”是一个字的学生
select * from students where name like '黄_';
例9:查询姓黄或叫靖的学生
select * from students where name like '黄%' or name like '%靖';
例10:查询编号是1或3或8的学生
select * from students where id in(1,3,8);
例11:查询编号为3至8的学生
select * from students where id between 3 and 8;
例12:查询编号是3至8的男生
select * from students where (id between 3 and 8) and gender=1;
例13:查询没有填写身高的学生
select * from students where height is null;
例14:查询填写了身高的学生
select * from students where height is not null;
例15:查询填写了身高的男生
select * from students where height is not null and gender=1;
语法:
select * from 表名 order by 列1 asc|desc [,列2 asc|desc,...]
说明
例1:查询未删除男生信息,按学号降序
select * from students where gender=1 and is_delete=0 order by id desc;
例2:查询未删除学生信息,按名称升序
select * from students where is_delete=0 order by name;
例3:显示所有的学生信息,先按照年龄从大–>小排序,当年龄相同时 按照身高从高–>矮排序
select * from students order by age desc,height desc;
为了快速得到统计数据,经常会用到如下5个聚合函数
count(*)表示计算总行数,括号中写星与列名,结果是相同的
例1:查询学生总数
select count(*) from students;
max(列)表示求此列的最大值
例2:查询女生的编号最大值
select max(id) from students where gender=2;
min(列)表示求此列的最小值
例3:查询未删除的学生最小编号
select min(id) from students where is_delete=0;
sum(列)表示求此列的和
例4:查询男生的总年龄
select sum(age) from students where gender=1;
-- 平均年龄
select sum(age)/count(*) from students where gender=1;
avg(列)表示求此列的平均值
例5:查询未删除女生的编号平均值
select avg(id) from students where is_delete=0 and gender=2;
不分组的结果如下:
分组后结果:
根据gender字段来分组,gender字段的全部值有4个’男’,‘女’,‘中性’,‘保密’,所以分为了4组 当group by单独使用时,只显示出每组的第一条记录, 所以group by单独使用时的实际意义不大
select gender,group_concat(name) from students group by gender;
通过group_concat()的启发,我们既然可以统计出每个分组的某字段的值的集合,那么我们也可以通过集合函数来对这个值的集合做一些操作
select gender,avg(age) from students group by gender;
select gender,count(*) from students group by gender;
select gender,count(*) from students group by gender having count(*)>2;
with rollup的作用是:在最后新增一行,来记录当前列里所有记录的总和
select gender,count(*) from students group by gender with rollup;
当数据量过大时,在一页中查看数据是一件非常麻烦的事情, 可以通过limit来分页查询结果
语法:
select * from 表名 limit start,count
说明
从start开始,获取count条数据
例1:查询前3行男生信息
select * from students where gender=1 limit 0,3;
当查询结果的列来源于多张表时,需要将多张表连接成一个大的数据集,再选择合适的列返回
mysql支持三种类型的连接查询,分别为:
语法:
select * from 表1 inner或left或right join 表2 on 表1.列 = 表2.列
使用内连接查询班级表与学生表
select * from students
inner join classes
on students.cls_id = classes.id;
使用左连接查询班级表与学生表
此处使用了as为表起别名,目的是编写简单
select * from students as s
left join classes as c
on s.cls_id = c.id;
使用右连接查询班级表与学生表
select * from students as s
right join classes as c
on s.cls_id = c.id;
所谓自关联就是一个表中的一个列引用了该表中另一个列的数据,但这些列的业务逻辑含义是不同的。例如,在一个员工表中,每个员工都有一个经理,该经理也是该表中的员工,这意味着每个员工行的 manager_id 列将引用该表中另一行的 id 列(即 manager_id 是外键,参照该表的 id 列)。但是,这两个列的业务逻辑含义是不同的。id 列表示每个员工的唯一标识符,而 manager_id 列是该员工的直接经理的唯一标识符。
在这种情况下,可以使用自关联来处理这种层次关系的数据结构。例如,在 SELECT 语句中,可以使用自连接来查找某个员工的经理的名字:
SELECT e.name AS employee_name, m.name AS manager_name
FROM employees e JOIN employees m ON e.manager_id = m.id
WHERE e.name = 'John';
在此示例中,“employees e”和“employees m”表示同一个表的两个实例,其中“e.manager_id = m.id”表示使用自连接筛选经理的名字,然后使用“e.name = ‘John’”筛选需要的员工 John 的数据。
在一个 select 语句中,嵌入了另外一个 select 语句, 那么被嵌入的 select 语句称之为子查询语句; 主要查询的对象,第一条 select 语句.
子查询可以分为以下四类:
返回单一值,例如:
SELECT name, salary
FROM employees
WHERE salary = (SELECT MAX(salary) FROM employees);
返回多行数据,但不能独立使用,仅能够在 IN 和 NOT IN 子句中使用,例如:
SELECT name, salary
FROM employees
WHERE id IN (SELECT employee_id FROM departments WHERE department_name='IT');
返回一列或多列的多行数据,可用于 SELECT、WHERE 或 HAVING 子句中,例如:
SELECT name,
(SELECT AVG(salary) FROM employees WHERE department_id = d.id) AS avg_salary
FROM departments d;
返回一个临时表,可在其他查询中被引用,例如:
SELECT d.name, COUNT(e.id) AS employee_count
FROM departments d
LEFT JOIN (SELECT * FROM employees WHERE hire_date > '2019-01-01') e
ON d.id = e.department_id
GROUP BY d.name;
create view 视图名称 as select语句;
show tables;
select * from 视图名称;
drop view 视图名称;
比如需要将students和classes这2张表的内连接查询创建视图
mysql> create view v_students_classes_info as
-> select s.id as student_id,s.name as student_name,s.age,s.height,s.gender, c.id as class_id,c.name as class_name
-> from students as s
-> inner join classes as c
-> on s.cls_id=c.id;
至于为什么要给students和classes的id和name起别名是因为视图中的字段不允许存在同名的字段.
查询创建好的视图v_students_classes_info就比较简单了.
select * from v_students_classes_info;
所谓事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。
例如,银行转帐工作:从一个帐号扣款并使另一个帐号增款,这两个操作要么都执行,要么都不执行。所以,应该把他们看成一个事务。事务是数据库维护数据一致性的单位,在每个事务结束时,都能保持数据一致性
表的引擎类型必须是innodb类型才可以使用事务,这是mysql表的默认引擎, 通过查看表的创建语句可以查看表的引擎, 例如:
show create table goods;
开启事务后执行修改命令,变更会维护到本地缓存中,而不维护到物理表中
begin;
--或者
start transaction;
将缓存中的数据变更维护到物理表中
commit;
放弃缓存中变更的数据
rollback;
注意
在py文件中引入pymysql模块, 如果不存在pymysql需要先下载
from pymysql import *
conn=connect(参数列表)
参数列表:
对象的方法:
cs1 = conn.cursor()
对象的方法:
from pymysql import *
def main():
# 创建Connection连接
conn = connect(host='localhost', port=3306, database='python_test_1', user='root', password='00000000',
charset='utf8')
# 获得Cursor对象
cs1 = conn.cursor()
# 执行insert语句,并返回受影响的行数:添加一条数据
# 增加
count = cs1.execute('insert into goods_cates(name) values("硬盘")')
# 打印受影响的行数
print(count)
count = cs1.execute('insert into goods_cates(name) values("光盘")')
print(count)
# 更新
count = cs1.execute('update goods_cates set name="机械硬盘" where name="硬盘"')
print(count)
# 删除
count = cs1.execute('delete from goods_cates where id=1')
print(count)
# 提交之前的操作,如果之前已经之执行过多次的execute,那么就都进行提交
conn.commit()
# 关闭Cursor对象
cs1.close()
# 关闭Connection对象
conn.close()
if __name__ == '__main__':
main()
from pymysql import *
def main():
# 创建Connection连接
conn = connect(host='localhost', port=3306, database='python_test_1', user='root', password='00000000',
charset='utf8')
# 获得Cursor对象
cs1 = conn.cursor()
# 执行select语句,并返回受影响的行数
count = cs1.execute("select id,name from goods_cates where id >=1")
# 打印受影响的行数
print("查询到%d条数据" % count)
for i in range(count):
# 获取查询结果
result = cs1.fetchone()
# 打印结果
print(result)
# 关闭Cursor对象
cs1.close()
# 关闭Connection对象
conn.close()
if __name__ == '__main__':
main()
打印结果:
查询到5条数据
(2, '光盘')
(3, '机械硬盘')
(4, '光盘')
(5, '机械硬盘')
(6, '光盘')
可见, 结果都是元组类型.
from pymysql import *
def main():
# 创建Connection连接
conn = connect(host='localhost', port=3306, database='python_test_1', user='root', password='00000000',
charset='utf8')
# 获得Cursor对象
cs1 = conn.cursor()
# 执行select语句,并返回受影响的行数
count = cs1.execute("select id,name from goods_cates where id >=1")
# 打印受影响的行数
print("查询到%d条数据" % count)
# for i in range(count):
# # 获取查询结果
# result = cs1.fetchone()
# # 打印结果
# print(result)
result = cs1.fetchall()
print(result)
# 关闭Cursor对象
cs1.close()
# 关闭Connection对象
conn.close()
if __name__ == '__main__':
main()
打印结果:
查询到5条数据
((2, '光盘'), (3, '机械硬盘'), (4, '光盘'), (5, '机械硬盘'), (6, '光盘'))
可见多行数据也是一个元组, 只不过里面的每条数据又是独立的元组.
from pymysql import *
def main():
find_name = input("请输入物品名称:")
# 创建Connection连接
conn = connect(host='localhost', port=3306, database='python_test_1', user='root', password='00000000',
charset='utf8')
# 获得Cursor对象
cs1 = conn.cursor()
# # 非安全的方式
# # 输入 " or 1=1 or " (双引号也要输入)
# sql = 'select * from goods_cates where name="%s"' % find_name
# print("""sql===>%s<====""" % sql)
# # 执行select语句,并返回受影响的行数:查询所有数据
# count = cs1.execute(sql)
# 安全的方式
# 构造参数列表
params = [find_name]
# 执行select语句,并返回受影响的行数:查询所有数据
count = cs1.execute('select * from goods_cates where name=%s', params)
# 注意:
# 如果要是有多个参数,需要进行参数化
# 那么params = [数值1, 数值2....],此时sql语句中有多个%s即可
# 打印受影响的行数
print(count)
# 获取查询的结果
result = cs1.fetchall()
# 打印查询的结果
print(result)
# 关闭Cursor对象
cs1.close()
# 关闭Connection对象
conn.close()
if __name__ == '__main__':
main()
索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。更通俗的说,数据库索引好比是一本书前面的目录,能加快数据库的查询速度
show index from 表名;
create index 索引名称 on 表名(字段名称(长度))
drop index 索引名称 on 表名;
create table test_index(title varchar(10));
from pymysql import *
def main():
# 创建Connection连接
conn = connect(host='localhost', port=3306, database='python_test_1', user='root', password='00000000',
charset='utf8')
# 获得Cursor对象
cs1 = conn.cursor()
# 获得Cursor对象
cursor = conn.cursor()
# 插入10万次数据
for i in range(100000):
cursor.execute(f"insert into test_index values('测试数据-{i}')")
# 提交数据
conn.commit()
# 关闭Cursor对象
cs1.close()
# 关闭Connection对象
conn.close()
if __name__ == '__main__':
main()
set profiling=1;
select * from test_index where title='测试数据-99999';
show profiles;
为表title_index的title列创建索引
create index title_index on test_index(title(10));
注意:
建立太多的索引将会影响更新和插入的速度,因为它需要同样更新每个索引文件。对于一个经常需要更新和插入的表格,就没有必要为一个很少使用的where字句单独建立索引了,对于比较小的表,排序的开销不会很大,也没有必要建立另外的索引。
建立索引会占用磁盘空间
desc user;
查看所有用户
use mysql;
select host,user,authentication_string from user;
-- mysql8.0.11之前的版本
grant 权限列表 on 数据库 to '用户名'@'访问主机' identified by '密码';
--mysql8.0.11之后的版本
create user '用户名'@'访问主机' identified by '密码';
grant select on `数据库名称`.* to '用户名'@'访问主机';
--如果要授予所有权限
grant all privileges on `数据库名称`.* to '用户名'@'访问主机';
例如创建一个laowang的账号,密码为123456,只能通过本地访问, 并且只能对python_test_1数据库中的所有表进行读操作
查看用户具有的权限,可以这样:
show grants for laowang@localhost;
使用root登录,修改mysql数据库的user表
使用password()函数进行密码加密
-- mysql8.0.11之前的版本
update user set authentication_string=password('新密码') where user='用户名';
例:
update user set authentication_string=password('123') where user='laowang';
--mysql8.0.11之后的版本
alter user '用户名'@'主机' IDENTIFIED WITH MYSQL_NATIVE_PASSWORD BY '你要修改的密码';
例:
alter user 'laowang'@'localhost' IDENTIFIED WITH MYSQL_NATIVE_PASSWORD BY '123456';
注意修改完成后需要刷新权限
flush privileges;
drop user '用户名'@'主机';
--例:
drop user 'laowang'@'localhost';
--或者
delete from user where user='用户名';
--例:
delete from user where user='laowang';
-- 操作结束之后需要刷新权限
flush privileges;