关系数据库,是建立在关系模型基础上的数据库,借助于集合代数等数学概念和方法来处理数据库中的数据。
存储介质分为两种:磁盘和内存
关系型数据库:存储在磁盘中
非关系型数据库:存储在内存中
典型关系型数据库
Oracle、DB2、Microsoft SQL Server、Microsoft Access、MySQL、SQLite
小型关系型数据库:Microsoft Access,SQLite
中型关系型数据库:SQL Server,Mysql
大型关系型数据库:Oracle,DB2
安全,容易理解、比较浪费
典型非关系型数据库
mongodb\redis
效率高、不安全、断电消失
关系数据库,是建立在关系模型基础上的数据库,借助于集合代数等数学概念和方法来处理数据库中的数据。现实世界中的各种实体以及实体之间的各种联系均用关系模型来表示。关系模型是由埃德加·科德于1970年首先提出的,并配合“科德十二定律”。现如今虽然对此模型有一些批评意见,但它还是数据存储的传统标准。关系模型由关系数据结构、关系操作集合、关系完整性约束三部分组成。
关系数据结构:指的数据以什么方式来存储,是一种二维表的形式存储
关系操作集合:如何来关联和管理对应的存储数据,SQL指令
(获取张三的年纪:已知条件为姓名
Select 年龄 from 二维表 where 姓名 = 张三;)
关系完整性约束:数据内部有对应的关联关系,以及数据与数据之间也有对应的关联关系
表内约束:对应的具体列只能放对应的数据(不能乱放)
表间约束:自然界各实体都是有着对应的关联关系(外键)
结构化查询语言(Structured Query Language)简称SQL,是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统;同时也是数据库脚本文件的扩展名。
SQL就是专门为关系型数据库而设计出来的。
1、 数据查询语言(DQL:Data Query Language):
其语句,也称为“数据检索语句”,用以从表中获得数据,确定数据怎样在应用程序给出。保留字SELECT是DQL(也是所有SQL)用得最多的动词,其他DQL常用的保留字有WHERE,ORDER BY,GROUP BY和HAVING。这些DQL保留字常与其他类型的SQL语句一起使用。
专门用于查询数据:代表指令为select/show
2、 数据操作语言(DML:Data Manipulation Language):
其语句包括动词INSERT,UPDATE和DELETE。它们分别用于添加,修改和删除表中的行。也称为动作查询语言。
专门用于写数据:代表指令为insert,update和delete
3、 事务处理语言(TPL):
它的语句能确保被DML语句影响的表的所有行及时得以更新。TPL语句包括BEGIN TRANSACTION,COMMIT和ROLLBACK。(不是所有的关系型数据库都提供事务安全处理)
专门用于事务安全处理:transaction
4、 数据控制语言(DCL):
它的语句通过GRANT或REVOKE获得许可,确定单个用户和用户组对数据库对象的访问。某些RDBMS可用GRANT或REVOKE控制对表单个列的访问。
专门用于权限管理:代表指令为grant和revoke
5、 数据定义语言(DDL):(Database Defination language)
其语句包括动词CREATE和DROP。在数据库中创建新表或删除表(CREAT TABLE 或 DROP TABLE);为表加入索引等。DDL包括许多与人数据库目录中获得数据有关的保留字。它也是动作查询的一部分。
专门用于结构管理:代表指令create和drop(alter)
1、 Mysql是一种开源免费的数据库产品
2、 Mysql对PHP的支持是最好(wamp或者lamp)
Mysql中用到的操作指令就是SQL指令
Mysql是一种C/S结构:客户端和服务端
通常:服务端与客户端不在同一台电脑上
2、 输入对应的服务器地址:-h:host -h[IP地址/域名]
3、 输入服务器中Mysql监听的端口: -P:port –P:3306
4、 输入用户名:-u:username -u:root
5、 输入密码:-p:password –p:root
连接认证基本语法:
(第二行输入密码)
注意事项
1、 通常端口都可以默认:mysql坚挺的端口通常都是3306(我是3307)
2、 密码的输入可以先输入-p,直接换行,然后再以密文方式输入密码
退出
断开与服务器的连接:通常Mysql提供的服务器数量有限,一旦客户端用完,建议就应该断开连接。
建议方式:使用SQL提供的指令
Exit; //exit带分号
\q; //quit缩写
Mysql服务端架构有以下几层构成:
1、数据库管理系统(最外层):DBMS,专门管理服务器端的所有内容
2、数据库(第二层):DB,专门用于存储数据的仓库(可以有很多个)
3、二维数据表(第三层):Table,专门用于存储具体实体的数据
4、字段(第四层):Field,具体存储某种类型的数据(实际存储单元)
数据库中常用的几个关键字
Row:行
Column:列(field)
TABLE层:(注意这里是圆括号)
出错原因:
快捷方式:set names 字符集
重新进行数据插入:中文(GBK)
深层原理:客户端,服务端,连接层(show variables like ‘character_set_%’)
客户端传入数据给服务端:client:character_set_client
服务端返回数据给客户端:server:character_set_results
客户端与服务端之间的连接:connection:character_set_connection
Tinyint
迷你整形,系统采用一个字节来保存的整形:一个字节 = 8位,最大能表示的数值是0-255
Smallint
小整形,系统采用两个字节来保存的整形:能表示0-65535之间
Mediumint
中整形,采用三个字节来保存数据。
Int
整形(标准整形),采用四个字节来保存数据。
Bigint
大整形,采用八个字节来保存数据。
无符号标识设定
无符号:表示存储的数据在当前字段中,没有负数(只有正数,区间为0-255)
基本语法:在类型之后加上一个 unsigned
显示长度只是代表了数据是否可以达到指定的长度,但是不会自动满足到指定长度:如果想要数据显示的时候,保持最高位(显示长度),那么还需要给字段增加一个zerofill属性才可以。
Zerofill:从左侧开始填充0(左侧不会改变数值大小),所以负数的时候就不能使用zerofill,一旦使用zerofill就相当于确定该字段为unsigned
Float又称之为单精度类型:系统提供4个字节用来存储数据,但是能表示的数据范围比整型大的多,大概是10^38;只能保证大概7个左右的精度(如果数据在7位数以内,那么基本是准确的,但是如果超过7位数,那么就是不准确的)
基本语法
Float:表示不指定小数位的浮点数
Float(M,D):表示一共存储M个有效数字,其中小数部分占D位
Float(10,2):整数部分为8位,小数部分为2位
最大的取值是<10e7;
Double又称之为双精度:系统用8个字节来存储数据,表示的范围更大,10^308次方,但是精度也只有15位左右。
定点数:能够保证数据精确的小数(小数部分可能不精确,超出长度会四舍五入),整数部分一定精确
Decimal定点数:系统自动根据存储的数据来分配存储空间,每大概9个数就会分配四个字节来进行存储,同时小数和整数部分是分开的。
Decimal(M,D):M表示总长度,最大值不能超过65,D代表小数部分长度,最长不能超过30。
时间类型:能够表示某个指定的时间,但是系统同样是提供3个字节来存储,对应的格式为:HH:ii:ss,但是mysql中的time类型能够表示时间范围要大的多,能表示从-838:59:59~838:59:59,在mysql中具体的用处是用来描述时间段。
时间戳类型:mysql中的时间戳只是表示从格林威治时间开始,但是其格式依然是:YYYY-mm-dd HH:ii:ss
年类型:占用一个字节来保存,能表示1900~2155年,但是year有两种数据插入方式:0~99和四位数的具体年
下面这个建表语句,如果分开行写会出bug,我也不知道为啥
表示我们选择d5=2069的数据,更新这行数据的d1部分为。。。
应用时候的保存:
PHP中有着非常强大的时间日期转换函数:date将时间戳转换成想要的格式,strtotime又可以将很多格式转换成对应的时间戳。PHP通常不需要数据库来帮助处理这么复杂的时间日期,所以通常配合PHP的时候,时间的保存通常使用时间戳(真正),从而用整型来保存。字符串型
在mysql中,有一项规定:mysql的记录长度(record == 行row)总长度不能超过65535个字节。
Varchar能够存储的理论值为65535个字符:字符在不同的字符集下可能占用多个字节。
计算在utf8和GBK下对应的varchar能够存储的长度
Utf8 最多只能存储21844个字符
GBK最多只能存储32766个字符
Char
定长字符:指定长度之后,系统一定会分配指定的空间用于存储数据
基本语法:char(L),L代表字符数(中文与英文字母一样),L长度为0到255
Varchar
变长字符:指定长度之后,系统会根据实际存储的数据来计算长度,分配合适的长度(数据没有超出长度)
基本语法:Varchar(L),L代表字符数,L的长度理论值位0到65535
Text
文本类型:本质上mysql提供了两种文本类型
Text:存储普通的字符文本
Blob:存储二进制文本(图片,文件),一般都不会使用blob来存储文件本身,通常是使用一个链接来指向对应的文件本身。
Text:系统中提供的四种text
Tinytext:系统使用一个字节来保存,实际能够存储的数据为:2 ^ 8 + 1
Text:使用两个字节保存,实际存储为:2 ^ 16 + 2
Mediumtext:使用三个字节保存,实际存储为:2 ^ 24 + 3
Longtext:使用四个字节保存,实际存储为:2 ^ 32 + 4
系统提供了1到2个字节来存储枚举数据:通过计算enum列举的具体值来选择实际的存储空间:如果数据值列表在255个以内,那么一个字节就够,如果超过255但是小于65535,那么系统采用两个字节保存。
错误数据:enum有规范数据的功能,能够保证插入的数据必须是设定的范围,其他类型都不可以
枚举enum的存储原理:实际上字段上所存储的值并不是真正的字符串,而是字符串对应的下标:当系统设定枚举类型的时候,会给枚举中每个元素定义一个下标,这个下标规则从1开始Enum(1=>‘男’,2=>’女’,3=>’保密’)
枚举的意义:
1、 规范数据本身,限定只能插入规定的数据项
2、 节省存储空间
集合:是一种将多个数据选项可以同时保存的数据类型,本质是将指定的项按照对应的二进制位来进行控制:1表示该选项被选中,0表示该选项没有被选中。
基本语法:set(‘值1’,’值2’,’值3’…)
系统为set提供了多个字节进行保存,但是系统会自动计算来选择具体的存储单元
1个字节:set只能有8个选项
2个字节:set只能有16个选项
3个字节:set只能表示24个选项
8个字节:set可以表示64个选项
Set和enum一样,最终存储到数据字段中的依然是数字而不是真实的字符串
值得注意的是:
数据在存储的时候,如果被选中,那么对应的位的值就为1,否则为0
系统在进行存储的时候会自动将得到的最终的二进制颠倒过来,然后再进行转换成十进制存储
Default:默认值,当字段被设计的时候,如果允许默认条件下,用户不进行数据的插入,那么就可以使用事先准备好的数据来填充:通常填充的是NULL
下面这里表示的是age 这个属性的默认值为18
列描述:comment,是专门用于给开发人员进行维护的一个注释说明
基本语法:comment ‘字段描述’;
查看Comment:必须通过查看表创建语句
用这个查看备注:show create table my_comment;
1、 查看自增长:自增长一旦触发使用之后,会自动的在表选项中增加一个选项(一张表最多只能拥有一个自增长)
1、 一张表只有一个自增长:自增长会上升到表选项中
2、 如果数据插入中没有触发自增长(给定了数据),那么自增长不会表现
创建唯一键与创建主键非常类似
1、 直接在表字段之后增加唯一键标识符:unique[ key]
2、 在所有的字段之后使用unique key(字段列表);
3、 在创建完表之后也可以增加唯一键alter table 表名 add unique key(字段列表);
一个表中允许存在多个唯一键:假设命令为主键一样:alter table 表名 drop unique key;//错误的
Index关键字:索引,唯一键是索引一种(提升查询效率)
删除的基本语法:alter table 表名 drop index 唯一键名字;
表关系:表与表之间(实体)有什么样的关系,每种关系应该如何设计表结构。
一对一
一对多
多对多
【多对多:一张表中的一条记录在另外一张表中可以匹配到多条记录,反过来也一样。
多对多的关系如果按照多对一的关系维护:就会出现一个字段中有多个其他表的主键,在访问的时候就会带来不便。
既然通过两张表自己增加字段解决不了问题,那么就通过第三张表来解决。】
多对多解决方案;增加一个中间表,让中间表与对应的其他表形成两个多对一的关系:多对一的解决方案是在“多”表中增加“一”表对应的主键字段。
追加主键
一个表只能有一个主键
(报错:ERROR 1068 (42000): Multiple primary key defined)
主键的属性只能有一个,insert一样的会报错
主键冲突解决办法:
1、 主键冲突更新:
类似插入数据语法,如果插入的过程中主键冲突,那么采用更新方法。
Insert into 表名 [(字段列表)] values(值列表) on duplicate key update 字段 = 新值;
(insert into my_pril values('小婷','itcast0001') on duplicate key update name = '小婷';)
2、 主键冲突更新:
当主键冲突之后,干掉原来的数据,重新插入进去。
Replace into [(字段列表)] values(值列表);
( replace into my_pril values('包包','itcast0004');)
3、更新数据
(update my_pril set name = '小包子' where name = '包包' limit 4;)
4、删除数据
delete from my_pril;
truncate my_pril;(建表信息都没有了)
5、业务逻辑主键,用来保证主键的独立性
SELECT col FROM tablename LIMIT 3, 5; 表示检索出查询结果中从行 3 开始的 5 行。(注意:行号从 0 开始,行 1 表示第二行)
SELECT col1, col2, col3 FROM tablename ORDER BY col1, col2;
首先按 col1 进行排序,如果 col1 的值相同,再按 col2 进行排序。如果 col1 的值不同,则不会按 col2 进行排序。
SELECT col1, col2, col3 FROM tablename ORDER BY col1 DESC, col2; // 表示按 col1 降序排序,再按照 col2 排序。如果要对多个列都降序排序,则需要对每一列都指定关键字 DESC。
1) AND
如果需要使用多个列一起过滤才能查询出要查询的结果,可以使用 AND 进行连接。
select * from student where stu_name="test13" and stu_id=26;
2)OR
与 AND 相反,只要匹配任一条件就可以。
select * from student where stu_id=26 or stu_id=27;
搜索学生姓名以 test 开头的学生信息
SELECT * FROM student WHERE stu_name="test%";
搜索学生姓名以 41 结尾的学生信息
SELECT * FROM student WHERE stu_name="%41";
搜索学生姓名包含 test 的学生信息
SELECT * FROM student WHERE stu_name="%test%";
查询学生表中学生姓名包含 13 的所有行:
SELECT *FROM student WHERE stu_name REGEXP '13';
REGEXP 和 LIKE 的一个重要区别:
如果使用上面的语句,关键字替换为 LIKE,那么不会返回数据。
如查询学生表中学生姓名包含 13 或 41 的所有行:
SELECT *FROM student WHERE stu_name REGEXP '13|41';
查询时要在一个字段中 stu_id、stu_name,中间用 '# ' 连接,mysql 语句:
SELECT CONCAT(stu_id, '# ', stu_name) FROM student;
输出结果:
去除空格:
如果要去除数据中的空格,可以使用 Trim() 函数。Trim() 去除左右两边的空格,Rtrim() 去除右边的空格,Ltrim() 去除左边的空格。
SELECT CONCAT(Rtrim(stu_id), '# ', stu_name) FROM student;
对检索出的数据进行算术计算,如加减乘除。
例如:要对 stu_id 的值都加1
SELECT stu_id + 1 AS stu_id FROM student;
完整的查询指令:
Select select选项 字段列表 from 数据源 where条件 group by分组 having条件 order by排序 limit限制;
去重: select distinct * from table;
两个表的笛卡尔: select * from table1,table2;
结果:两张表的记录数相乘,字段数拼接
本质:从第一张表取出一条记录,去拼凑第二张表的所有记录,保留所有结果。得到的结果在数学上有一个专业的说法:笛卡尔积,这个结果出了给数据库造成压力,没有其他意义:应该尽量避免出现笛卡尔积。
数据获取原理:针对表去对应的磁盘处获取所有的记录(一条条),where的作用就是在拿到一条结果就开始进行判断,判断是否符合条件:如果符合就保存下来,如果不符合直接舍弃(不放到内存中)
Where是通过运算符进行结果比较来判断数据。
Group by是为了分组后进行数据统计的,如果只是想看数据显示,那么group by没什么含义:group by将数据按照指定的字段分组之后,只会保留每组的第一条记录。
(每个班级就显示一个人出来;
(聚合函数的应用,可以统计每个班的情况
将数据按照某个字段进行分组之后,对已经分组的数据进行再次分组
基本语法:group by 字段1,字段2; //先按照字段1进行排序,之后将结果再按照字段2进行排序,以此类推。
默认是升序,但是后面加desc就是倒序:
统计每个分组的总和
当分组进行多分组之后,往上统计的过程中,需要进行层层上报,将这种层层上报统计的过程称之为回溯统计:每一次分组向上统计的过程都会产生一次新的统计数据,而且当前数据对应的分组字段为NULL。
基本语法:group by 字段 [asc|desc] with rollup;
同时注意这里的count是对每个班级的综合统计
Having在group by分组之后,可以使用聚合函数或者字段别名(where是从表中取出数据,别名是在数据进入到内存之后才有的)
强调:having是在group by之后,where是在group by之前:where的时候表示将数据从磁盘拿到内存,where之后的所有操作都是内存操作。
Order by排序:根据校对规则对数据进行排序
select * from table order by column11 desc ;(倒叙,去掉desc默认升序
select * from table order by column1 desc column2;(按照列1 倒叙,然后再对列2升序
Limit 0,2; 表示获取前两条记录
select * from table limit 0,2 (表示选择表0,1行
select * from table where student_score between 20 and 30;
select * from table where student_score>=20 and student_score<=30;
比较运算符
>、>=、<、<=、=、<>
通常是用来在条件中进行限定结果
=:在mysql中,没有对应的 ==比较符号,就是使用=来进行相等判断
<=>:相等比较 返回的是bool值
(注意这里,两边都是转化成int,再来比较的
查询数据表里面是否有空的(好用的方法)
匹配模式中,有两种占位符:
_:匹配对应的单个字符
%:匹配多个字符
Select 语句
Union [union 选项]
Select 语句;
Union选项:与select选项基本一样
Distinct:去重,去掉完全重复的数据(默认的)
在联合查询中,如果要使用order by,那么对应的select语句必须使用括号括起来
(注意union上下的列名要对应起来,表才是可以看起来连的)
内连接:inner join,从一张表中取出所有的记录去另外一张表中匹配:利用匹配条件进行匹配,成功了则保留,失败了放弃。
基本语法:表1 [inner] join 表2 on 匹配条件;
因为表的设计通常容易产生同名字段,尤其是ID,所以为了避免重名出现错误,通常使用表名.字段名,来确保唯一性
内连接使用where 也是一样的 (不用on
另外可以起别名:
外链接:outer join,按照某一张表作为主表(表中所有记录在最后都会保留),根据条件去连接另外一张表,从而得到目标数据。
外连接分为两种:左外连接(left join),右外连接(right join)