您的位置:首页 > 博客中心 > 数据库 >

mysql数据库

时间:2022-03-16 10:44

第一天

?

永久性保存数据的仓库。

?

php的变量,在php脚本执行周期,临时性保存变量的概念!

?

什么是关系型

所谓关系型数据库,基于关系模型建立的数据!

关系模型:

?

mysql数据是关系型数据库!

?

何谓关系型(关系模型),利用关系(二维表),去描述实体信息,与实体之间的联系的数据库架构就是关系型数据!

?

所谓关系:二维表!

?

学生信息

?

mysql的操作,是基于 C/S 的!

Client / Server,客户端/服务器.

c/s指的是不同的服务器,提供的是不同的终端访问方式!

?

操作mysql,就一定:通过操作mysql客户端,向mysql服务器发出指令,从而完成操作!

技术分享

?

安装mysql时,自动携带一个命令行的客户端!mysql。

利用该客户端,向服务器发送指令,然后等待执行结果即可!

技术分享

技术分享

?

?

任何操作mysql服务器行为的行为,都是mysql客户端发出的!

?

?

msyql服务器的基本结构体系

技术分享

?

?

数据库服务器 ->库 ->表 ->字段(数据)

?

完成数据的操作,先建立数据的结构(由库到表再到字段)

?

?

?

SQL:大体分成典型:DML(数据管理语句,数据操作),DDL(数据定义语句,数据结构的控制语句,表操作和库操作)

库操作,DDL

创建,create

(create,几乎所有的结构都是用该语法完成)

create database 库名 [库选项]

技术分享

?

注意的问题:

库选项,只有字符集,校对集的概念!

?

每个库,会对应一个数据目录

存放在当前mysql的总的数据库目录内

参考 mysql的配置文件得到该目录:

技术分享

技术分享

看到刚刚的数据库目录:

技术分享

看看目录内,没有表,没有其他文件,除了一个数据库选项文件:

技术分享

?

技术分享

?

?

数据库名的问题

大小写问题,取决于mysql服务器,所在的操作系统!(建议是,认为区分)

特殊名称,关键字,特殊字符等!默认是不可以的!

技术分享

但是,可以使用反引号将名称包裹起来,告知服务器,此处一个名字,而不是特殊操作!

技术分享

中文等都可以作为标识符(库名),需要同样反引号!(多字节字符,还需要注意字符集的问题)

技术分享

?

查询(看看有哪些库,库的基本结构),show

查询已有的数据库名字

show databases;

技术分享

show databases likes;

like 关键字用于过滤多个数据库!

技术分享

可以使用通配符(通用匹配符,可以匹配多个字符)

% 匹配任意字符的任意次数(包括0次)的组合!

_ 匹配任意字符的一次!

?

like ‘x_y‘;

x1y xby xxy(可以)

xy(不可以)

?

通配符是与 like 关键字一起使用!

?

注意如需要匹配特定的通配符,则需要对通配符转义,使用反斜杠\完成转义!

技术分享

查看某个数据库的定义

show create database 库名;

技术分享

技术分享

修改,alter

alter database 数据库名

只能修改数据库选项

技术分享

?

?

删除,drop

drop database 名字

技术分享

?

?

if not exists, if exists

在 create 与 drop 时,创建和删除时,有两个额外的操作:

?

create database if not exists 库名

如果不存在则创建

?

drop database if exists 库名

如果存在,则删除

技术分享

?

表操作,DDL

表本身,与表结构的操作!

?

?

创建,create table

create table 表名 (

字段的定义

) [表选项];

?

其中表名,一定先要确定数据库!因此一个典型的表名是由两部分组成:

所在库.表名

test.itcast ????test库内itcast表

itcast.stu ????itcast库内的stu表

?

但是我们可以设置默认数据库,如果不指定则使用默认数据库(当前数据库)

use 数据库名。选择默认数据库!

在使用表名但是没有指明其所在数据库时,默认数据库才会起作用!

技术分享

在itcast库内创建:

use itcast ; create table stu;

或者

create table itcast.stu

?

?

其中字段的部分

字段才是最终的数据的载体(与变量的概念是类似的,都是基本保存数据的),mysql的是强类型,字段的类型是固定的,提前定义好的!

因此,在定义字段时,至少要字段名和字段类型!

两种最基本的mysql数据类型(int, varchar,varchar必须指定最大长度字符为单位)

?

表选项部分

典型的常用的表选项有:

字符集(校对集),表引擎。

技术分享

?

查看,show,desc

查看所有的表有哪些

show tables like ‘模式‘

技术分享

查看具体的建表语句

show create table table_name

技术分享

在mysql的命令行客户端,如果数据过多,不容易展示!

可以使用 \G 作为语句结束符!

技术分享

?

查询表结构

desc 表名

desc describe的简写

技术分享

?

修改,alter table

修改表选项

alter table table_name [新选项]

技术分享

?

改表名

rename table原表名 to 新表名。

技术分享

注意,表名可以由库名.表名形式的!

因此,可以跨库修改表名:只要在表名前增加库名即可

技术分享

?

修改表结构,表内字段

增加字段

alter table table_name add column 字段定义 [字段位置]

?

增加一个 age字段:

技术分享

技术分享

?

增加一个 height 在 name之后:

使用关键字 after some_column_name;

技术分享

在最开始增加sn字段

使用关键字,first

技术分享

?

删除字段

alter table table_name drop column column_name;

?

技术分享

?

?

修改已有字段(修改字段定义)

alter table table_name modify column column_name 新的定义!

可以修改位置

技术分享

字段改名

alter table table_name change column 原字段名新字段名新字段定义!

注意,不是纯粹的改名,而是需要在修改定义的同时改名!

技术分享

?

删除,drop table

技术分享

?

drop table if exists

create table if not exists!

?

?

?

?

?

数据操作,DML

基本的操作

增加,创建,插入,insert

insert into 表名 (字段列表) values (与字段相对的值列表)

不一定要一次性插入所有字段,或者按照原始的字段顺序插入:

技术分享

但是:

字段与值的数量一定要匹配:

技术分享

特别的:

如果所有的值都按照字段的出现顺序都插入的话,可以省略字段列表部分!

技术分享

注意:数值类型,不需要增加引号!而字符串类型都需要出现引号内!(但是数值型,可以出现引号内)

?

查询,检索,选择,select

select 字段列表 from 表名 [where 条件表达式]

其中字段列表可以使用 * 表示所有字段!

技术分享

?

关于条件表达式,默认是没有,表示永远为真!

但是,很少出现没有条件的情况!

技术分享

?

为了突出,应该所有的语句都有查询条件!即使没有条件,我也强制增加一个 where 1;

技术分享

?

关于字段列表:

也应该够用就可以!

技术分享

?

?

删除,delete

delete from 表名 where 条件;

关于条件,可以省略。表示永远为真。

技术分享

注意,删除是不可逆的。要避免没有条件的删除!

?

?

修改,更新,update

update 表名 set 字段=新值, 字段n=新值n where 条件

关于条件,可以省略。表示永远为真。

技术分享

?

?

?

create,show,alter,drop ????database/talbe

add,modify,change,drop column

insert , select, update, delete table_name

?

?

字符集

?

字符集,描述可见到的图形,在存储和传输时使用的编码称之为字符集!

指的是:

图形与编码之间的对应关系!

?

字 => 11100101 11100001 00010100

?

技术分享

?

?

数据存储的编码

数据是存储在服务器端的!究竟是以哪种编码保存的,怎么决定?

数据是最终要映射(保存)到字段的层面上!因此决定数据的编码,也是最终由字段来决定!

?

确定数据的存储编码是由以下的方案完成的:

  1. 先看字段的编码!如果存在则确定完毕!
  2. 如果字段没有设置编码,查看表的编码,如果有,则确定数据编码!
  3. 如果表没有编码,查看库的编码,如果有,则确定数据编码!
  4. 如果库也没有编码,则有服务器程序确定!

技术分享

?

?

?

典型的编码:gbk,utf8!

?

?

?

?

客户端操作,查询的编码

?

在客户端与服务器端交互时,存在两个重要的编码:

  1. 客户端发送数据的编码
  2. 客户端接收到服务器数据编码!

?

可以通过 show variables like ‘character_set_%‘展示以character_set开头变量,其中就有上面的两个值:

技术分享

?

在命令行客户端下:

该客户端,只能是gbk编码!

?

?

技术分享

?

使用 set 变量名 = 变量值的形式更改变量值!

技术分享

?

set names gbk,就是一个快捷操作,将上面两个配置同时更改成目标编码!

?

set names gbk|utf8 取决于,客户端所能接受的编码!

?

?

整体流程:

?

技术分享

?

set names gbk|utf8。

?

?

PHP操作mysql服务器

?

php作为mysql服务器的客户端!

?

连接认证

?

发送sql

????执行sql,生成结果(mysql-server)

处理结果

?

关闭连接

?

?

加载必要的扩展,使可以作为客户端使用

mysql_connect();

技术分享

技术分享

?

?

连接认证

mysql_connect()

技术分享

成功返回连接资源,失败 false!

?

?

向mysql服务器发送sql

?

mysql_query(sql, 连接资源);

失败返回false,成功返回资源或者true!

可以使用 mysql _error(连接) mysql_errno(连接)获得错误信息和标识

技术分享

?

处理返回数据

执行成功后:返回数据可以是资源也可以true。执行失败一定是false!

依据所执行的 sql,是否有返回数据!

返回资源:有返回数据:select,show,desc。

返回true:没有返回数据的: use,set,insert,update,delete,DDL

?

?

处理返回资源

技术分享

称之为结果集(result set)类型资源!

?

结果集:结果的集合!

?

将数据,从结果集中取出来!称之为 fetch!

使用函数:

mysql_fetch_assoc|row|array。功能完全一致,只是返回的数据格式不同!

?

在结果集中,取得一条记录。结果集内也存在结果集记录指针的概念!

fetch一次,只能取得当前记录,但是可以向后移动记录指针!配合上循环结构可以将所有的记录从结果集中取出!

技术分享

技术分享

?

?

特别注意:

任何有结果的sql操作,返回的都是结果集!

结果集,就是一个二维表的结构!是一行行的记录组成!

即使,结果集中只有一条记录

甚至,我们只需要返回一条数据!

?

技术分享

?

?

释放资源

mysql_free_result(结果集)

mysql_close(连接资源);

技术分享

?

?

?

预习

校对集

列类型(数据类型)

列选项(列属性,列约束)

设计模式(范式,关联)

?

作业

1,模拟查找所有的数据表结构

?

?

2,编码问题!

?

?

第二天

?

连接的必要四个参数:

技术分享

?

客户端发送一条sql:

客户端编码(character_set_client)->连接层编码(characger_set_connection)->服务器内部编码(server_internal)

?

服务器端发送结果:

服务器内部编码(server_internal)->连接层编码(characger_set_connection)->客户端接收的结果编码(character_set_results)

?

?

总体的编码问题:

技术分享

?

?

先获得所有的数据库:

技术分享

为其增加链接,请求到table.php展示所有的表,应该以 GET方式(在url上传递)形式将库名,传递到table.php

技术分享

?

table.php

先获得表名列表,再为其增加指向结构和数据的连接!

技术分享

?

技术分享

?

注意,在获得表结构与数据时,至少需要库名和表名两个参数!

技术分享

?

?

column.php获得结构

技术分享

展示:

技术分享

?

?

rows.php

展示列表时,先展示字段名,再展示数据!

?

?

?

mysql_num_rows($result)获得结果集中的记录数量

?

校对集,collate

指的是字符之间的比较关系!

?

a B c

or?

B????a????c

技术分享

?

此时,使用 order by对结果排序,看结果:

技术分享

?

顺序为 a-B-c 忽略了大小写!

?

可以被校对集改变:

利用 show collation; 查看到所有的校对集!

技术分享

技术分享

校对集,依赖于字符集!

校对集,指的是,在某个字符集下,字符的排序关系应该是什么,称之为校对集!

?

再创建一个 utt8_bin的校对集表,在排序:

技术分享

?

技术分享

?

我们典型的选择:

技术分享

?

典型的后缀:

_bin 二进制编码层面直接比较:

_ci 忽略大小写(大小写不敏感)比较

_cs 大小写敏感比较

?

mysql的数据类型,列类型,字段类型

三大类:

数值,字符串,日期时间

?

数值

整数,int

int 4个字节。

还有占用其他空间的整型:

tinyint????????1

smallint ????????2

mediumint????3

int????????????4

bigint????????8

技术分享

如何选择:

通过业务逻辑判断!常见的是 tinyint,int!

?

mysql的整型,有php整型不具备的概念:

one,无符号

只能表示整数或0。那么最大的整数会很大!

默认是有符号!可通过整型的 unsigned选项,int unsigned 设置整型无符号

技术分享

技术分享

?

无符号的:

技术分享

?

two,显示宽度

显示宽度,不决定整型的范围。而决定在显示出该数之后,如果宽度不够,则采用前导零不齐!此时需要额外的属性 zerofill 来设置!

技术分享

可见无符号,默认的显示宽度是 10,因此全都使用0来补齐。

可以设置整型的显示宽度!在 int(M)即可!

技术分享

255个宽度就可以了!

?

注意,如果超出了宽度范围,则直接显示!

技术分享

?

?

额外的,mysql中,没有布尔型!

但是存在Boolean这个关键字,表示 tinyint(1)

技术分享

典型的,0表示假,1表示真!

?

浮点数,float,double

单精度,float,4个字节

双精度,double,8个字节

?

技术分享

?

双精度:

技术分享

?

在定义浮点数,典型的需要指明其有效位数,和小数位数

float(M,D)

double(M,D)

M:所有的有效位数

D:其中的小数位数

以上两个值,决定一个浮点数的有效范围!

技术分享

?

典型的浮点数

float(10, 2);

99999999.99

注意,浮点数,近似值,不是精确值!如果一个数,很大,接近最大值,可能出错!

技术分享

?

一旦出现精确数据(小数)需要保存可以使用,下面的定点数

?

定点数,decimal

小数点是固定的!

decmal,与定义浮点数一致,也有有效位数与小数位数的概念:

?

decimal(M,D)

技术分享

不是数的形式存储,类似于字符串的形式!

技术分享

?

注意,关于小数:

1,支持科学计数法

技术分享

2,同样支持 unsigned,无符号!

3,同样支持 zerofill,

技术分享

?

TIP:小数的M,即表示有效范围,也表示显示宽度!(而整数的M只表示显示宽度)

?

?

字符串类型

char

最基本(定长)的字符串类型!

用于保存,长度固定的内容!

速度快,但是保存变长数据,会浪费空间!

varchar

可变长度的字符串!

用于保存长度可变的数据!

保存变长数据时,节省空间,处理起来麻烦些!

?

char(L),varchar(L)

L,表示每个数据的最大长度!单位是字符数(不是字节数)

技术分享

L 表示最大长度!

?

L的值不是多大都可以!

有最大值:

1,mysql一条记录最大不能超过65535个字节!(字段的长度加起来,不能超过这个值)

2,长度单位是字符数,与编码是相关的!

技术分享

?

采用单字节编码测试下:

Latin1

技术分享

测试发现只有一个字段,而且是单字节字符集,还是不能是65535,原因是?

技术分享

为什么是 65532呢,少了三个字节:

3,由于varchar是变长,需要记录下真实的数据到底有多长!每个varchar类型的数据,还需要额外的1个或2个字节保存真实数据的长度!(取决于真实数据的长度)

4,整条记录,还需要一个字节来保存那些字段为null

技术分享

?

但是,在使用时,varchar 超过255就选择 text来保存!

?

text

文本,不限长度的字符串!

该字段,不需要指定长度,而且也不会算入到记录的总长度内!

技术分享

?

?

选择

定长,char

变长较短(255)个字符之内,varchar

变长,较长,text

?

?

枚举,enum,单选

需要在定义枚举类型时,列出哪些是可能的!

技术分享

?

在处理时,类似字符串型进行操作!

?

意义在于:

  1. 限定值的可能性!

技术分享

  1. 速度快,比普通的字符串速度快!

原因是枚举型是利用整数进行管理的,能够2个字节进行管理!

?

技术分享

每个值,都是一个整数标识,从第一个选项开始为1,逐一递增!

管理时整数的形式,速度比字符串快!

技术分享

?

2 个字节,0-65535,因此可以有 65535个选项可以使用!

集合,set,复选

类似于 enum枚举,在定义时,也需要指定其已有值!

?

技术分享

与字符串相比,优势是:

  1. 也是采用整数进行管理的!采用位运算,从第一位开始为1,逐一x2!

技术分享

?

  1. 每个集合类型8个字节,64位,因此可以表示64个元素!

?

注意:站在 mysql的角度,尽量多用枚举和集合!

但是站在php操作mysql的角度,尽量少用!(兼容性差)

?

?

日期时间

datetime

,日期时间,用于保存大范围的日期时间!

‘1000-01-01 00:00:00‘到‘9999-12-31 23:59:59‘

在处理时是使用字符串的形式进行管理!

技术分享

?

timestamp

时间戳,管理常用的典型时间,从1970-1-1开始。空间少,而且是以整型的形式管理,但是一个字符串的形式展示的!

技术分享

?

?

date

日期,如果只记录日期,不记录时间采用 date!

?

year

在保存年份的时候。

采用一个字节保存!因此只能表示 1901——2155年!

?

time

时间,时间时刻!

还可以表示时间跨度!时间段的概念!

技术分享

?

总结:

one:除了time,表示都是时间点的概念!time还表示时间跨度!

?

two:年份的表示

可以采用2位年份:

0-69 表示 20 XX

而 70-99 表示 19XX

技术分享

技术分享

1990

2090

?

  1. 除了-还有:可以作为日期和时间分隔符之外,很多其他字符都可以!

技术分享

?

?

放在php程序中:

小范围的日期:使用整型

大范围的日期:字符串!

?

?

列属性,字段约束

NULL,not null属性空约束

mysql的NULL不是数据,也不是类型!只是标识属性!

用于说明某个字段,是否可以为null(是否可以什么都不存)

?

NULL采用关键NULL表示!(不是字符串)

是:NULL,而不是:‘NULL‘

属性:

null 表示可以为空

技术分享

not null,表示不能为空

技术分享

?

?

如果,在添加数据时,没有指定值,也可能会是NULL!

?

?

default属性,默认值约束

采用 default 关键字,来限定一个字段的默认值,在没有指定字段数据时,采用默认值!

技术分享

?

技术分享

default 与 null 的处理关系!

如果此时,该字段被指定了一个null:

不能使用默认值,允许为null则为null,不允许则插入失败!

技术分享

?

如果一个字段没有指定默认值,那么默认为NULL

技术分享

此时:如果在定义该字段时,不允许为NULL,则插入时,必须保证该字段有值才可以!

(另外一个选择是增加默认值)

技术分享

?

?

默认值,存在一些特殊的标记关键字:

default,用在值中的关键字!

技术分享

?

current_timestamp,用在第一个时间戳类型的字段上,表示当前的时间!

技术分享

典型在很多表上增加一个 update_time 将其默认值设置成 current_timestamp。就可以记录下当前记录的最后操作时间!

?

主键约束/唯一约束,primary unique

站在约束的角度,限制的,该字段,值要唯一!

?

但是主键与唯一不是一个概念:

?

都是索引的一种!

主键:

可以唯一标识记录的字段,称之为主键!

?

唯一:

保证在某个字段上的数据是唯一的,可以设置成唯一约束!

?

但是,一个表,只能有一个主键!

典型的,在创建表时,主动增加一个非实体的自然属性,充当主键,采用整型,运算速度快!

技术分享

其他的唯一字段,建立唯一约束!

?

建立:

两种方案:

技术分享

一旦创建了主键:

默认就是不能为空:

技术分享

唯一,使用 unique key 来创建!

技术分享

技术分享

?

一个表可以有多个唯一,但是只能有一个主键!

?

注意:主键或者是唯一,都可以由多个字段组成!

技术分享

?

因此,主键与字段的概念:字段来充当主键,不是字段就是主键!(称之为复合主键)

尽量采用 id 一个来作为主键!

技术分享

?

如果管理的主键/唯一呢

删除主键:

alter table表名 drop primary key;

技术分享

添加主键

alter table 表名 add primary key(‘字段列表‘);

技术分享

?

?

删除唯一

alter table 表名 drop index index_name;

索引的名字,可以通过 show create table 看到!

技术分享

?

技术分享

?

增加唯一

alter table 表名 add unique key 索引名字 (字段列表)

技术分享

?

自动增长,auto_increment

?

用于主键,只有一个字段主键,才能使用auto_increment!

可以,从1开始,逐一递增的数值!

?

目的是保证唯一,计算方面!

技术分享

?

典型的,从1 开始,没有负数,可以采用无符号 unsigned整型!

技术分享

?

技术分享

?

?

注意: unsigned,不是列属性,是类型的一部分!(包括zerofill)因此位置上与类型在一起!

技术分享

?

?

comment,注释

技术分享

外键!

预习

  1. 范式
  2. 表实体之间的关系
  3. 外键约束

4,语句(查询语句)

作业

1????说说那些地方可以设置编码

2????增加对库的管理(删,增加)

????增加对表的管理(增加,改名,删除)

????增加对字段的管理(增加,删除)

????增加对数据的管理(增加,删除,编辑)

?

位,bit,比特,计算机可以处理的最小单元

字节,Bytes 存储的最基本单位。KB 千字节, MB,兆字节,GB,1024*MB,TB,1024*GB。一个字节 8 个位。 1Byte = 8 bit.

字符,char,一个显示逻辑上的单位,一个图形就是一个字符。

?

字,双字节

双字,4字节。

?

  1. 编程,定义一个函数

参数为 table_name 表名,要求大家返回一个数组,内容是当前表的结构信息!只需要字段名,如果有主键,则在返回其主键(不考虑符合主键)

?

f1(stu)

array(‘id‘, ‘name‘,‘pk‘=>‘id‘)

?

  1. 建立一个学生信息表!尽可能利用多种类型!

第三天

?

编码:

建表,建库,建字段设置(数据库中的数据的编码)

PHP作为mysql服务器的客户端,设置的客户端编码和连接编码(set names)

设置php返回给浏览器数据的编码,(Content-Type,header(),<meta>)

PHP文件本身保存的编码(文件编码,通过文本编辑器设置)

?

?

[浏览器查看时,可以强制指定编码]

?

?

删除库

增加删除的链接,传递所操作的库名!

在数据库列表页:

技术分享

?

增加一个处理删除的功能页面:

?

在形成sql时,只要出现了标识符(库名,表名,字段名,索引名),都使用反引号!

?

请求跳转:

header(‘Location: url‘);//告知浏览器,对新的url发出请求!

database_drop.php

技术分享

?

新建库

执行 create database

?

?

列表页,增加一个链接,请求到创建页:

技术分享

?

增加一个create_form表单页面

技术分享

?

在增加一个脚本处理该数据即可

database_create.php

技术分享

如果存在多个选项,因该如何处理?

例如字符集!

?

应该,取得所有的字符集。

利用 show character set;可以展示所有的字符集!

技术分享

技术分享

?

?

?

在创建库时,需要先对哪个字符集做一次判断!(是否是默认)

database_create.php

技术分享

?

查询表:

table.php

利用mysql_num_rows($result)可以获得结果集中的记录数:

技术分享

?

展示一个增加表名与记录数的小表单:

技术分享

?

?

显示创建table的表单

table_create_form.php

技术分享

?

处理提交数据:

应该为每组数据形成一个唯一的标识!采用数组下标的形式!

技术分享

技术分享

?

循环对数据做判断,然后依次拼凑sql语句:

?

?

?

?

关系(二维表)的设计规范,范式

范式,NF,normal format,就是指对表的结构的要求!

目的:1,规范结构!2,减少数据冗余!

?

第一范式,1NF,字段原子性

要求字段不能再分,要求字段的原子性

技术分享

?

第二范式,2NF,非部分依赖

增加唯一主键即可!ID

?

范式的要求,是逐渐递增!

在满足了第一范式的前提下,不能出现部分依赖!

部分依赖指的是:普通字段对主键是完全依赖的,而不应该是依赖主键的一部分!

依赖:可以通过那个字段去决定另一个字段

?

因此,出现主键部分依赖的前提是,出现复合主键!

技术分享

?

其中代课时间,开始和结束时间,没有部分依赖!称之为完全依赖于主键:

?

但是,性别,依赖于讲师字段即可!

讲师字段是主键的一部分!因此称之为性别部分依赖于主键

技术分享

因此,该表不符合第二范式!

?

怎么做?

消灭复合主键即可!增加一个唯一字段的主键即可。增加一个与业务逻辑毫无关系的,唯一的ID主键,int unsigned primary key auto_increment

技术分享

?

?

第三范式,3NF,非依赖传递

在满足第二范式的前提下,取消传递依赖,就是第三范式!

?

传递依赖:如果字段B对字段A有依赖,而字段C对字段B存在依赖。则出现了传递依赖!

讲师依赖于ID,而性别依赖于讲师。

班级依赖于ID,而教室依赖于班级。

技术分享

称之为传递依赖!

?

解决,要保证所有的字段都完全依赖于主键,而不依赖于其他字段!

将独立的实体信息,使用独立的关系(二维表)进行保存!

分别增加讲师,班级表,将代课信息内的讲师和班级信息拆分出:

技术分享

?

?

总结:

每个实体建立一个表,为每个表增加一个主键ID即可!

?

?

?

一个实体表应该如何设计

实体之间的关系的设计

多个是体表应该如何设计!

?

实体之间存在哪些关系?

班级,学生两类实体!

一对多,多对一,1:N, N:1

?

班级,讲师两类实体!

多对多,M:N

?

学生常用信息,学生不常用信息

一对一,1:1

?

如何设计?

多对一,一对多

在多的那端(那个表内),增加一个字段,用于保存于当前记录相关联的一端记录的主键!

技术分享

?

多对多

技术分享

?

增加一个专门管理关联的表,使班级与讲师都与关连表存在联系。从而是两个实体间有多对多的关系!

技术分享

?

因此,一个多对多,会拆分成两个多对一!

?

?

一对一

技术分享

可见,两个表之间存在相同的主键ID即可!

?

?

外键约束

约束的作用,是用于保证数据的完整性或者合理性的工具!

外键:foreign key,当前表内,指向其他表的主键的字段,称之为外键!

技术分享

?

外键约束:用于限制相关联的记录在逻辑上保证合理性的约束称之为外键约束!

?

约束,不是字段。

?

建立班级表

技术分享

?

再创建学生表

技术分享

?

看看删除班级的情况:

技术分享

出现了不合理数据:

?

此时,可以通过增加外键约束的方式,来限制以上的操作!

?

增加外键

alter table 表名 add constraint 约束的名字 foreign key 外键索引名字 (外键字段名) references 关联表名 (关联字段) [操作]

技术分享

再删除个试试:

技术分享

?

注意:如果当前的数据,已经不符合所见约束关联,则创建失败!

?

删除外键

alter table table_name drop foreign_key外键名字!

?

可以通过 show create table 查看约束的名字:

技术分享

?

?

?

注意,外键约束与索引的关系:

?

如果需要在某个字段上,增加外键约束,那么需要该字段也同样有索引!如果该字段上,没有索引,此时,mysql会自动在该字段上增加一个普通索引!

技术分享

?

?

可以选择指定外键约束的名字:

技术分享

技术分享

注意上面的外键约束自动建立的索引的名字,与外键的名字相同!

?

总结:在创建时:

  1. 外键与相应关联表的主键类型
  2. 已有数据,必须满足约束条件才可以!
  3. 可以使用 constraint 关键字,为外键约束起名字!

?

?

约束操作

在对父表(被关联的表)做操作时,有三种行为:

  1. 严格限制,拒绝操作。restrict
  2. 置 null,set null
  3. 级联操作,cascade

以上三个行为操作,会在主表记录被删除或者更新时被使用!

on delete set null

on update cascade

技术分享

?

技术分享

?

更新时的级联操作:

只有在关联表的主键发生变化时,才会影响到从表的关联字段的变化!

技术分享

?

?

主表:被关联的

从表:发出关联的!

?

?

应该注意的问题:

关于,外键约束,只能在当前的mysql的的innodb表类型(引擎)下才会生效!

技术分享

?

外键,站在php程序的角度,用到的不多!

?

?

?

数据操作,DML,DATA Management Language

?

增加操作insert into

一条insert into可以插入多条记录

技术分享

?

?

insert into 支持判断主键(唯一)是否冲突,从而执行更新

技术分享

insert into 表名 (字段列表) values (值列表) on duplicate key update 字段=值,字段=值

技术分享

注意,update后没有 set

?

?

insert into 表名 select 语句;

技术分享

注意,并不是一定要字段数一致,才可以完成操作,只要是字段数量与字段类型一致,就可以完成插入!

?

?

查询 select 的用法

?

基本的查询语句的结构

?

select [字段表达式列表] [from子句] [where 子句] [group by 子句] [having 子句] [order by子句] [limit 子句]

?

字段表达式子句

注意,表达式与别名的概念

1+1,$v1+10, abs(-10)

技术分享

?

如果为字段名,那么字段名就是一个变量的概念,可以参与运算!

技术分享

?

?

因此,可以利用各种运算符,来形成SQL中的表达式!

例如:逻辑运算符:

技术分享

?

关系运算符:

技术分享

?

可以是一个列表

技术分享

?

每个表达式,可以有一个别名:

select结果内,以表达式本身来命名的!

技术分享

但是,有两个典型的问题:

  1. 表达式直接做名字不容易识别!
  2. 如果名字冲突,不能区分!

技术分享

使用 AS 关键字可以使用别名,可以省略as关键字,但是不建议省略!

技术分享

?

?

from子句

表示查询的来源,就是表!

?

可以写表名列表,使用逗号分割

技术分享

?

如果此时没有条件,相当于形成了一个笛卡尔积!

A集合的每个元素,都与B集合的每个元素之间有个关联!

?

A表的所有记录,都与B表的所有记录之间存在关联!

?

?

此时结果中会将所有的字段都列出来,包括重名的!

技术分享

可以为相应的字段名起别名:

此时访问到某个字段需要使用表名.字段名的形式!

技术分享

?

?

表的别名

如果多次出现表名.字段名的情况,可以为表名起别名!

技术分享

?

dual 的问题

?

虚拟表名问题

技术分享

?

是语法更加规范而已!

?

?

where子句,查询条件子句

where 条件表达式

运算符,变量(字段)

?

省略where子句,相当于永远为真~

技术分享

?

where,找到每条记录,并依次执行条件表达式,根据条件结果返回数据!

?

形成条件表达式的基本要素:

数据,(变量),运算符,函数调用()

?

典型的运算符:

关系:????>????<????>=????<= ????!=????=

like模糊查询。数据 like ‘模式匹配符‘

可以使用 % 和 _ 作为通配符

技术分享

?

not like,不像like取反!

技术分享

技术分享

?

between 3 and 5,在某个区间,闭区间。

技术分享

包括边界值:

技术分享

?

?

in,在某个集合之内

in (元素列表)

not in,不在某个集合内

not in (元素列表)

技术分享

留心:

再做批量操作时,in notin的出镜率很高!

?

集合(3,4,5)区间(3,4)

?

null值的判断

不能使用普通的运算符,因为运算的结果都是null,而且不能作为查询条件!

技术分享

?

技术分享

?

应该使用 is null 或者 is not null 来判断!

技术分享

?

应该使用上面的来完成判断:

技术分享

?

函数(isnull())也可以完成类似的判断:

技术分享

?

?

注意:运算符也有的优先级的概念,注意可以使用 () 来修改优先级!

技术分享

?

第四天

select 语句

group by 子句,分组查询

对查询结果(已经通过where子句过滤之后的数据),按照某个字段,进行分组!

?

group by 字段!

在分组的结果中,只会显示组内的头一条记录!因此,通常,分组之后的数据,除了分组的字段外,其他字段的逻辑含义很轻!

?

分组的作用,不在查询每个组内的具体数据。而其作用主要是在分组统计上:

?

合计函数

此时需要使用统计函数(合计函数)加以配合!

合计函数例如:count() 可以统计结果中的记录数,但是一旦使用了分组查询,则只会统计组内的数据!

技术分享

?

count(),统计记录数。典型的使用是 count(*),但是除了*之外,是可以使用字段名的!

其中,只要记录存在,则count(*)就会统计到数据,而如果相应的字段为null,则count(字段)不会统计上数据:

看下面对 gender 的统计结果:

技术分享

sum(字段表达式),统计和,对某个字段求和!

技术分享

avg(),平均值

技术分享

max(字段表达式),最大值

min(字段表达式),最小值

group_concat(字段表达式),组内连接字符串

技术分享

?

技术分享

?

?

分组排序

默认的分组后会按照分组字段对结果进行排序。可以group by子句指定排序的方式(升序ASC和降序DESC)

技术分享

?

多字段分组

使用逗号分隔开多个分组字段即可!统计时,会按照多个字段的组合分组生成结果!

例如:统计每个班级内的男生和女生的数量!

技术分享

?

如果是多字段分组,需要查看每个分组的的详细情况:

可以使用关键字with rollup关键字来回滚统计:

技术分享

?

?

having子句,条件子句

功能上与where类似,都是条件子句!

技术分享

?

主要的区别,在于执行时机:

技术分享

执行时机:

where,是开始时,从数据源中检索数据的条件。

而 having,是在筛选,分组之后,在得到的结果中,再次进行筛选的语法!

?

因此 having的结果一定是 where 已经过滤之后的结果!

技术分享

?

?

having的作用在于,对结果进行二次处理!

例如:找到平均身高高于 175cm的班级:

每个班级的平均身高:

技术分享

查询条件是 avg(height)之后的结果:

此时,where和groupby已经执行结束!可以使用 having 进行二次过滤:

技术分享

为啥要有 having:where没有办法与合计函数一起使用!原因在于执行顺序问题!

典型的应该使用别的形式为 having完成条件表达式:

?

?

技术分享

?

order by 排序子句

对结果进行排序的语句!

?

order by 字段名 [asc|desc], [字段名 [asc|desc],]

可见可按照多个字段进行排序

技术分享

原则是,先按照第一个字段进行排序,如果字段值相同,则采用第二个,以此类推!

技术分享

?

limit 子句

限制结果记录数的子句!

从所有的结果中,选择部分结果的子句!

技术分享

上面的是记录的位置:

可以从某个位置开始,取得多少条!

limit start, size;

start:起始位置

size,取得的记录数

技术分享

注意,第二个参数是,长度,而不是终止位置!

?

还有一个简写,省略start起始位置,表示从第一条记录开始:

技术分享

?

分页!

?

?

select的子句的总结

select子句的全部子句

书写顺序

字段表达式,from子句,where子句,group by子句,having子句,order by子句,limit子句。

书写顺序,与执行顺序!几乎是一样的!

执行顺序

from

where

group by

字段表达式,合计函数表达式

having

order by

limit

?

书写顺序不能错,但是子句几乎都可以省略!省略表示不发生操作!

?

?

子查询,sub-query

出现在其他语句内部的查询语句,称之为子查询

?

场景:

最高的学生

按照身高,降序,取得第一个!

技术分享

问题是出现等高的学生,问题不能处理!

?

应该,找到最高的身高,然后找到所有符合最高身高的学生!

技术分享

此时,select max()出现在另外的语句内部,称之为子查询语句!

?

注意:子查询,应该始终出现在括号内!

技术分享

?

?

子查询的分类

热门排行

今日推荐

热门手游