mysql数据库(从入门到放弃)

mysql数据库(从入门到放弃)_第1张图片
mysql数据库(从入门到放弃)_第2张图片

本章节主要讲解数据库相关的知识,包括数据库操作,数据表操作,数据库编程等内容。

   为什么要讲数据库 现在有一个场景,公司需要从旗下产品中采集到的10万用户信息进行保存,你要怎么做? 数据是不可能一直运行在程序中的,万一断电或出现其它故障,数据就会丢失。 当今时代,丢了信息就是丢了命。 所以能将数据进行持久化存储,并能快速的查找,成了很重要的需求。 数据库出现就是来解决这个问题的。 数据库也是在程序开发中非常重要的一块内容。

  1. 数据
    数据用来描述事物的特征,行为,记录事物的状态,过程,结果等等。
    比如 一个人的姓名,姓别,年龄,职业,特长等等,这些都是数据。从计算机角度来看,数据体现在记录现实数据信息的组织方式。比如:文本,图片,表格,视频,音频等等。以下我们所说的数据,都是将现实信息转换为计算机角度的表示形式。

  2. 数据库
    当数据越来越多的时候,就面临着一个具大的问题,就是如何去管理这些数据,数据量越大,管理难度就越大。
    比如,你在你的桌面上建立了 N 个文件夹,文件夹又保存了 N 个文件,当你想找一个很久以前创建的文件时,就很难找到,需要花费大量的查找时间。
    这时,就需要一种管理组织方式,分门别类的将数据进行保存,方便使用时的查找。
    将个桌面级的数据管理放大到千万级,亿万级的数据量时,问题更加突出。
    数据库就产生了。数据库就是数据的仓库,数据库按照一定的数据格式,结构来存储数据。方便数据和操作和管理。

  3. 数据库管理数据和其它方式管理数据区别
    内存管理数据
    优点:存取速度快 缺点:断电后数据不能保存
    文件管理数据
    优点:数据可以持久化保存 缺点:读取速度慢,数据组织格式不好控制
    数据库管理数据
    优点:统一的数据组织格式 读取速度快 容量大 缺点:需要专门的管理软件 需要一定的学习成本

  4. 数据库如何管理数据
    实际数据库在管理数据时,也是管理文件的形式来进行管理,只是这些文件具有特定的文件格式。
    如果要操作这些数据文件,需要通过专门的数据库管理软来进行操作。
    数据库管理软件:DBMS Database Management System 数据库管理系统,简称DBMS ,是用来管理数据的专用软件。
    数据库在管理时,通过 DBMS 来操作数据库文件。
    类似于 MS Office Excel 可以操作 .xls 的文件一样

  5. 数据库概念
    数据库 真正用来存储数据的仓库。
    数据库服务管理软件 用来操作数据库中文件的管理软件,也就是 DBMS, 但在使用过程中经常的提及的数据库常指 DBMS
    数据库客户端软件 用户在需要使用数据时,需要向数据库服务管理软件按照一定的格式申请,提交申请的软件软件称为数据库客户端软件

  6. 常用数据库管理软件
    MySQL 中小型数据库,跨平台,开源,免费,应用范围广
    Oracle 大型数据库,跨平台,稳定,安全,收费
    MS SQL Server MS 针对 NT系统开发的数据库,只能运行在 NT 系统上
    Sqlite 微型数据库,一般用在移动端开发

  7. 关系型数据库 RDBMS
    RDBMS Relational Database Management System 关系数据库管理系统
    关系型数据库系统是指以行和列的形式存储数据,将数据组织为相关的行和列的系统
    这种方式便于用户理解,类似于一张表格。
    一组行列关系组成的表构成一个数据文件。
    一组表组成了数据库。
    用户通过查询(Query)来检索数据库中的数据。

  8. 数据库操作语言
    数据库在操作时,需要使用专门的数据库操作规则和语法,这个语法称为 SQL。
    SQL Structured Query Language 结构化查询语言
    SQL 的主要功能是和数据库建立连接,提供增删改查的操作。
    按照ANSI(美国国家标准协会)的规定,SQL被作为关系型数据库管理系统的标准语言。
    SQL语言共分为四大类:
    数据定义语言DDL Data Definition Language
    用于定义数据库中要存储的现实世界实体的语言。
    主要提供数据库,数据表的创建操作。
    数据操作语言DML Data Manipulation Language 用于数据表的操作语言 主要提供数据表中数据的插入,更新,删除操作
    数据查询语言DQL Data Query Language
    主要提供对数据表中数据的查询操作。
    数据控制语言DCL Data Control Language
    主要用来设置或更改数据库用户或角色权限的语句。

  9. 数据库服务器工作流程
    数据库服务在运行时,也和其它服务一样,即然提供了服务,那么就需要有一个服务器存在。
    服务器的作用是用来接受用户的操作请求,并将结果返回给用户。
    提供数据操作服务的称为服务器
    连接数据库服务器发起操作请求的称为客户端
    执行过程:
    客户端发生请求
    服务器接收请求
    服务器将请求发给DBMS查询数据
    DBMS 将查询结果返回给服务器
    服务器将结果返回给客户端
    客户端接收使用数据
    mysql数据库(从入门到放弃)_第3张图片

ubuntu环境下安装管理mysql

服务器安装命令
sudo apt-get install mysql-server
sudo apt-get install mysql-client
sudo apt-get install libmysqlclient-dev
一般情况下只需要安装第一个就可以了,MySQL自的客户端软件并不好用。

MySQL 服务管理
查看服务是否开启
   ps aux | grep mysql
在这里插入图片描述
MySQL 服务管理命令
启动服务
   sudo service mysql start
停止服务
   sudo service mysql stop
重新启动服务
   sudo service mysql restart
查看服务状态
   sudo service mysql status

  1. MySQL 客户端安装
    在数据库操作时,需要通过客户端向服务器发送 SQL 语句。
    MySQL 可以使用的客户端很多,比如 MySQL 自带的客户端,使用系统命令行做为客户端,使用我们开发的程序做为客户端等等,以及 Navicat,PhpAdmin 等图形化的客户端等。
    在这里,我们使用 Navicat 图形化客户端工具来进行操作。
    安装过程
    下载 官方下载地址: https://www.navicat.com/en/download/navicat-for-mysql 在下载时,需要填写一些信息。(官网打开较慢,可以百度一些二次分享的下载地址)
    已经下好源码版本。(资料分享中)
    解压
    mysql数据库(从入门到放弃)_第4张图片
    mysql数据库(从入门到放弃)_第5张图片
    mysql数据库(从入门到放弃)_第6张图片
    小提示 因为该软件是收费软件,只能是试用。 如果在启动时提示试用期结束,或者启用出现问题。可以如图解决
    mysql数据库(从入门到放弃)_第7张图片
    mysql数据库(从入门到放弃)_第8张图片
    mysql数据库(从入门到放弃)_第9张图片
  2. 连接数据库
    在连接数据库时,使用 mysql 命令连接数据库
    使用命令行客户端连接
    mysql数据库(从入门到放弃)_第10张图片
  3. MySQL 默认数据库介绍(了解)
    Information_schema
    保存着关于MySQL服务器所维护的所有其他数据库的信息(元数据)。
    如数据库名,数据库的表,表栏的数据类型与访问权限等。
    performance_schema
    保存数据库的性能优化信息。
    sys
    因为上面的两个数据库中的数据经常被使用,sys整合了两个数据库中的信息,方便操作。
    mysql
    保存用户信息。
    注意:数据库安装成功后,会自动创建上面的四个数据库,这四个库不需要我们操作,一般是数据库管理员来操作。 程序开发中基本用不到里面的内容,但是也不能删除。放着别动 ,只做了解即可。

数据库操作

1.数据库操作介绍
在数据库操作中,基本操作都是围绕增删改查来操作。简称CRUD

  • C Create 创建
  • R Read/Retrieve 查询
  • U Update 修改
  • D Delete 删除
    在数操作数据库时,所有的数据库语句都要以分号结束;数据库操作不区分大小写

创建数据库
create database 数据库名
create database testdb;

create database 数据库名
create database testdb2 character set utf8;

显示数据库创建信息 show create database 数据库名
show create database testdb;
mysql数据库(从入门到放弃)_第11张图片
修改数据库编码 alter database 数据库名 character set utf8
alter database testdb charset=utf8;

显示所有数据库
show databases;

切换、使用数据库 use 数据库名
use testdb

显示当前数据库 :select database();

删除数据库 drop database 数据库名
drop database testdb2;
不要随便删库,删库只能跑路,追杀你到天涯海角

数据表操作

  1. 数据表操作介绍
    和数据库操作一样,在数据表在操作中,也是是围绕增删改查来操作。
    查看表 作用:查看所选数据库中所有的表 语法: show tables;

创建表:create table stu(sid int,sname char(20),sage int);
显示创建表:show craete table stu;
mysql数据库(从入门到放弃)_第12张图片
mysql数据库(从入门到放弃)_第13张图片
增加字段 作用:为已存在的表添加一个新字段 语法:alter table 表名 add 列名 数据类型
alter table stu add gender char(4);
mysql数据库(从入门到放弃)_第14张图片
修改字段的数据类型 作用:修改表中现有字段的类型 语法:alter table 表名 modify 字段名 数据类型
alter table stu modify sname varchar(20);

修改列的数据类型并且改名 作用:修改表中现有字段的字段名和类型 语法:alter table 表名 change 原字段名 新字段名 数据类型
alter table stu change sid snumber smallint;
mysql数据库(从入门到放弃)_第15张图片
删除字段 作用:在表中删除一个已存在的字段 语法:alter table 表名 drop 列名
alter table stu drop gender;
mysql数据库(从入门到放弃)_第16张图片

字段类型

  1. MySQL 常用字段类型
    数据表是由若干个字段组成的,每个字段表示不同类型的数据。
    所以在创建表的时候,需要为每个字段指定相应的数据类型。
    整数类型
    mysql数据库(从入门到放弃)_第17张图片
    小数类型
    mysql数据库(从入门到放弃)_第18张图片
    字符串类型
    mysql数据库(从入门到放弃)_第19张图片
    枚举类型 enum(枚举值1,枚举值2,…)
    enum(‘男’,‘女’)
    时间类型
    在这里插入图片描述

数据操作

  1. 查询数据
    作用:查询数据就是通过客户端通过 DBMS 从数据库中取出满足条件的数据。
    语法:select 字段名列表 from 表名;
    select * from stu;

  2. 插入数据
    作用:向数据库中插入数据
    语法:insert into 表名 [(字段名列表, …)] values(值列表, …),…
    插入所有字段数据
    可以不指定插入的字段,直接写入插入的数据
    insert into tStudent values(1,‘tom’,20)

  3. 插入指定字段
    可以插入指定的字段,指定字段顺序和列中顺序可以不同,值顺序要和指定的列顺序相同。
    insert into stu(sage,sname) values(20,‘jack’);    字段和值要一一对应
    select * from stu;      查看插入效果

  4. 插入多条数据
    insert into stu values(2,‘rose’,20),(3,‘tony’,22);

  5. 修改数据
    作用: 可以根据指定的条件,修改更新满足条件的数据
    语法: update 表名 set 字段=值 [条件]
    更新所有的数据
    update stu set sAge=25;

  6. 更新满足条件的数据
    update stu set sname=‘alice’ where name=‘tony’;
    select * from stu;      查看更新效果

  7. 删除数据
    作用:将数据从数据表中删除
    语法1:truncate 表名
    语法2:delete from 表名 [条件]
    删除全部数据 truncate
    truncate stu;
    不需要加条件,也不能加条件,删除全部数据,重置自动编号到默认值,没有事务,速度快。

    delete from stu;
    相当于 truncate stu,但是delete操作有事务操作,所以速度慢,而且不会重置自动编号。

  1. 删除满足条件的数据
    delete from stu where snumber = 1;
    mysql数据库(从入门到放弃)_第20张图片

Mysql 删除数据表的三种方式详解

用法:
1、当你不再需要该表时, 用 drop;
2、当你仍要保留该表,但要删除所有记录时, 用 truncate;
3、当你要删除部分记录或者有可能会后悔的话, 用 delete。
删除程度可从强到弱如下排列:

  1. drop table tb;
    drop 是直接将表格删除,无法找回。例如删除 user 表:
    drop table user;

  2. truncate (table) tb;
    truncate 是删除表中所有数据,但不能与where一起使用;
    TRUNCATE TABLE user;

  3. delete from tb (where);
    delete 也是删除表中数据,但可以与where连用,删除特定行;
    – 删除表中所有数据
    delete from user;
    – 删除指定行
    delete from user where username =‘Tom’;
    truncate 和 delete 的区别:

  4. 事物
    truncate删除后不记录mysql日志,因此不可以rollback,更不可以恢复数据;而 delete 是可以 rollback ;
    原因:truncate 相当于保留原mysql表的结果,重新创建了这个表,所有的状态都相当于新的,而delete的效果相当于一行行删除,所以可以rollback;

  5. 效果
    效率上 truncate 比 delete快,而且 truncate 删除后将重建索引(新插入数据后id从0开始记起),而 delete不会删除索引 (新插入的数据将在删除数据的索引后继续增加)

  6. truncate 不会触发任何 DELETE触发器;

  7. 返回值
    delete 操作后返回删除的记录数,而 truncate 返回的是0或者-1(成功则返回0,失败返回-1);
    delete 与 delete from 区别:
    如果只针对一张表进行删除,则效果一样;如果需要联合其他表,则需要使用from :
    delete tb1 from tb1 m where id in (select id from tb2)
    看看手册中关于 OPTIMIZE 的描述:

  8. OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] …
    如果您已经删除了表的一大部分,或者如果您已经对含有可变长度行的表(含有VARCHAR, BLOB或TEXT列的表)进行了很多更改,则应使用

  9. OPTIMIZE TABLE。被删除的记录被保持在链接清单中,后续的INSERT操作会重新使用旧的记录位置。您可以使用OPTIMIZE TABLE来重新
    利用未使用的空间,并整理数据文件的碎片。
    在多数的设置中,您根本不需要运行OPTIMIZE TABLE。即使您对可变长度的行进行了大量的更新,您也不需要经常运行,每周一次或每月一次
    即可,只对特定的表运行。
    OPTIMIZE TABLE只对MyISAM, BDB和InnoDB表起作用。
    注意,在OPTIMIZE TABLE运行过程中,MySQL会锁定表。

案例:近期整理数据库堆积了三年多的数据,将19年之前的数据(大概十几万条,也不是很多居然……)删除,只保留今年的数据,也仅仅释放出了500MB左右。

第一步:先查看了一下占用磁盘空间较多的几张表
SELECT TABLE_NAME, CONCAT(TRUNCATE(data_length/1024/1024,2),’ MB’) AS data_size,
CONCAT(TRUNCATE(index_length/1024/1024,2),’ MB’) AS index_size
FROM information_schema.tables WHERE TABLE_SCHEMA = ‘database_name’
GROUP BY TABLE_NAME ORDER BY data_length DESC
(PS:以后要仔细研究,详细说明,不马虎了,打脸打脸打脸)

mysql在安装成功后,会有四个系统自带的database(可以通过mysql命令>show databases;查看):
| information_schema |
| mysql |
| performance_schema |
| sys |
而查看数据库占用空间(包括数据data和索引index)则是查看information_schema。而关于这四张表的解释,可以参考
https://blog.csdn.net/dj673344908/article/details/80482844
第二步:针对占用空间大的表做清理删除
由于直接操作服务器,非常卡,所以我都是拷在本地,在本地操作,就是试着玩儿的……
Linux服务器备份MySQL数据库:
mysqldump -u userName -p dataBaseName > fileName.sql
将备份的sql文件下载到本地,Windows下MySQL数据库恢复:
mysql -u 用户名 -p 数据库名 < 保存文件.sql
如果上述命令不成功,换一个,好吧,我用的下面的(mysql命令不是一次性执行的,分开执行!):
mysql>
show databases;
create database 数据库名;
use 数据库名;
source 保存文件.sql;
再次显示mysql>即成功
言归正传
之前关于删除数据库数据首先想到是delete,但是delete执行完成后不会释放磁盘空间。(还有一个truncate table语句,但是这个是删除整张表的数据,由于整个操作不会记录日志,因为时间要比delete删除整张表快。且delete可以添加删除条件,truncate不支持)。
因此通过drop表的方式删除。一大批命令呈上来:
create table temp_table like drop_table;
insert into temp_table select * from drop_table where time >= ‘2019-01-01 00:00:00’;
drop table drop_table;
alter table temp_table rename to drop_table;

首先创建一个新表(temp_table),格式和要删除的表(drop_table)一样
然后将要保留的数据放在临时表(temp_table)中
将旧表删掉

将临时表重命名为旧表名称
表中可能会有外键,删除的时候会ERROR提示,以下:
SELECT @@FOREIGN_KEY_CHECKS;
SET FOREIGN_KEY_CHECKS=0;
SET FOREIGN_KEY_CHECKS=1;
第一行命令查看外键约束是否打开,1是打开,0是关闭,删除的时候如果是1会报错,通过第二行命令修改为0,删除成功之后再改回1。
第三步:执行完成
执行完成后如果想查看某个表空间占用是否变小:
select concat(round(sum(data_length/1024/1024),2),‘MB’) as data_length_MB, concat(round(sum(index_length/1024/1024),2),‘MB’) as index_length_MB from information_schema.tables where table_schema=‘database_name’ AND table_name=‘drop_table’;
查看当前占用空间,可与之前记录下来的做比较。

数据完整性和约束

  1. 数据完整性
    存储在数据库中的所有数据值均正确的状态。
    如果数据库中存储有不正确的数据值,则该数据库称为已丧失数据完整性。
    数据完整性包括:
    域完整性
    实体完整性
    参考完整性
    数据库通过约束来保证数据完整性。
    它通过对表的行或列的数据做出限制,来确保表的数据的准确性,完整性、唯一性,可靠性、联动性。

  2. 数据常见问题
    2.1 数据冗余-
    mysql数据库(从入门到放弃)_第21张图片
    2.2 失去数据完整性
    mysql数据库(从入门到放弃)_第22张图片
    2.3 数据缺少唯一标识
    mysql数据库(从入门到放弃)_第23张图片
    2.3 失去实体完整性
    mysql数据库(从入门到放弃)_第24张图片
    2.4 失去引用完整性
    mysql数据库(从入门到放弃)_第25张图片

  3. 数据库常用约束
    主键约束 作用:让数据具有唯一标识 语法:primary key
    create table tpk(id int primary key , name char(10));
    字段被设置了主键约束,同时也具有了唯一性约束和非空约束。 在字段中插入重复数据时,或不给数据时会报错。

  4. 自动增长 作用:让数字值自动累加 语法:auto_increment 自动增长设置在数值型字段上,需要配合主键约束一起使用。 如果字段没有设置主键约束,是不允许设置自动增长的。
    create table tai(id int auto_increment primary key,name varchar(10));
    在这里插入图片描述

  5. 唯一性约束 作用:保证数据的准确性,不会出现重复数据 语法:unique
    create table tuni(id int unique,name char(10);
    一个表中可以给多个字段设置唯一性,如果有需要的话。
    mysql数据库(从入门到放弃)_第26张图片

  6. 非空约束 作用:不允许字段为空,添加数据时必须给值 语法:not null
    create table tnn(id int,name char(10) not null);
    mysql数据库(从入门到放弃)_第27张图片

  7. 默认约束 作用:在添加数据时,如果没有给定有默认约束字段的数据,该字段使用默认值填充 语法:default
    create table tdt(id int,name char(10) default ‘NoName’);
    mysql数据库(从入门到放弃)_第28张图片

  8. 外键约束 作用:让两表之间产生联动关系 语法:foreign key(字段名) references 表名(字段名)
    – 表1
    create table fClass(id int primary key,name char(10));
    – 表2
    create table fStudent(id int primary key auto_increment, name char(10), cid int, foreign key(cid) references fClass(id));
    mysql数据库(从入门到放弃)_第29张图片
    设置外键约束字段所关联的字段,必须是主键约束字段。
    想要删除有设置外键的表,必须先删除外键所关联的表。

    drop table fStudent;
    drop table fClass;
    在这里插入图片描述

导入导出数据库

  1. 数据库导入导出
    作用:使用数据库和导入导出功能,可以对数据库进行备份,迁移等操作。
  2. 导出数据库
    导出数据库使用 mysqldump 命令完成
    语法: mysqldump –uroot –p(注意不要输入密码) 要导出的数据库名 要导出的数据表 … > 目标文件.sql
    导出整个数据库
    mysqldump -uroot -p School > school_bak.sql
    在这里插入图片描述
    导出库当中的指定表
    mysqldump -uroot -p School tpk > tpk.sql
    mysqldump -uroot -p School tpk tfk > tpktfk.sql
    在这里插入图片描述

导入数据库

导入数据库使用 mysql 命令完成
语法:mysql -uroot -p 数据库名 < 要导入的文件.sql
导入数据库前需要先创建一个空数据库
mysql -uroot -p sch < school_bak.sql
mysql数据库(从入门到放弃)_第30张图片

数据查询(重点)

单表查询

  1. 准备工作
    在查询之前,首先要有数据表和相应的数据。
    导入之前需要先创建一个数据库
    使用新创建的数据库
    使用 source 文件地址 导入数据
    mysql数据库(从入门到放弃)_第31张图片

  2. 查询指定字段
    查询数据库使用 select 命令。 这个命令相对比较复杂。可变化样式较多,这里分功能依次讲解。
    查询数据表中所有数据 语法:select * from 表名
    select * from t_student;

  3. 查询指定字段的显示 语法:select 字段1,字段2,… from 表名
    select c_id,c_name,c_address from t_student;
    在查询时,默认结果显示的字段和表中字段名相同,可以通过别名来修改显示的样式 语法:select 字段1 as 别名,字段2 别名,… from 表名
    select c_id as 学号 ,c_name as 姓名 ,c_address 地址 from t_student;
    在给字段起别名时,可以使用 as ,也可以直接在字段后跟别名,省略 as 。

  4. 消除重复数据
    在查询数据时,查询结果可能会有很多重复的数据,如果不想重复,可以使用 distinct 来实现去重。 语法:select distinct 字段名 from 表名
    select distinct c_address from t_student;
    注意:distinct 在去重时,会比较所有的指定字段,只有完全相同时才认为是重复的。

  5. 条件查询 where 子句
    查询数据时,需要根据不同的需求设置条件,通过where 子句来设置查询条件
    语法: select 字段,… from 表名 [where 字段 运算符 值];
    select * from t_student where c_gender=‘男’;

  6. 运算符
    where 条件中可以使用的运算符。
    比较运算符

    等于: =
    大于: >
    大于等于: >=
    小于: <
    小于等于: <=
    不等于: != 或 <>
    如:select * from t_student where c_age < 20;

  7. 逻辑运算符
    and
    or
    not
    如:select * from t_student where c_age < 20 and c_gender = ‘女’;

  8. 模糊查询
    like
    % 表示任意多个任意字符
    _ 表示一个任意字符
    select * from t_student where c_name like ‘孙’;
    select * from t_student where c_name like ‘孙%’;
    select * from t_student where c_name like ‘孙_’;

  9. 范围查询
    in 表示在一个非连续的范围内 , 可以使用 or 实现
    select * from t_students where id in(1,3,8);
    mysql数据库(从入门到放弃)_第32张图片
    between … and … 表示在一个连续的范围内,可以使用 and 实现
    mysql数据库(从入门到放弃)_第33张图片

  10. 空判断
    在数据库中,允许在数据添加是没有数据,使用空值来表示。 空值不等于0,也不等于‘’,需要使用特殊的判断方式
    判断空值
    语法:is null
    select * from t_student where c_age is null;
    判断非空值 语法:is not null

  11. 查询结果排序
    排序是一个在查询数据时非常重要的操作。比如买东西时,想按一定的条件进行有序显示。就需要使用排序
    asc(默认) 升序 / desc 降序 语法:select * from 表名 order by 列1 asc|desc [,列2 asc|desc,…]
    单字段排序
    select * from t_student order by c_age;
    select * from t_student order by c_age asc;
    默认使用就是升序排序,可以不指定 asc ,效果相同。

  12. 多字段排序 可以对多个字段进行排序,只需将字段的排序方式依次写在 order by 后面即可,字段间使用逗号分隔
    select * from t_student order by c_age desc,c_id asc;
    mysql数据库(从入门到放弃)_第34张图片

  13. 分页查询
    查询数据库时,由于数据较多,在显示过程中不可能将数据全部显示。 可以使用分页查询,只显示指定的一部分数据 语法:select from 表名 limit start=0,count *说明
    从start开始,获取count条数据
    start默认值为0
    需要获取数据的前n条的时候可以直接写 limit n
    select * from t_student limit 3;
    select * from t_student limit 2,3;
    mysql数据库(从入门到放弃)_第35张图片
    查询第 N 页 M 条数据,可以通过公式算出:(N - 1) * M

聚合函数

在MySQL中提供了一些定义好的函数,利用这些函数提供对数据的统计功能。 常用的聚合函数如图:
mysql数据库(从入门到放弃)_第36张图片

  1. sum 求和函数 对指定的字段求和
    select sum(c_age) from t_student;
    mysql数据库(从入门到放弃)_第37张图片
  2. avg 求平均值函数 对指定字段求平均值
    select avg(c_age) from t_student;
    mysql数据库(从入门到放弃)_第38张图片
  3. max 求最大值函数
    select max(c_age) from t_student where c_gender = ‘男’;
    mysql数据库(从入门到放弃)_第39张图片
  4. min 求最小值函数
    select min(c_age) from t_student where c_gender = ‘女’;
    mysql数据库(从入门到放弃)_第40张图片
  5. count 统计记录总数
    select count(**) from t_student;
    select count(*) from t_student where c_gender = ‘女’;
    mysql数据库(从入门到放弃)_第41张图片
  6. 分组
    分组就是将相同数据放到一起进行处理。 单纯的分组是没有意义的,需要配合聚合函数一起使用。
    语法: select 分组的字段名,聚合函数… from 表名 group by 分组字段名 having 分组后的条件
    注意:在执行 group by 分组时,select 后只能有被分组的字段,不允许有其它字段,除非这些字段在聚合函数中
    单字段分组
    select c_gender from t_student group by c_gender;
    mysql数据库(从入门到放弃)_第42张图片
  7. 多字段分组(了解)
    可以对多个字段进行分组,作用同上,需要注意的是多字段时,只有对应字段完全相同,才能分为同一组
    select c_gender,c_address from t_student group by c_gender,c_address;
    mysql数据库(从入门到放弃)_第43张图片
    group_concat()
    作用:根据分组结果,使用group_concat()来获取分组中指定字段的集合
    语法:group_concat(字段名)
    select c_gender,group_concat(c_name) from t_student group by c_gender;
    在这里插入图片描述
  8. 分组和聚和函数使用
    单纯的使用分组并没有实际意义,需要使用聚合函数对数据进行处理。
    select c_gender,max(c_age),min(c_age),sum(c_age),avg(c_age),count(*) from t_student group by c_gender;
    select c_gender,max(c_age),min(c_age),sum(c_age),avg(c_age),count(c_age) from t_student group by c_gender;
    mysql数据库(从入门到放弃)_第44张图片
  9. having条件子句
    having 作用和 where 类似,用来去分组数据进行筛选 where 是对 form 表 中取数据时进行筛选 having 是对 group by 分组后的数据进行筛选 ,因为在执行顺序上,在执行 where 时,分组还没有执行,得先根据 where 的条件取出数据,才能去取出的数据进行分组。
    select c_gender,group_concat(c_name) from t_student group by c_gender having c_gender = ‘女’;
    select c_gender,group_concat(c_name) from t_student where c_age > 50 group by c_gender having c_gender = ‘女’;
    mysql数据库(从入门到放弃)_第45张图片

多表查询

  1. 能够对多张数据表进行查询操作
       在数据库操作中,数据往往不是存在一张表中的,同一个项目中,根据设计范式,数据可能分散在不同的多张表中,这时查询数据时,就需要多表查询。

  2. 普通多表查询(无意义)
    作用:直接将表放在from后面,进行读取。 语法:select 表名.字段 … from 表名1,表名2…
    select * from t_student,t_class;
    mysql数据库(从入门到放弃)_第46张图片
    这种查询方式没有任何意义。
    在查询时,数据库会将表1中的数据逐条和表2中的所有数据连接,组成一条新记录。
    查询的结果为 M * N 条,实际就是笛卡尔积结果。

  3. 多表查询连接条件
    在多表个表进行查询时,表与表之间应该是有有关系的,一般会以外键的形式来建立表间的关系。 查询时按照条件建立记录的匹配规则。 比如学生表中保存了学生的信息和所在班级的ID,班级表中保存了班级的信息。 在查询学生的班级信息时,可以通过学生表中的班级ID和班级表中的ID匹配进行查询
    select t_student.c_name,t_class.c_name from t_student,t_class where t_student.c_class_id = t_class.c_id;
    mysql数据库(从入门到放弃)_第47张图片

  4. 表别名
    在多表操作时,由于表的名字比较长,在写SQL语句时非常不方便。可以在查询 时,给表起个别名,代替表名来操作
    语法:select 别名.字段名… from 表1 as 表1别名,表2 表2别名… [条件]
    select ts.c_name as ‘姓名’ , tc.c_name ‘班级名’ from t_student as ts,t_class tc where ts.c_class_id = tc.c_id;
    mysql数据库(从入门到放弃)_第48张图片

  5. 内连接查询
    作用:查询的结果为两个表匹配到的数据 语法:select * from 表1 inner join 表2 on 表1.列 运算符 表2.列
    mysql数据库(从入门到放弃)_第49张图片
    数据库默认的连接方式就是内连接查询, inner join 可以不显示的写出来。 这种连接方式会以笛卡尔积的形式进行连接。 所以在连接时,必须要给定连接条件。 连接条件使用 on 进行指定。尽量不要使用 where,where在其它连接方式时,指定的连接条件无效。
    select ts.c_name, tc.c_name from t_student as ts inner join t_class tc on ts.c_class_id = tc.c_id;
    mysql数据库(从入门到放弃)_第50张图片

  6. 左连接查询
    作用:查询的结果为根据左表中的数据进行连接,如果右表中没有满足条件的记录,则连接空值。
    语法:select * from 表1 left join 表2 on 表1.列 运算符 表2.列
    在这里插入图片描述
    select ts.c_name, tc.c_name from t_student as ts left join t_class tc on ts.c_class_id = tc.c_id;
    mysql数据库(从入门到放弃)_第51张图片

  7. 右连接查询(实际工作中用的少)
    作用:查询的结果为根据右表中的数据进行连接,如果左表中没有满足条件的记录,则连接空值。
    语法:select * from 表1 right join 表2 on 表1.列 运算符 表2.列
    mysql数据库(从入门到放弃)_第52张图片
    select ts.c_name, tc.c_name from t_student as ts right join t_class tc on ts.c_class_id = tc.c_id;
    mysql数据库(从入门到放弃)_第53张图片
    在实际工作中,右连接使用的非常少,因为左连接完全可以替代右连接,在连接过程中,只需要调整表的顺序即可。

  8. 子查询
    作用:在一个 select 语句中,嵌入了另外一个 select 语句, 那么被嵌入的 select 语句称之为子查询语句
    语法:select * from 表1 where 条件 运算符 (select 查询)
    外部那个select语句则称为主查询
    主查询和子查询的关系

    • 子查询是嵌入到主查询中
    • 子查询是辅助主查询的,要么充当条件,要么充当数据源
      子查询是可以独立存在的语句,是一条完整的 select 语句标量子查询 作用:子查询返回的结果是一个数据(一行一列) 语法:主查询 where 条件 比较运算符 (列子查询)
      示例:查询班级中年龄大于平均年龄的学生信息
    • 查询班级学生平均年龄
    • 查询大于平均年龄的学生
      mysql数据库(从入门到放弃)_第54张图片
  9. 列级子查询 作用:子查询返回的结果是一列(一列多行) 语法:主查询 where 条件 in (列子查询) 示例:查询所有学生所在班级的班级名称
    找出学生表中所有的班级 id
    找出班级表中对应的名字
    mysql数据库(从入门到放弃)_第55张图片

  10. 行级子查询 作用:子查询返回的结果是一行(一行多列) 语法:主查询 where (字段1,2,…) = (行子查询) 示例:查找班级年龄最大,所在班号最小的的学生
    找出最大年龄和最小班号
    找出年龄和班号满足条件的学生
    select * from t_student where(c_age,c_class_id) = (select max(c_age),min(c_class_id) from t_student);
    在这里插入图片描述

  11. 自连接查询
    作用:在查询数据时,只有一张表,查询时使用自己连接自己。 语法:select * from 表 as 表别名1 inner join 表 表别名2 on 表别名1.列 运算符 表别名2.列 where 条件
    为什么需要自连接?
    现要设计表结构来存储全国所有的省份和全国所有的市
    设计省信息的表结构provinces
    id 省的编号
    ptitle 省名称
    设计市信息的表结构citys
    id 市编号
    ctitle 市名称
    proid 市所属的省的编号
    citys表的proid表示城市所属的省,对应着provinces表的id值
    如果需要查询一个省 比如广东省对应的所有的时的信息 ,我们可以使用两个表连接查询。

问题: 能不能将两个表合成一张表呢?
观察两张表发现,citys表比provinces表多一个列proid,其它列的类型都是一样的。存储的都是地区信息,而且每种信息的数据量有限,没必要增加一个新表,或者将来还要存储区、乡镇信息,都增加新表的开销太大。

那么将可以将两张表合为一张表来存储数据。

定义表areas,结构如下
id
atitle
pid

关于这个表的说明:
因为省没有所属的省份,所以可以填写为null
城市所属的省份pid,填写省所对应的编号id
这就是自关联,表中的某一列,关联了这个表中的另外一列,但是它们的业务逻辑含义是不一样的,城市信息的pid引用的是省信息的id
在这个表中,结构不变,可以添加区县、乡镇街道、村社区等信息
思考: 如果还是要查询广东省对应的所有的市的信息,咱们应该怎么做呢?

areas表和自身进行连接这种形式的连接 就成为自连接。

准备数据
创建areas表的语句如下: 注意,表所在的数据库字符集必须是utf8的,如果不是会导入数据出错
create table areas(
aid int primary key,
atitle varchar(20),
pid int
);

从sql文件中导入数据
source /home/python/Desktop/areas.sql;

示例1:查询一共有多少个省
select count() from areas where pid is null; -----(这里pid表示的是城市,除去城市,就是省份)
mysql数据库(从入门到放弃)_第56张图片
示例2: 查询省的名称为“山西省”的所有城市
select city.
from areas as city inner join areas as province on city.pid=province.aid where province.atitle=‘山西省’;
mysql数据库(从入门到放弃)_第57张图片
示例3:查询市的名称为“广州市”的所有区县
select dis.* from areas as dis inner join areas as city on city.aid=dis.pid where city.atitle=‘广州市’;
mysql数据库(从入门到放弃)_第58张图片

Python数据库编程

  1. 导语
    数据库编程就是针对数据库的操作,通过编写程序的方式,让程序做为数据库的客户端进行数据库操作。
    从前面我们知道数据库概念包含 数据库文件、服务器和数据库客户端 客户端我们之前已经用过的有navicat/mysql-client等程序。
    比如,现在从网络上爬取了100万条数据,需要将这些数据保存到数据库中,这该如何操作?
    手动插入?这简直是不可完成的工作,而现实是生产环境中的数据只会多不会少。
    可是,如果我们有一个功能能够插入一行数据,借助程序强大的特点-重复,就可以轻而易举的就将10w行数据收入麾下。
    这种通过使用程序代码的方式去连接数据库服务器,通过和服务器进行交互完成对数据库的增删改查的方式,就称为数据库编程。而此刻学习的 pymysql 就是一种客户端。
  2. Python 操作 MySQL 步骤
    mysql数据库(从入门到放弃)_第59张图片
    从图中可以看出,在 Python 中操作数据库,要经过五个步骤,分别是连接数据库,获取游标,数据库操作,关闭游标,关闭数据库连接。

这个过程和实际仓库操作相同,比如现在要去一个实际的仓库。
mysql数据库(从入门到放弃)_第60张图片
3. pymysql 常用方法
在 Pyhton 中,使用 Pymysql 模块来对数据库进行编程。
导入模块
from pymysql import connect
Connection 对象
创建连接对象 conn=connect(参数列表)
参数host:连接的mysql主机,如果本机是’localhost’
参数port:连接的mysql主机的端口,默认是3306
参数database:数据库的名称
参数user:连接的用户名
参数password:连接的密码
参数charset:通信采用的编码方式,推荐使用utf8
关闭连接 conn.close()
提交数据 conn.commit()
撤销数据 conn.rollback()
通过连接获取游标 cur = conn.cursor()返回Cursor对象,用于执行sql语句并获得结果
Cursor游标对象
获取Cursor对象 cur = conn.cursor()
使用游标执行SQL语句 cur.execute(operation , [parameters]) 执行SQL语句,返回受影响的行数,主要用于执行insert、update、delete语句
获取结果集中的一条 cur.fetchone() 返回一个元组 如 (1,‘妲己’,18)
获取结果集中的一条 cur.fetchmany(2) 返回一个元组 如 ((1,‘妲己’,18),2,‘公孙离’,20))
获取结果集中的所有 cur.fetchall() 返回结果集的所有行,一行构成一个元组,再将这些元组装入一个元组返回. 如((1,‘妲己’,18),(2,‘公孙离’,20),(3,‘姜子牙’,28))
关闭游标 cur.close()

Python数据库编程

知道如何使用 pymysql 对数据库进行CRUD

  1. 准备数据
-- 创建数据库
create database python_db charset=utf8;

-- 使用数据库
use python_db;

-- 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 int 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期");
  1. 查询数据
# 导入模块
from pymysql import connect
# 连接数据库
conn = connect(host='localhost', port=3306, database='python_db', user='root', password='123123',charset='utf8')
# 获取游标
cur = conn.cursor()
# 以字符串形式书写SQL语句,因为SQL语句中也会出现字符串,所以建议使用 ```引号形式将SQL诗句引起来
sql_str = '''select * from students;'''
# 执行SQL语句
row_count = cur.execute(sql_str)
# 显示执行 SQL 语句影响的行数
print(row_count)
# 获取一条记录
row_one = cur.fetchone()
# 显示获取的记录
print(row_one)
# 获取多条记录
row_many = cur.fetchmany(4)
# 遍历输出所有的结果
for t in  row_many:
    print(t)
# 获取所有的数据
row_all = cur.fetchall()
# 遍历输出所有的结果
for t in  row_all:
    print(t)
# 关闭游标
cur.close()
# 关闭数据库
conn.close()

注意:因为在获取数据时,游标是移动的,所以前面取过的数据,后面不会再取了。

  1. 增删改
# 导入模块
from pymysql import connect
# 连接数据库
conn = connect(host='localhost', port=3306, database='python_db', user='root', password='123123',charset='utf8')
# 获取游标
cur = conn.cursor()
# 以字符串形式书写SQL语句
# sql_str = '''insert into students values(0,'新来的',20,180,'男',1,1)'''
# sql_str = '''update students set name = '王钢蛋' where name = '新来的'; '''
sql_str = '''delete from students where name='王钢蛋'; '''
# 执行SQL语句
row_count = cur.execute(sql_str)
# 在执行增删改操作时,需要向数据库提交操作,否则操作不成功
conn.commit()
# 关闭游标
cur.close()
# 关闭数据库
conn.close()
  1. 回滚(取消操作)
# 导入模块
from pymysql import connect
# 连接数据库
conn = connect(host='localhost', port=3306, database='python_db', user='root', password='123123',charset='utf8')
# conn.autocommit(True)
# 获取游标
cur = conn.cursor()
# 以字符串形式书写SQL语句
sql_str = '''insert into students values(0,'新来的',20,180,'男',1,1)'''
#插入10条数据
for i in range(10):
    # 执行SQL语句
    row_count = cur.execute(sql_str)
# 在执行增删改操作时,如果不想提交前面的修改操作,可以使用 rollback 回滚取消操作
conn.rollback()
# 关闭游标
cur.close()
# 关闭数据库
conn.close()

SQL注入

学习目标
知道什么是SQL注入
知道如何避免SQL注入

  1. SQL注入
    什么是SQL注入?

产生原因: 后台对用户提交的带有恶意的数据和 SQL 进行字符串方式的拼接,得到了脱离原意的 SQL 语句,从而影响了 SQL 语句的语义,最终产生数据泄露的现象
如何防止: SQL 语句的参数化, 将 SQL 语句的所有数据参数存在一个列表中传递给 execute 函数的第二个参数

注意:
此处不同于python的字符串格式化,必须全部使用%s占位

# 导入模块
from pymysql import connect
find_name = input("请输姓名:")
# 连接数据库
conn = connect(host='localhost', port=3306, database='python_db', user='root', password='123123', charset='utf8')
# 获得Cursor对象
cur = conn.cursor()
# # # 非安全的方式
# # # 输入 "小明" or 1
# sql = '''select * from students where name=%s''' % find_name
# print("""sql===>%s<====""" % sql)
# # 执行select语句,并返回受影响的行数:查询所有数据
# count = cur.execute(sql)

# 安全的方式
# 构造参数列表 
params = [find_name]
sql = '''select * from students where name=%s;'''
print("""sql===>%s<====""" % sql)
# 执行select语句,execute方法在内部实现了防SQL注入的功能,但具体如何实现并不清楚,隐藏了细节 
count = cur.execute(sql, params)
# 注意:
# 如果要是有多个参数,需要进行参数化
# 那么params = [数值1, 数值2....],此时sql语句中有多个%s即可 
# 打印受影响的行数
print(count)
# 获取查询的结果
result = cur.fetchall()
# 打印查询的结果
print(result)
# 关闭Cursor对象
cur.close()
# 关闭Connection对象
conn.close()

练习
使用 pymysql 模块完成练习
1. 准备工作
准备数据
创建数据库
create database JDDB charset=utf8;
use JDDB
导入数据
source JDDB.sql
2. 代码结构
功能列表
print(“1查询所有商品信息”)
print(“2查询所有商品所在种类信息”)
print(“3查询所有商品所在品牌信息”)
print(“4添加商品种类”)
print(“5根据id查询商品信息”)
print(“6根据id查询商品信息安全方式”)

方法命名

  #查询所有商品信息
  def fetch_all_info():
      pass

  #查询种类信息
  def fetch_cate():
      pass
  #查询品牌信息
  def fetch_brand():
      pass

  # 添加一个商品类型
  def add_info(type):
      pass

  # 通过ID 查找商品
  def find_info(id):
      pass

  # 通过ID 查找商品 防SQL注入
  def find_info_safe(id):
      pass
  1. 代码实现
    判断当前是否是主程序
    if name == ‘main’:
    main()
    实现主函数
    def main():

    创建 JD 类的对象

    jd = JD()

    运行 run 方法

    jd.run()
    实现 JD 类 因为所有的操作都要操作数据库,为了避免代码冗余,所以将连接和关闭操作设计到类中,对象创建成功,数据库就连接成功,对象销毁时,数据库关闭
 class JD(object):
 """JD 类,提供商品查询服务"""
 # 将数据库连接操作放到初化方法中,对象创建时,自动连接数据库
 def __init__(self):
     # 连接数据库
     self.__conn = connect(host='localhost', port=3306, database='JDDB', user='root', password='123123', charset='utf8')
     # 获取游标
     self.__cur = self.__conn.cursor()

 # 将数据库关闭操作放到 __del__方法中,当对象销毁时,自动关闭数据库
 def __del__(self):
     # 关闭游标
     self.__cur.close()
     # 关闭数据库
     self.__conn.close()

实现 run 方法 因为需要重复选择,所以要用死循环

 # run 方法,提供显示接口
 def run(self):
     while True:
         print("1查询所有商品信息")
         print("2查询所有商品在种类信息")
         print("3查询所有商品在品牌信息")
         print("4添加商品种类")
         print("5根据id查询商品信息")
         print("6根据id查询商品信息安全方式")

         selectID = input('请输入要执行的功能编号:')

         if selectID == '1':
             # 查询所有商品信息
             self.fetch_all_info()
         elif selectID == '2':
             # 查询种类信息
             self.fetch_cate()
         elif selectID == '3':
             # 查询品牌信息
             self.fetch_brand()
         elif selectID == '4':
             # 添加一个商品类型
             self.add_info()
         elif selectID == '5':
             # 通过ID 查找商品
             self.find_info()
         elif selectID == '6':
             # 通过ID 查找商品 防SQL注入
             self.find_info_safe()
         else:
             print('输入行号不正确!')

实现一个显示方法,用来输出结果

#用来显示结果的方法,私有,对外不可见
def __show_result(self, result):
    for t in result:
        print(t)
实现查询所有商品方法

#查询所有商品信息
def fetch_all_info(self):
    sql_str = ''' select * from goods;'''
    self.__cur.execute(sql_str)
    self.__show_result(self.__cur.fetchall())
查询种类信息

# 查询种类信息
def fetch_cate(self):
    sql_str = ''' select * from goods_cates;'''
    self.__cur.execute(sql_str)
    self.__show_result(self.__cur.fetchall())

查询品牌信息

# 查询品牌信息
def fetch_brand(self):
    sql_str = ''' select * from goods_brands;'''
    self.__cur.execute(sql_str)
    self.__show_result(self.__cur.fetchall())
添加商品类型

# 添加商品类型
def add_info(self):
    new_type = input('请输入商品类型:')
    sql_str = ''' insert into goods_cates values(0,"%s");'''% new_type #注意,这里占位符要加引号
    self.__cur.execute(sql_str)
    self.__conn.commit() # 修改操作要手动提交

根据id 查找商品
# 根据id查找商品
def find_info(self):
   id = input('请输入ID:')
   sql_str = ''' select * from goods where id=%s;'''%id
   self.__cur.execute(sql_str)
   self.__show_result(self.__cur.fetchall())
根据id 查找商品,案例防注入
# 根据id查找商品,案例防SQL注入
def find_info_safe(self):
   id = input('请输入ID:')
   sql_str = ''' select * from goods where id=%s;'''
   self.__cur.execute(sql_str,(id,))
   self.__show_result(self.__cur.fetchall())

视图

  1. 导语
    视图是一种基于查询结果产生的虚拟表。

  2. 为什么要有视图?
    当在执行查询操作时,经常会出现查询频率高并且查询语句非常复杂的情况。 每次都要将复杂的SQL语句重新书写,非常不便。
    比如:显示每种商品的名字以及对应的商品类型名和品牌名
    select goods.name,goods_cates.name,goods_brands.name from goods inner join goods_cates on goods.cate_id = goods_cates.id inner join goods_brands on goods.brand_id = goods_brands.id;
    mysql数据库(从入门到放弃)_第61张图片
    上面的功能实际很简单,但是书写起来很头疼,如果每天还要执行很多次。头大。。。
    如果能将这个查询的结果保存下来,下次在使用时,直接使用结果就非常完美了。
    这个需求通过视图就可以完成。

  3. 视图的特性
    视图是一个虚拟表,实际它就是一条被封装起来的 SQL 查询语句。
    在使用视图时,就相当执行了被封装的复杂SQL查询语句。
    视图不存储具体的数据。
    视图的基本表发生变化,那么视图也随之变化

  4. 视图操作
    定义视图 视图在定义时,建议视图名称以 v_xxx 形式命名,以便和普通的表区分。
    语法:create view 视图名称 as select语句;
    create view v_goods_info as select goods.name as gname,goods_cates.name as gcname,goods_brands.name as gbname from goods inner join goods_cates on goods.cate_id = goods_cates.id inner join goods_brands on goods.brand_id = goods_brands.id;

  5. 查看视图
    视图以表的形式体现,通过 show tables 即可查看视图。
    mysql数据库(从入门到放弃)_第62张图片
    使用视图
    视图的作用就是用来查询,视图的作用类似将子查询做了封装。
    select * from v_goods_info;
    mysql数据库(从入门到放弃)_第63张图片
    删除视图
    语法: drop view 视图名称
    drop view v_goods_info;
    mysql数据库(从入门到放弃)_第64张图片

  6. 视图小结
    视图封装了对多张基本表的复杂操作,简化用户操作
    视图只是一个虚表,并不存储任何基本表的表数据,当用户使用视图的时候 视图会从基本表中取出
    通过视图可以对用户展示指定字段从而屏蔽其他字段数据,更加安全

索引

  1. 什么是索引?
    能够快速查询数据的线索就称之为索引。

  2. 为什么需要索引?
    思考: 如何在一个图书馆中找到一本书的?
    在图书馆中如果没有其他辅助手段只能一条道走到黑,一本书一本书的扫。
    终于经过1个小时的连续扫描发现你需要看的那本书在一分钟之前被人借走了。
    这种方式是顺序查找。
    图书馆管理员发现这个问题,于是决定减少这样的悲剧故事。 为同学们购置了一套图书馆管理系统。
    大家要找书籍先在系统上查找到书籍所在的房屋编号和货架编号,然后就可以直接大摇大摆的去取书了。
    这个房屋编号和货架编号就是索引。
    除了词典,生活中随处可见索引的例子,如火车站的车次表、图书的目录等,它们的原理都是一样的。 通过不断的缩小想要获得数据的范围来筛选出最终想要的结果。

  3. 索引原理
    索引的原理就是为无序存放的数据建立一个有序的对应关系,通过这个关系可以快速查找数据。
    索引的目的在于提高查询效率。

  4. 索引的使用
    查看表中已有索引 show index from 表名
    创建索引 create index 索引名称 on 表名(字段名称(长度))
    如果指定字段是字符串,需要指定长度,建议长度与定义字段时的长度一致
    字段类型如果不是字符串,可以不填写长度部分
    删除索引: drop index 索引名称 on 表名;

  5. 验证索引的效率
    创建一个新表(不带索引)
    create table test_index(title varchar(10));

准备10万条数据

  from pymysql import connect

  def main():
      # 创建Connection连接
      conn = connect(host='localhost',port=3306,database='jddb',user='root',password='123123',charset='utf8')
      # 获得Cursor对象
      cursor = conn.cursor()
      # 插入10万次数据
      for i in range(100000):
          cursor.execute("insert into test_index values('ha-%d')" % i)
      # 提交数据
      conn.commit()

  if __name__ == "__main__":
      main()

查询验证
开启运行时间监测 set profiling=1;
查询 ha-99999 的数据 select * from test_index where title='ha-99999;
为表 test_index 创建索引 create index title_index on test_index(title(10));
再次查询 ha-99999 的数据 select * from test_index where title='ha-99999;
查看执行时间 show profiles;
mysql数据库(从入门到放弃)_第65张图片
使用 desc 命令也可以查看索引的效率 desc select * from test_index where title=‘ha-99999’;
mysql数据库(从入门到放弃)_第66张图片
6. 索引小结:
索引可以明显提高某些字段的查询效率。
但不是所有的表都需要建立索引
如果表中数据很少,没有必要建立索引
如果一个表中的数据增删很频繁,不能建立索引 ,因为只要数据发生增减,索引就要重新建立。增加了系统开销,反而慢了。
索引只适合查询操作频繁的表。

事务

知道事务的作用

  1. 什么是事务?
    事务 Transaction 是指作为一个基本工作单元执行的一系列SQL语句的操作,要么完全地执行,要么完全地都不执行。

  2. 为什么要有事务?
    以下内容出自《高性能MySQL》第三版,了解事务的ACID有助于我们更好的理解事务运作。 下面举一个银行应用是解释事务必要性的一个经典例子。假如一个银行的数据库有两张表:支票表(checking)和储蓄表(savings)。现在要从用户Jane的支票账户转移200美元到她的储蓄账户,那么至少需要三个步骤:

    • 检查支票账户的余额高于或者等于200美元。
    • 从支票账户余额中减去200美元。
    • 在储蓄帐户余额中增加200美元。
  3. 上述三个步骤的操作必须打包在一个事务中,任何一个步骤失败,则必须回滚所有的步骤。
    可以用START TRANSACTION语句开始一个事务,然后要么使用COMMIT提交将修改的数据持久保存,要么使用ROLLBACK撤销所有的修改。
    事务SQL的样本如下:

1. start transaction;
2. select balance from checking where customer_id = 10233276;
3. update checking set balance = balance - 200.00 where customer_id = 10233276;
4. update savings set balance = balance + 200.00 where customer_id = 10233276;
5. commit;
  1. 事务的四大特性 ACID

    • 原子性(Atomicity)

      • 一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作,这就是事务的原子性
    • 一致性(Consistency)

      • 数据库总是从一个一致性的状态转换到另一个一致性的状态。(在前面的例子中,一致性确保了,即使在执行第三、四条语句之间时系统崩溃,支票账户中也不会损失200美元,因为事务最终没有提交,所以事务中所做的修改也不会保存到数据库中。)
    • 隔离性(Isolation)

      • 通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的。(在前面的例子中,当执行完第三条语句、第四条语句还未开始时,此时有另外的一个账户汇总程序开始运行,则其看到支票帐户的余额并没有被减去200美元。)
    • 持久性(Durability)
      - 一旦事务提交,则其所做的修改会永久保存到数据库。(此时即使系统崩溃,修改的数据也不会丢失。)

  2. 事务操作
    MySQL使用的InnoDB引擎支持事务操作。
    mysql数据库(从入门到放弃)_第67张图片
    开启事务 开启事务后执行修改命令,变更会维护到本地缓存中,而不维护到物理表中
    begin; 或 start transaction;
    提交事务
    将缓存中的数据变更维护到物理表中
    commit;
    回滚事务
    放弃缓存中变更的数据 表示事务执行失败 应该回到开始事务前的状态
    rollback;

  3. 验证事务提交
    为了查看效果,需要打开两个终端窗口,使用同一个数据库,操作同一张表。
    step 1: 两个终端同时连接同一个数据库并查询同一张表 select * from goods_cates;
    step 2: 终端1开启事务,插入数据,查看

begin;
  insert into goods_cates(name) values('手机')
  select * from goods_cates;  -- 插入的数据显示插入成功了

setp 3: 终端2查询数据
  select * from goods_cates; -- 并没有看到新数据,因为终端1的操作缓存在本地,还没有提交。隔离性
step 4: 终端1提交数据,并查询
  commit; -- 提交后,事务完成,原子性操作结束
  select * from goods_cates;
step 5: 终端2查询
  select * from goods_cates; -- 可以查到新数据,一致性,持久性。
  1. 验证事务回滚
    为了查看效果,需要打开两个终端窗口,使用同一个数据库,操作同一张表。
step 1: 两个终端同时连接同一个数据库并查询同一张表 select * from goods_cates;

step 2: 终端1开启事务,删除所有数据,查看

  begin;
  insert into goods_cates(name) values('HIFI播放器');
  select * from goods_cates;  -- 插入的数据显示插入成功了
setp 3: 终端2查询数据

  select * from goods_cates; -- 并没有看到新数据,因为终端1的操作缓存在本地,还没有提交。隔离性
step 4: 终端1因为各种原因不想或不能提交数据,取消之前的操作

  rollback;
step 5: 终端2查询

  select * from goods_cates; -- 没有查到新数据,一致性,持久性。
  1. 事务小结
    事务的存在是解决数据在操作过程中的 ACID 问题。

用户管理

  1. 用户管理
    之前在登陆数据时,一直使用的都是 root 用户。
    root用户是数据库系统中的超级管理员,可以对数据库做任何操作。
    在生产环境中,开发人员一般只是对数据做读取操作。root 用户对于普通人来说,权限太大了,如果不小心做了一些不可逆的操作。那么后果是非常严重的。
    所以 root 用户不会让开发人员使用,一般会由DBA或运维人员统一管理。给开发人员针对项目的数据库建立专门的用户来操作。

  2. 查看所有用户
    MySQL中所有的用户及权限信息都存储在MySQL数据库的user表中。
    通过 desc user; 可以查看user表的结构
    主要字段:

  • Host 允许访问的主机地址 localhost 为本机, % 为任何主机
  • User 用户名
  • authentication_string 密码,保存的是加密后的值
    查看所有的用户
    select host ,user,authentication_string from user;
    mysql数据库(从入门到放弃)_第68张图片
  1. 创建帐户、授权
    注:用户管理操作的权限 都是管理员来操作的,只能使用 root 用户操作。
    常用权限: create、alter、drop、insert、update、delete、select
    全部权限: all privileges
    语法:grant 权限列表 on 数据库 to ‘用户名’@‘访问主机’ identified by ‘密码’;
    创建账户并授予查询权限
    – 加入testuser用户,密码123123,只能对jddb中的表做查询操作
    grant select on jddb.* to ‘testuser’@‘localhost’ identified by ‘123123’;
    mysql数据库(从入门到放弃)_第69张图片
    验证用户权限
    mysql数据库(从入门到放弃)_第70张图片
  2. 查看权限
    语法: show grants for 用户名@主机地址
show grants for testuser@localhost;
  1. 修改权限
    语法:grant 权限名称 on 数据库 to 账户@主机 with grant option;
    – 将testuser权限改为对所有库有所有权限
    grant all privileges on . to ‘testuser’@‘localhost’ with grant option;
    flush privileges;
    在这里插入图片描述

  2. 修改用户密码
    直接使用 update 对user 表中的用户进行修改密码。 注意: 密码需要使用 password(‘新密码’) 来进进加密
    update user set authentication_string=password(‘新密码’) where user=‘用户名’;

  3. 删除用户
    语法:drop user 用户名@主机地址 drop user ‘testuser’@‘localhost’; 或 delete from user where user=‘用户名’;

  4. 小结
    用户管理是MySQL当中一块非常重要的内容,它涉及到了数据的安全问题。
    但是对于开发人员来讲,这块内容在实际工作中涉及又不多,因为数据库的维护会有专门的运维人员或DBA来完成。
    一般在操作数据时,不会使用root用户。DBA会针对不同项目需求给你专门创建用户,甚至是视图。
    数据库高级部分的内容,大家主要做一个了解即可。当遇到问题时,要知道如何解决。或者可以快速找到解决办法。
    对于数据库编程。对表的CURD才是重要的。

主从配置(了解 )

主从配置

  • 主从同步使得数据可以从一个数据库服务器复制到其他服务器上,在复制数据时,一个服务器充当主服务器(master),其余的服务器充当从服务器(slave)。因为复制是异步进行的,所以从服务器不需要一直连接着主服务器,从服务器甚至可以通过拨号断断续续地连接主服务器。通过配置文件,可以指定复制所有的数据库,某个数据库,甚至是某个数据库上的某个表。
    使用主从同步的好处:
    提供服务可用性
    通过增加从服务器来提高数据库的性能,在主服务器上执行写入和更新,在从服务器上向外提供读功能,可以动态地调整从服务器的数量,从而调整整个数据库的性能。
    提高数据安全,因为数据已复制到从服务器,从服务器可以终止复制进程,所以,可以在从服务器上备份而不破坏主服务器相应数据

  • 主从同步的机制
    mysql数据库(从入门到放弃)_第71张图片
    Mysql服务器之间的主从同步是基于二进制日志机制,主服务器使用二进制日志来记录数据库的变动情况,从服务器通过读取和执行该日志文件来保持和主服务器的数据一致。

  • 在使用二进制日志时,主服务器的所有操作都会被记录下来,然后从服务器会接收到该日志的一个副本。从服务器可以指定执行该日志中的哪一类事件(譬如只插入数据或者只更新数据),默认会执行日志中的所有语句。
    每一个从服务器会记录关于二进制日志的信息:文件名和已经处理过的语句,这样意味着不同的从服务器可以分别执行同一个二进制日志的不同部分,并且从服务器可以随时连接或者中断和服务器的连接。
    主服务器和每一个从服务器都必须配置一个唯一的ID号(在my.cnf文件的[mysqld]模块下有一个server-id配置项),另外,每一个从服务器还需要通过CHANGE MASTER TO语句来配置它要连接的主服务器的ip地址,日志文件名称和该日志里面的位置(这些信息存储在主服务器的数据库里)

  • 备份恢复-配置主从需要了解的一个小知识
    备份
    运行mysqldump命令
    mysqldump –uroot –p 数据库名 > python.sql;
    按提示输入mysql的密码

  • 恢复
    连接mysql,创建新的数据库
    退出连接,执行如下命令
    mysql -uroot –p 新数据库名 < python.sql

  • 配置主从同步的步骤
    有很多种配置主从同步的方法,可以总结为如下的步骤:

  • 在主服务器上,必须开启二进制日志机制和配置一个独立的ID
    在每一个从服务器上,配置一个唯一的ID,创建一个用来专门复制主服务器数据的账号
    在开始复制进程前,在主服务器上记录二进制文件的位置信息
    如果在开始复制之前,数据库中已经有数据,就必须先创建一个数据快照(可以使用mysqldump导出数据库,或者直接复制数据文件)
    配置从服务器要连接的主服务器的IP地址和登陆授权,二进制日志文件名和位置
    主和从的身份可以自己指定,我们将虚拟机Ubuntu中MySQL作为主服务器,可以考虑将Windows中的MySQL作为从服务器。 在主从设置前,要保证Ubuntu与Windows间的网络连通,都使用桥接连接即可-请确认你的虚拟机工作正常。

  • 备份主服务器原有数据到从服务器
    如果在设置主从同步前,主服务器上已有大量数据,可以使用mysqldump进行数据备份并还原到从服务器以实现数据的复制。

  • 在主服务器Ubuntu上进行备份,执行命令:
    mysqldump -uroot -pmysql --all-databases --lock-all-tables > ~/master_db.sql
    在这里插入图片描述

  • 说明
    -u :用户名
    -p :示密码
    –all-databases :导出所有数据库
    –lock-all-tables :执行操作时锁住所有表,防止操作时有数据修改
    ~/master_db.sql :导出的备份数据(sql文件)位置,可自己指定

  • 在从服务器Windows上进行数据还原
    找到Windows上mysql命令的位置
    mysql数据库(从入门到放弃)_第72张图片
    新打开的命令窗口,在这个窗口中可以执行类似在Ubuntu终端中执行的mysql命令
    mysql数据库(从入门到放弃)_第73张图片
    将从主服务器Ubuntu中导出的文件复制到从服务器Windows中,可以将其放在上面mysql命令所在的文件夹中,方便还原使用
    mysql数据库(从入门到放弃)_第74张图片
    在刚打开的命令黑窗口中执行还原操作:
    mysql –uroot –pmysql < master_db.sql

mysql数据库(从入门到放弃)_第75张图片
配置主服务器master(Ubuntu中的MySQL)
编辑设置mysqld的配置文件,设置log_bin和server-id
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
在这里插入图片描述
mysql数据库(从入门到放弃)_第76张图片
重启mysql服务
sudo service mysql restart
在这里插入图片描述
登入主服务器Ubuntu中的mysql,创建用于从服务器同步数据使用的帐号
mysql –uroot –pmysql
GRANT REPLICATION SLAVE ON . TO ‘slave’@’%’ identified by ‘slave’;
FLUSH PRIVILEGES;
mysql数据库(从入门到放弃)_第77张图片
获取主服务器的二进制日志信息
SHOW MASTER STATUS;
mysql数据库(从入门到放弃)_第78张图片
File为使用的日志文件名字,Position为使用的文件位置,这两个参数须记下,配置从服务器时会用到

配置从服务器slave(Windows中的MySQL)
找到Windows中MySQL的配置文件
mysql数据库(从入门到放弃)_第79张图片
编辑my.ini文件,将server-id修改为2,并保存退出。
mysql数据库(从入门到放弃)_第80张图片
打开windows服务管理
可以在开始菜单中输入services.msc找到并运行
mysql数据库(从入门到放弃)_第81张图片
在打开的服务管理中找到MySQL57,并重启该服务
mysql数据库(从入门到放弃)_第82张图片
进入windows的mysql,设置连接到master主服务器
change master to master_host=‘10.211.55.5’, master_user=‘slave’, master_password=‘slave’,master_log_file=‘mysql-bin.000006’, master_log_pos=590;

  • 注:
    master_host:主服务器Ubuntu的ip地址
    master_log_file: 前面查询到的主服务器日志文件名
    master_log_pos: 前面查询到的主服务器日志文件位置

mysql数据库(从入门到放弃)_第83张图片
开启同步,查看同步状态
mysql数据库(从入门到放弃)_第84张图片

  • 测试主从同步
    在Ubuntu的MySQL中(主服务器)创建一个数据库
    mysql数据库(从入门到放弃)_第85张图片
    在Windows的MySQL中(从服务器)查看新建的数据库是否存在
    mysql数据库(从入门到放弃)_第86张图片

你可能感兴趣的:(mysql)