数据库入门

Posted by     "Eric" on Monday, December 9, 2019

一、MySQL数据库软件

MySQL的结构

MySQL是一个客户端/服务器的架构,它的服务器程序直接和我们存储的数据打交道,然后可以有好多客户端程序连接到这个服务器程序,发送增删改查的请求,然后服务器就响应这些请求,从而操作它维护的数据。服务器进程对客户端进程发送的请求做了什么处理,才能产生最后的处理结果呢?客户端可以向服务器发送增删改查各类请求,我们这里以比较复杂的查询请求为例来画个图展示一下大致的过程:

image-20200812224636555

存储引擎

MySQL服务器把数据的存储和提取操作都封装到了一个叫存储引擎的模块里。我们知道是由一行一行的记录组成的,但这只是一个逻辑上的概念,物理上如何表示记录,怎么从表中读取数据,怎么把数据写入具体的物理存储器上,这都是存储引擎负责的事情。为了实现不同的功能,MySQL提供了各式各样的存储引擎,不同存储引擎管理的表具体的存储结构可能不同,采用的存取算法也可能不同。

登录

  1. mysql -uroot -p密码
  2. mysql -hip -uroot -p连接目标的密码
  3. mysql –host=ip –user=root –password=连接目标的密码

退出

  1. exit
  2. quit

MySQL目录结构

数据库目录

MySQL有一个安装目录有一个数据目录,在数据目录中又有这样的几个概念

  • 数据库:文件夹
  • 表:文件
  • 数据:数据

二、SQL

SQL全称为Structured Query Language,即结构化查询语言,其通用的语法有

  1. SQL 语句可以单行或多行书写,以分号结尾。
  2. 可使用空格和缩进来增强语句的可读性。
  3. MySQL 数据库的 SQL 语句不区分大小写,关键字建议使用大写。
  4. 3 种注释
    • 单行注释: – 注释内容 或
    • 单行注释:#注释内容(mysql 特有)
    • 多行注释: /* 注释 */

根据SQL操作的对象和功能不一样,被分为四大类

  1. DDL(Data Definition Language)数据定义语言

    用来定义数据库对象:数据库,表,列等。关键字:create,drop,alter 等

  2. DML(Data Manipulation Language)数据操作语言

    用来对表中数据进行增删改,关键字:insert,delete,update等

  3. DQL(Data Query Language)数据查询语言

    用来查询数据库中表的记录。关键字:select,where等

  4. DCL(Data Control Language)数据控制语言

    用来定义数据库的访问权限和安全级别,及创建用户。关键字:GRANT, REVOKE 等

SQL语句分类

DDL:操作数据库、表

对于DDL语句,可以分为操作数据库和操作表,并且对于数据库和表,又都可以分为CRUD操作,即Create,Retrieve,Update和Delete。

  1. 操作数据库

    1.1 Create:创建

    • 创建数据库:

      create database 数据库名称;
      
    • 判断数据库是否存在,再创建:

      create database if not exists 数据库名称;
      
    • 创建数据库,并制定字符集:

      create database 数据库名称 character set 字符集名;
      

    1.2 Retrieve:查询

    • 查询所有数据库的名称:

      show databases
      
    • 查询某个数据库的字符集:

      show create database 数据库名称;
      

    1.3 Update: 修改

    • 修改数据库的字符集

      alter database 数据库名称 character set 字符集名称;
      

    1.4 Delete:删除

    • 删除数据库

      drop database 数据库名称;
      
    • 先判断数据库是否存在,再删除

      drop database if exists 数据库名称;	
      

    1.5 使用数据库

    • 查询当前正在使用的数据库名称

      select database()
      
    • 使用数据库

      use 数据库名称;
      
  2. 操作表

    2.1 Create:创建

    • 创建表
    create table 表名(
    	列名1 数据类型1
    	列名2 数据类型2
    	...
    	列名n 数据类型n
    );
    
    数据类型:
    1. int:整数类型
       * age int,
    2. double(总位数,小数点后位数):小数类型
       * score double(5,2)
    3. date:日期,只包含年月日,yyyy-MM-dd
    4. datetime:日期,包含年月日时分秒	 yyyy-MM-dd HH:mm:ss
    5. timestamp:时间错类型	包含年月日时分秒	 yyyy-MM-dd HH:mm:ss	
       * 如果将来不给这个字段赋值,或赋值为null,则默认使用当前的系统时间,来自动赋值
    6. varchar:字符串
       * name varchar(20):姓名最大20个字符复制表
    
    • 复制表
    create table 表名 like 被复制表明;
    

    2.2 Retrieve:查询

    • 查询某个数据库中所有的表名称
    show tables;
    
    • 查询表结构
    desc 表明
    

    2.3 Update:修改

    • 修改表名
    alter table 表名 rename to 新表名;
    
    • 修改表的字符集
    alter table 表名 character set 字符集名称;
    
    • 添加一列
    alter table 表名 add 列名 数据类型;
    
    • 修改列名称 类型
    alter table 表名 change 列名 新列名 新数据类型;
    alter table 表名 modify 列名 新数据类型
    
    • 删除列
    alter table 表名 drop 列名	
    

    2.4 Delete:删除

    drop table 表名;
    drop table if exists 表名
    

DML:增删改表中数据

  1. 添加数据:

    insert into 表名(列名1,列名2,...列名n) values(1,2,...n);
    
    • 注意:
      1. 列名和值要一一对应。
      2. 如果表名后,不定义列名,则默认给所有列添加值 insert into 表名 values(值1,值2,…值n);
      3. 除了数字类型,其他类型需要使用引号(单双都可以)引起来
  2. 删除数据:

    delete from 表名 [where 条件]
    
    • 注意:
      1. 如果不加条件,则删除表中所有记录。
      2. 如果要删除所有记录
        1. delete from 表名; – 不推荐使用。有多少条记录就会执行多少次删除操作
        2. TRUNCATE TABLE 表名; – 推荐使用,效率更高 先删除表,然后再创建一张一样的表。
  3. 修改数据:

    update 表名 set 列名1 = 1, 列名2 = 2,... [where 条件];
    
    • 注意:如果不加任何条件,则会将表中所有记录全部修改。

DQL:查询表中的记录

select * from 表名;

select
		字段列表
from
		表名列表
where
		条件列表
group by
		分组字段
having
		分组之后的条件
order by
		排序
limit
		分页限定
  1. 多个字段的查询

    select 字段名1,字段名2... from 表名;
    
    • 注意:如果查询所有字段,则可以使用*来替代字段列表。
  2. 去除重复:

    distinct
    
  3. 计算列

    • 一般可以使用四则运算计算一些列的值。(一般只会进行数值型的计算)
    • ifnull(表达式1,表达式2):null参与的运算,计算结果都为null
      • 表达式1:哪个字段需要判断是否为null
      • 如果该字段为null后的替换值。
  4. 起别名:

    • as:as也可以省略
  5. 条件查询:

    • where子句后跟条件
    • 运算符
      • >, <, <=, >=, =, <>
      • BETWEEN…AND
      • IN(集合 )
      • LIKE:模糊查询
        • 占位符:
          • _:单个任意字符
          • %:多个任意字符
      • 不能用!=或者=判断NULL,需要用IS NULL
      • and 或 &&
      • or 或 ||
      • not 或 !
  6. 排序查询

    • 语法:order by 子句

      • order by 排序字段1 排序方式1 , 排序字段2 排序方式2…
    • 排序方式:

      • ASC:升序,默认的。
      • DESC:降序。
    • 注意:

      • 如果有多个排序条件,则当前边的条件值一样时,才会判断第二条件。
  7. 聚合查询:将一列数据作为一个整体,进行纵向的计算。

    • count:计算个数

      • 一般选择非空的列:主键
    • max:计算最大值

    • min:计算最小值

    • sum:计算和

    • avg:计算平均值

注意:聚合函数的计算,要排除NULL值,可以选择不包含非空的列进行计算,或者使用IFNULL函数

  1. 分组查询
  • 语法:group by 分组字段;
  • 注意:
    • 分组之后可以查询的字段:分组字段、聚合函数
    • where 和 having 的区别?
      • where 在分组之前进行限定,如果不满足条件,则不参与分组。having在分组之后进行限定,如果不满足结果,则不会被查询出来
      • where 后不可以跟聚合函数,having可以进行聚合函数的判断。
  1. 分页查询
  • 语法:limit 开始的索引,每页查询的条数;

  • 公式:开始的索引 = (当前的页码 - 1) * 每页显示的条数 – 每页显示3条记录

    SELECT * FROM student LIMIT 0,3; – 第1页

    SELECT * FROM student LIMIT 3,3; – 第2页

    SELECT * FROM student LIMIT 6,3; – 第3页

  • limit 是一个MySQL"方言"

约束

  1. 概念:对表中的数据进行限定,保证数据的正确性、有效性和完整性
  2. 分类:
    1. 主键约束:primary key
    2. 非空约束:not null
    3. 唯一约束:unique
    4. 外键约束:foreign key

非空约束

值不能为null

  1. 创建表时添加约束
CREATE TABLE stu(
    id INT,
    NAME VARCHAR(20) NOT NULL -- name为非空
);
  1. 创建表完后,添加非空约束
ALTER TABLE stu MODIFY NAME VARCHAR(20) NOT NULL;
  1. 删除name的非空约束
ALTER TABLE stu MODIFY NAME VARCHAR(20);

唯一约束

值不能重复

  1. 创建表时,添加唯一约束
CREATE TABLE stu(
	id INT,
	phone_number VARCHAR(20) UNIQUE -- 添加了唯一约束
);
  1. 删除唯一约束
ALTER TABLE stu DROP INDEX phone_number;
  1. 在创建表后,添加唯一约束
ALTER TABLE stu MODIFY phone_number VARCHAR(20) UNIQUE;		

主键约束

  1. 注意:

    1. 含义:非空且唯一
    2. 一张表只能有一个字段为主键
    3. 主键就是表中记录的唯一标识
  2. 在创建表时,添加主键约束

CREATE TABLE stu(
	id int primary key, -- 给id添加主键约束
	name varchar(20)
);
  1. 删除主键
ALTER TABLE stu DROP PRIMARY KEY;	
  1. 创建完表后,添加主键
ALTER TABLE stu MODIFY id INT PRIMARY KEY;	
  1. 自动增长:

    1. 概念:如果某一列是数值类型,使用auto_increment可以来完成值的自动增长
    2. 在创建表时,添加主键约束,并且完成主键自增长
    CREATE TABLE stu(
    	id INT PRIMARY KEY AUTO_INCREMENT,
    	name VARCAHR(20)
    );
    
    1. 删除自动增长
    ALTER TABLE stu MODIFY id INT;
    
    1. 添加自动增长
    ALTER TABLE stu MODIFY id INT AUTO_INCREMENT;
    

外键约束

让表与表之间产生关系,从而保证数据的正确性

  1. 在创建表时,可以添加外键

    CREATE TABLE stu(
    	...
    	constraints 外键名称 foreign key (外键列名) references 主表名称(主表列名称)
    );
    
  2. 删除外键

ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;
  1. 创建表之后,添加外键
ALTER TABLE 表名 ADD CONSTRAINT 外键名 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称);
  1. 级联操作
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 
					FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称) ON UPDATE CASCADE ON
                    DELETE CASCADE;

三、多表查询

1. 内连接

隐式内连接

使用where消除无用数据

SELECT * FROM emp,dept WHERE emp.`dept_id` = dept.`id`;

或者使用如下语句,可以给表起别名,从而简化写法

SELECT 
    t1.name, -- 员工表的姓名
    t1.gender,-- 员工表的性别
    t2.name -- 部门表的名称
FROM
    emp t1,  --起别名
    dept t2  --起别名
WHERE 
    t1.`dept_id` = t2.`id`;

显式内连接

select 字段列表 from 表名1 [inner] join 表名2 on 条件

2. 外连接

左外连接:左表以及左表与右表的交集

select 字段列表 from 1 left [outer] join 2 on 条件;

右外连接:右表以及右表与左表的交集

select 字段列表 from 1 right [outer] join 2 on 条件;

四、子查询

查询中嵌套查询,称嵌套查询为子查询

子查询分为以下三种不同情况:

  1. 子查询结果是单行单列的,子查询可以作为条件,使用运算符去判断。运算符有:>, >=, <, <=, =
  2. 子查询的结果是多行单列的:子查询结果可以作为条件,使用运算符in来判断
  3. 子查询的结果是多行多列的:子查询的结果可以作为一个虚拟表,参与查询

五、数据库的设计

1. 多表之间的关系

  1. 一对一
    • 一对一关系实现,可以在任意一方添加唯一外键指向另一方外键,或直接集成在一张表中
  2. 一对多
    • 在多的一方建立外键,指向一的一方主键
  3. 多对多
    • 多对多实现需要借助第三张中间表,中间表至少包含两个字段,这两个字段作为第三张表的外键,分别指向两张表的主键

2. 数据库设计范式

设计数据库时,需要遵循的一些规范。要遵循后边的范式要求,必须先遵循前边的所有范式要求。目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。

  1. 第一范式(1NF):每一列都是不可分割的原子数据项
  2. 第二范式(2NF):在1NF的基础上,非码属性必须完全依赖于码(在1NF基础上消除非主属性对主码的部分函数依赖)
  3. 第三范式(3NF):在2NF的基础上,消除传递依赖

一些概念:

  1. 函数依赖:A–>B,如果通过A属性(属性组)的值,可以确定唯一B属性的值。则称B依赖于A 例如:学号–>姓名。 (学号,课程名称) –> 分数

  2. 完全函数依赖:A–>B, 如果A是一个属性组,则B属性值得确定需要依赖于A属性组中所有的属性值。 例如:(学号,课程名称) –> 分数

  3. 部分函数依赖:A–>B, 如果A是一个属性组,则B属性值得确定只需要依赖于A属性组中某一些值即可。 例如:(学号,课程名称) – > 姓名

  4. 传递函数依赖:A–>B, B–>C

    ​ 例如:学号–>系名,系名–>系主任

  5. 码:如果在一张表中,一个属性或者一个属性组,被其他所有属性所完全依赖,则称这个属性(属性组)为该表的码

    ​ 例如:该表中码为:(学号,课程名称)

    • 主属性:码属性组中的所有属性
    • 非主属性:除过码属性组的属性

image-20191208224853847

分析上表,学号和课程名称组成的属性组是码,则这两个属性也就是主属性。可见,姓名只需要学号就可以确定,所以对于码而言,是一个部分函数依赖,系所、系主任也是,因此将其剥离,也就是根据第二范式,可以将上表修改为下图。

image-20191208225906983

但此表仍然存在问题,虽然右边的表满足于范式二,但是存在传递函数依赖,如果此时我想设立一个计算机系,然而该系还未招生,就无法把这种关系表现出来,因此继续剥离,变成以下三个表

image-20191208225839666

六、数据库的备份还原

  1. 命令行:
    • 备份: mysqldump -u用户名 -p密码 数据库名称 > 保存的路径
    • 还原:
      1. 登录数据库
      2. 创建数据库
      3. 使用数据库
      4. 执行文件 source 文件路径
  2. 图形化工具:

七、事务

7.1 概念

如果一个包含多个步骤的业务操作,被事务管理,那么这些操作要么同时成功,要么同时失败。(在提交事务之前, 进行的操作都不针对实际的数据)

  • 操作:
    • 开启事务:start trasaction;
    • 回滚:rollback;
    • 提交:commit;
    • 事务的提交有两种方式:
      • 自动提交:mysql就是自动提交
      • 手动提交:需要先开启事务,再提交
      • 查询方式:SELECT @@autocommit;

7.2 事务的四大特征

  1. 原子性:是不可分割的最小单位,要么同时成功,要么同时失败
  2. 持久性:当事务提交或回滚后,数据库会持久化的保存数据。
  3. 隔离性:多个事务之间。相互独立。
  4. 一致性:事务操作前后,数据总量不变。

7.3 事务的隔离级别

  • 概念:多个事务之间本应该隔离的,相互独立的,如果多个事务操作同一批数据,会引发一些问题,设置不同的隔离级别可以解决这些问题

  • 存在问题:

    • 脏读:一个失误,读取到另一个事务中没有提交的数据。
    • 不可重复读:在同一个事务中,两次读取到的数据不一样。
    • 幻读:一个事务操作数据表中所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改(mysql不能存在)
  • 隔离级别

    • read uncommitted:读未提交
      • 产生问题:脏读、不可重复读、幻读
    • read committed:读已提交
      • 残生问题:不可重复读、幻读
    • repeatable read:可重复度
      • 产生问题:幻读
    • serializable:串行化
      • 可解决所有问题