数据库(1)
目录
1. 内存和外存的区别?
内存:容量小、造价高、速度快、断电数据丢失
外存:容量大、造价低、速度慢、断电数据不丢失,写入即永久保存
2. 常见的关系型数据库:
ACCESS:微软的OFFICE中集成的一个小型数据库,以前在网站刚开始流行的时候,用户量非常小的网站上使用,现在基本没人用
SQLite:小型数据库,常用于手机APP,桌面程序,处理简单的数据存储
SQL Server:微软推出的一个专业级的数据库,是微软推出的真正意义上的大型数据库
MySQL:使用最多的数据库,开源的,免费的
PostgreSQL:效率比MySQL高
Oracle:业内最强的数据库,收费的,用于大型公司
3. 常见的非关系型数据库:
Redis:内存级别的数据库,也可以把数据持久化到磁盘,但是内存数据库的功能非常强
MongoDB:文档数据库
4. 数据库与数据结构有什么关系?
答:数据结构是组织数据的一种方式。数据库用到了一些合适的数据结构把数据组织并保存起来。主要的作用就是管理数据。
数据库把数据保存在磁盘中,就可以完成对数据的持久化,每次程序重新加载数据就可以从数据库中读取以前的数据,基于这样的特性,数据就不会丢失了。
对于客户端与服务器之间的交互模型,我们称之为C/S架构
客户端与服务器之间是通过网络进行交互的,本机的客户端访问本机的数据库服务也是CS架构。
虽然我们访问的是本机的服务,但是还是通过网络访问的,只不过客户端与服务器在同一台电脑上而已。每台电脑都有一个环回网卡,本地有一个固定的IP,127.0.0.1 这个IP代表的就是本机,无论本机是否有网络,这个IP始终访问的是本机地址。
关系型数据库是指采用了关系模型来组织数据的数据库,关系模型就是二维表格模型。
关系型数据库就是由二维表及其它们之间的联系所组成的一个数据组织。
SQL是针对数据库操作的语言,是介于关系代数和关系演算之间的语言,充分体现了关系数据库语言的特性和优点。SQL包含了DDL、DCL和DML。
每个应用程序只要有数据产生,都有与之对应的数据库。
关系模型的完整性规则是对关系的某种约束,分为实体完整性、参照完整性约束和用户定义完整性。
关系数据库中,关系也称为表,元组也称为行,属性也称为列。(注意:关系不是数据库!)
5. SQL分类
- DDL(data definition language)数据定义语言,用来维护存储数据的结构。代表指令:create,drop,alter
- DML(data manipulation language)数据操纵语言,用来对数据进行操作。代表指令:insert,delete,update
DML中又单独分了一个DQL,数据查询语言,代表指令:select
- DCL(data control language)数据控制语言,主要负责权限管理和事务。代表指令:grant,revoke,commit
6. 数据库的基本操作
mysql -uroot -p;——使用客户端工具连接数据库服务器
show databases;——查看当前服务器所有的数据库
红色标记的是MySQL自带的数据库,记录的是一些关于MySQL自身的配置、性能、系统变量信息,不能改动,也不能删除。若删除则无法启动。
ctrl+C可以重新另起一行(^C)
show warnings;——查看警告信息
show variables like '%character%';——查看当前数据库服务默认的编码集
select database();——查看当前选择了哪个数据库
7. 创建数据库
CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name
[create_specification] ...
create_specification: [DEFAULT] {
CHARACTER SET [=] charset_name
| COLLATE [=] collation_name
| ENCRYPTION [=] {'Y' | 'N'}
}
高亮的表示mysql中的关键字;大括号表示必须要有这个关键字,里面的 | 是或的意思,即database和schema必须写一个,它们都表示数据库;中括号表示可有可无,即可选项,当前这里写的if not exists表示如果不存在则创建数据库;这些规则在MYSQL文档中都是通用的,在编程界大多数的语法描述也是这套规则。
1. 先看当前是否存在将要创建的数据库 show databases;
2. 根据语法规则创建数据库 create database java113; 或者 CREATE DATABASE java113;(大小写不敏感)
3. 检查是否创建成功 show databases;
当再次执行相同的SQL时,虽然执行成功,但是报出一个警告,数据库已存在。
如果不加if not exists就直接报错
建议创建数据库时指定编码集和排序规则。
character set:8.0中默认的字符集是utf8mb4;5.7中默认的字符集是latin1(不能存储中文).
collate:8.0以后默认是utf8mb4_0900_ai_ci;5.7中默认是utf8mb4_general_ci
创建一个名为test_db的数据库,并指定字符集和排序规则:
如果创建一个名为create或database的数据库,是否可以?答:不可以!
不可以是关键字!
MySQL中允许开发者使用关键字命名,但是在使用的时候要用反引号 ` 把关键字引起来
查看当前使用的是哪个数据库:
8. 删除数据库
删除数据库一定要慎之又慎
恢复数据库的方法:通过日志来处理。
MySQL在执行的过程中只要对数据库进行修改操作,都会把这些操作内容记录在日志中,如果误删了数据库,可以通过日志快速的把日志中记录的所有操作再执行一遍,完成恢复。
退出:
9. 数值类型:
float和double类型,在表示小数的时候都不是特别精准,所以用decimal类型表示小数。在有些系统中表示金额,一般把元为单位换成以分为单位,然后用int类型表示金额。
DECIMAL(M,D)中的M表示有效数字的长度,D表示小数部分的长度。M最大为65,D最大为30
如果省略D,则默认为0;如果省略M,则默认为10
数值类型可以指定为无符号(unsigned),表示不取负数。
10. 字符串类型
char(n) 和 varchar(n) 中括号中 n 代表字符的个数,并不代表字节个数,比如 CHAR(30) 就可以存储 30 个字符。
utf8mb4编码集,一个符最多占4个字节,根据字符的具体情况用1~4个字节表示一个字符。
在utf8mb4编码集的情况下,一个varchar字段最多可以存放65535/4≈16383个字符。
11. 日期类型
MySQL :: MySQL 8.4 Reference Manual :: 13.2.1 Date and Time Data Type Syntax
12. 表的操作
操作数据库中的表时,要先使用该数据库:
12.1 创建表
drop table if exists table_name;(创建表之前先确认该表是否存在)
举例:
注意:varchar长度要指定!每张表都要设计一个编号字段,数据类型为bigint.
12.2 查看表结构
12.3 删除表
一条drop语句可以删除多个表,每个表之间用逗号隔开。
13. MySQl表的增删改查
CRUD - 增删改查
C - Create 新增
R - Retrieve 检索,查询
U - Update 更新
D - Delete 删除
13.1 新增(Create)
insert into 表名 [字段1,字段2] values (值,值,值);
没有指定id,用null代替:
多行插入:
insert into 表名 [(指定列...)] values (值[,值...]) [,(值[,值...])] [,(值[,值...])]...
一次插入一条数据和一次插入多条数据哪个效率高?
1. 执行所有的SQL时都有网络开销
2. 写入数据时还有磁盘IO的开销
3. 每执行一条SQL语句都会开启一个事务,事物的开启和关闭都需要消耗系统资源
答:一次提交多条数据(在一个可控范围内),比一次提交一条数据效率高一些。
13.2 查询(Retrieve)
报错出现乱码,首先考虑数据库的编码集设置是否正确。如果是编码集的问题,那么要把原来的库删了,重新创建库并指定正确的编码集。
13.2.1 全列查询:
select * from 表名;*号表示的是要查询表中所有的列。
这是非常危险的操作,因为在生产环境中,一个表中的数据量可能会很多很多,有可能达到TB级,当一个查询开始的时候,磁盘开销,网络开销(都是非常紧缺的资源),如果这条语句开始执行,那么就有可能把服务器资源吃光,其他的程序或者数据库操作就要等待当前SQL执行完之后才能继续执行。(不加任何限制的查询在生产环境不要使用)
13.2.2 指定列查询:
select 列名[,列名]... from 表名;
图中的10,数值类型,效果就是让所有的列中都包含一个表达式中的值,它本身并不在我们的真实的表里。
13.2.3 表达式查询:
把所有人的语文成绩在原来的基础上+10分:
列与列之间也可以参与运算:可以之间相加chinese+math+english。也可以chinese+math+english (as) total from exam;
我们的表里本来没有total这一列,所以通过表达式查询出来的结果集是通过一个临时表返回给我们的,执行完之后临时表就删除了。
13.2.4 去重查询:DISTINCT
使用DISTINCT关键字对某列数据进行去重:
语法:select distinct 列名 from 表名;
在查询结果中,每一列都相同,MySQL才认为他们是重复数据。
13.2.5 排序:ORDER BY
升序:ASC;降序:DESC
查看表结构用到了desc describe 描述;排序中desc descend 下降。在MySQL中一个关键字,表示了两种意思,这是一个反面案例。
语法:select 列名 from 表名 order by 列名 [ASC | DESC];(默认升序)
指定了排序的列,返回的结果就是针对这个列进行排序后的结果集。
NULL数据排序,视为比任何值都小,升序出现在最上面,降序出现在最下面。
排序的时候可以使用别名:
select id,name,chinese+math+english as total from exam order by total asc;
MySQL中NULL比较特殊:
1. 不论和什么值进行运算,返回的值都是NULL
2. NULL始终被判定为FALSE
3. NULL的值不是我们以前学习过的其他编程语言中的0,在MySQL中就是NULL
13.2.6 条件查询:WHERE
根据指定条件过滤不符合的记录,把符合的记录返回给用户。
比较运算符:
注意:在其他的编程语言中判断相等用的是==号,在MySQL中用的是=号,赋值也是用的=号。但是NULL不安全,例如NULL=NULL的结果是NULL。
<=> 等于,NULL安全,例如NULL <=> NULL的结果是TRUE(1) 专门针对于NULL来做判断。
ctrl+R执行SQL
!=,<>都表示不等于
BETWEEN a0 AND a1:范围匹配,[a0,a1],如果a0<=value<=a1,返回TRUE(1)
IN (option,...)如果是option(列表、集合)中的任意一个,返回TRUE(1)
LIKE:模糊匹配,%表示任意多个(包括0个)任意字符;_表示任意一个字符。有几个_就必须匹配几个字符。注意要用单引号引起来。
show variables like '%character%';
注:WHERE条件可以使用表达式,但不能使用别名。
使用where条件的语法:select * from 表名 where 列名/表达式 运算符 条件;
出现这种现象是和MySQL内部的实现有关,换句话说就是和MySQL执行SQL语句的顺序有关:
1. 如果要在数据中查某些数据,首先要确定表,先执行from
2. 在查询的过程中要根据指定的查询条件把符合条件的数据过滤出来,这时执行的就是where子句(此时total还没有被定义)
3. 执行select后面的指定的列,这些列是需要加入到最终的结果集中
4. 排序操作,根据order by子句中指定的列名和排序规则进行最后的排序
13.2.7 分页查询LIMIT
作用:限制查询结果集中的条数
通过分页查询可以有效的控制一次查询出来的结果集中的记录的条数,可以有效地减少数据库服务器的压力,对用户较友好。
语法:
从0开始,筛选n条结果:
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT n;
从s开始,筛选n条结果:
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT s,n;
从s开始,筛选n条结果,比第二种用法更明确,建议使用:
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT n OFFSET s;
如果起始位置超出整个结果集的范围,可以执行,但是返回空结果集。
13.3 修改(Update)
语法:
UPDATE table_name SET column = expr [, column = expr ...]
[WHERE ...] [ORDER BY ...] [LIMIT ...]
如果匹配到了多条,只修改不符合的数据。如果都不符合,那么全部修改。
不加where条件的时候,修改的就是整张表中所有的记录,谨慎操作!
比如:要给总分排名倒数3名的同学的数学成绩减去30分:
update exam set math=math-30 where math is not null order by (chinese+math+english) asc limit 3;
注意:math=math-30不能写成math -= 30;
13.4 删除(Delete)
语法:
DELETE FROM table_name [WHERE ...] [ORDER BY ...] [LIMIT ...]
总结一下增删改查的语法要点:
新增:insert into 表名
查询:select 列名 from 表名
修改:update 表名
删除:delete from 表名
同样的,获取长度:
数组:array.length;
集合:list.size();
字符串:str.length();
14. 数据库约束
是关系型数据库的一个重要功能
主要作用是保证数据的完整性,也可理解为数据的正确性(数据本身是否正确,关联关系是否正确)
- NOT NULL - 指示某列不能存储NULL值,为必填项
- UNIQUE - 保证某列的每行必须有唯一的值,是唯一的,但是NULL可以重复插入
- DEFAULT - 规定没有给列赋值时的默认值
- PRIMARY KEY - NOT NULL 和 UNIQUE 的结合(非空且唯一)。确保某列(或两个列多个列的结合)有唯一标识,有助于更快速地找到表中的一个特定的记录。可以用bigint类型为表单独指定主键,同时也可以指定主键自增,用auto_increment关键字。自增操作时,会找到当前列中最大的值,然后在这个基础上+1
如果写入记录的时候报错(主外键约束、语法),insert操作时都会先生成一个主键值,且主键编号不回退。不论记录写入成功与否,这个主键都会视为已使用,从而造成主键值不连续。
当设置了自增主键之后,即使写入null,也可以成功插入数据,数据库帮我们处理这个值(自增):
一个表不允许有两个主键,但是一个主键可以包含多个列(复合主键):
复合主键的应用场景:名字相同,学号不同的学生的成绩,可以插入到数据库中(是不相同的)。
- FOREIGN KEY - 保证一个表中的数据匹配另一个表中的值的参照完整性
外键约束,一张表要与另一张表的主键或唯一键进行关联,说明表与表之间的关联关系。
表中某个列的值,必须是另一张表的主键列,或是唯一约束列的值,也就是当前表中的值在另一张表中必须存在,且满足主键或唯一约束。本质上也是一个校验的过程。
没有设置外键,创建两个表:
create table class(
id bigint primary key auto_increment,
name varchar(50)
);
create table student(
id bigint primary key auto_increment,
name varchar(50) not null,
class_id bigint
);
insert into class(name) values ('java113'),('java112'),('java111'),('java110');
insert into student (name,class_id) values ('Tom',1),('Kang',2),('Wang',3),('Amy',2);
查询结果:
写入一条学生记录,设置了不存在的班级编号,数据是可以写入的:
insert into student (name,class_id) values ('Qing',5);
外键用于关联其他表的主键或唯一键,语法:
foreign key (字段名) reference 主表(列);
建立外键之后,再写入不存在的班级编号:(报错)
通过外键约束,保证数据的完整性和关系的正确性
当子表中存在对主表的依赖的时候,如果子表中存在数据,那么删除主表中的记录的时候,会出现报错:
需要先删除子表中的数据,再删除主表中的数据:
—— >
- CHECK - 保证列中的值符合指定的条件。对于MySQL数据库,对CHECK子句进行分析,但是忽略CHECK子句
创建表:
MySQL8.0之后是生效的,MySQL5.7中不生效:
总结:
15. 表的设计
- 从需求中获取类,类对应到数据库中的实体,实体在数据库中表现为一张一张的表,类中的属性就对应着表中的字段(列)
- 确定类与类之间的关系
- 使用SQL去创建具体的表
设计表的时候会遵守一些规则,我们称之为三大范式
范式描述的是数据关系的模型,一对一关系,一对多关系,多对多关系
分类:第一范式1NF,第二范式2NF,第三范式3NF,BC范式BCNF
15.1 第一范式
关系型数据库最基本的要求:满足第一范式【表中的字段不可再分(属性不可再分)】
在定义表的时候,如果每一个字段都可以用一个数据类型表示,那么这个表就天然满足第一范式
15.2 第二范式
在满足第一范式的基础上,不存在非关键字段(非主键字段)对任意候选键(主键、外键、没有主键时的唯一键)的部分函数依赖(对于由两个或多个关键字段决定一条记录的情况,如果一行记录中有些字段只与关键字段中的一个有关系,那么就称这种只存在部分函数依赖)(存在于复合主键的情况下)
一个表中不能存在两个主键,但是一个主键可以包含多个列(复合主键)
对于由两个或多个关键字决定一条记录的情况,不满足第二范式
不满足第二范式可能会出现的问题:
- 数据冗余,有些字段重复出现。例如,一个选课关系表如果不满足第二范式,会出现同一门课程由n个学生选修,“学分”就重复n-1次;同一个学生选修了m门课程,姓名和年龄就重复了m-1次的情况
- 更新异常,如果要调整一个字段,那么就需要更新所有有关记录,如果某些更新失败,会造成数据表中同一门课不同学分的情况,表现为数据不一致
- 插入异常
- 删除异常,如果要删除会删除全部字段
如果一个表中的键只有一列时,这种设计天然满足第二范式
15.3 第三范式
在第二范式的基础上,不存在非关键字段(非主键)对候选键的传递依赖(两个强相关关系存在传递现象)
第三范式可以解决数据冗余,更新异常,插入异常,删除异常的问题
多对多关系:
一个学生可以选修多门课程,一门课程也可以被多名学生选修。
- 分别创建实体表(class表,course表,student表,score表)
- 创建关系表,在关系表中为实体之间创建关联关系(student_course表)
通过关系表可以把学生选修的课程清楚地记录下来,这种设计同时满足了第二范式的要求,修改学生表中的信息不会影响到关系表
16. 新增
插入查询结果
新建一张表,把旧表中指定列的数据导入到新表
语法:
insert into table_name(目标表) [ (column [, column ...] ) ] select (从旧表中查询出来的列)...
17. 查询
17.1 聚合查询
17.1.1 聚合函数
聚合查询本质上是针对数据表中的行和行进行运算
MySQL内置的函数:(这些操作都是针对某一列进行操作)
count ( [ distinct ] expr ) 返回查询到的数据的数量(统计记录的行数)
count(列名),如果说列中有NULL值,则不会统计在内;count(*),如果有NULL值会被统计
sum ( [ distinct ] expr ) 返回查询到的数据的总和,不是数字没有意义
把查询结果中所有行中的指定列进行相加
注意:列的数据类型必须是数值型,不能是其他类型
此处的sum(chinese)为临时表,不受上面定义的字段长度约束:
在sum()求和时,NULL不参与运算,默认为0(函数内部处理):
对非数值类型的列进行运算,会得到一些警告信息:
avg ( [ distinct ] expr ) 返回查询到的数据的平均值,不是数字没有意义
对所有行的指定列进行求平均值运算
min ( [ distinct ] expr ) 返回查询到的数据的最小值,不是数字没有意义
max ( [ distinct ] expr ) 返回查询到的数据的最大值,不是数字没有意义
可以同时使用多个聚合函数,并使用别名:
之前的表达式查询,是对一行记录中的列和列之间进行计算(比如:语文成绩+数学成绩+英语成绩)
17.1.2 GROUP BY子句
select 中使用group by 子句可以对指定列进行分组查询。需要满足:使用group by 进行分组查询时,select 指定的字段必须是“分组依赖字段”(要对哪个列进行分组),其他字段若想出现在select 中必须包含在聚合函数中。
分组查询语法:
select column1,sum(column2), .. from table group by column1,column3;
先分组再计算
round (数值,小数点位数):
having可以把这个结果集中的数据进行过滤操作,平均工资这些数据并不是表中的真正记录,而是通过聚合函数计算得出:
group by 之后可以跟order by 子句:
17.1.3 HAVING
HAVING是从分组结果中筛选数据的(行),而不是筛选列的
group by子句进行分组以后,需要对分组结果进行条件过滤,不能使用where语句,而使用having
where 是对表中每一行的真实数据进行过滤的;having 是对group by 之后计算出来的结果进行过滤的
where 用在from 表名 之后,也就是分组之前;having跟在group by 子句之后。
如果需求要对真实数据进行过滤,同时也要对分组的结果进行过滤,那么在合适的位置写 where和having即可。
显示平均工资低于1500的角色和他的平均工资:
17.2 联合查询
联合查询也叫表连接查询
- 首先确定哪几张表要参与查询,对目标表取笛卡尔积(全排列)
- 根据表与表之间的主外键关系,确定过滤条件
- 精减查询字段,得到想要结果
实际开发中数据往往来自不同的表,需要联合多个表进行查询
语法:select * from 表名,表名;
设计数据时把表进行拆分,为了消除表中字段的依赖关系,比如部分函数依赖,传递依赖
两张表取笛卡尔积之后,形成联合表,其中有很多无效数据,class_id相等时为有效数据。
过滤掉无效数据:
通过连接条件过滤掉无效数据。两个表之间有主外键关系,只需要判断两个表中主外键字段是否相等即可。
可以通过表名.列名的方式来解决这个问题:
通过指定列查询,来精减结果集:
查询列表中,通过表名.列名的方式指定要查询的字段
通过给表名起别名的方式来简化SQL语句:
1. 内连接:
select * from 表名,表名;
select 字段 from 表1 别名1 [inner] join 表2 别名2 on 连接条件 and 其他条件;
(join两边是参与查询的表,on后面是连接条件)
select 字段 from 表1 别名1,表2 别名2 where 连接条件 and 其他条件;
2. 外连接:
外连接分为左外连接和右外连接。如果联合查询,左侧的表完全显示就是左外连接,右侧的表完全显示就是右外连接
主要应用在两张表数据不一致的场景里
select * from student st left join score sc on st.student_id=sc.student_id where sc.score_id is null;//左外连接
MySQL中不支持全外连接 FULL JOIN
3. 自连接:
在一行中进行列与列之间的比较
可以把行转化为列,查询的时候可以使用where条件进行过滤
select
stu.*,s1.score java,s2.score 计算机原理
from
score s1
join score s2 on s1.student_id=s2.student_id
join student stu on s1.student_id=stu.id
join course c1 on s1.course_id=c1.id
join course c2 on s2.course_id=c2.id
and s1.score<s2.score
and c1.name='java'
and c2.name='计算机原理';
4. 子查询
也叫嵌套查询
子查询是把一条SQL查询结果,当作另一条SQL的查询条件,可以嵌套很多层
内层查询的结果作为外层查询的条件,把多条语句合并为一条执行
可无限嵌套,层数过多会影响效率
语法:select * from table1 where table1.id=(select id from table2 where name=...);
单行子查询:返回一行记录的子查询: (返回一个对象)
select * from student where class_id=(select class_id from student where name='不想毕业');//外层条件的列与内层查询列表中的列要匹配
多行子查询:返回多行记录的子查询: (返回一个集合,集合中包含多个对象)
语法:select * from table1 where table1.id in (select id from table2 where xxx=...);
5. [not] exists关键字
语法:select * from 表名 where exists (select * from 表名1);
//exists后面括号中的查询语句,如果有结果返回,则执行外层的查询;
//如果返回一个空结果集,则不执行外层的查询。
返回的结果集非空,只不过列名为null,值为null
真实表和临时表进行联合查询:
select * from score sc,
(select avg(sc.score) score from score sc,student st,class c
where c.class_id=st.class_id
and st.student_id=sc.student_id
and c.name='中文系2019级3班') tmp
where sc.score>tmp.score;
6. 合并查询
作用:合并多个查询结果到一个结果集中
注意:合并查询时多个查询的查询列表必须匹配,MySQL不对结果进行校验,需注意
错误演示:
union, union all
复制表结构:create table student2 like student;
- union:该操作符用于取得两个结果集的并集,当使用该操作符时,会自动去掉结果集中的重复行(去重)
- union all:该操作符用于取得两个结果集的并集,当使用该操作符时,不会自动去掉结果集中的重复行(不去重)
18. 总结
客户端和数据库操作:
- 登录 mysql -uroot -p
- 查看当前的数据库版本 select version();
- 显示所有数据库 show databases;
- 创建数据库 create [if not exists] database 数据库名 character set 字符编码集 collate 排序规则;
- 选择数据库 use 数据库名
- 查看当前数据库 select database();
- 删除数据库 drop [if exists] database 数据库名;//危险操作
- 查看警告信息 show warnings;
- 退出 quit/exit
表操作:
- 查看当前数据库中有哪些表 show tables;
- 创建一张新表 create table 表名(列名/字段名 数据类型[,列名/字段名 数据类型]...);
- 查看表结构 desc 表名;
- 删除表 drop 表名;//危险操作
CRUD增删改查:
1. 新增-插入
insert into 表名 [(列名[,列名]...)] values (值[,值]...);//值与列名一一对应,不指定列名,值的顺序与个数和表中所有的列一一对应
2. 查询
- 全列查询 select * from 表名;//查询所有列
- 指定列查询 select 列名[,列名]... from 表名;//推荐使用
- 列为表达式的查询 select 列名/表达式 from 表名;
- 别名查询 select 列名/表达式 [as] 别名 from 表名;//别名中如果包含空格,需要用单引号引出
- 去重查询 select distinct 列名[,列名]... from 表名;
- 排序 select 列名[,列名]... from 表名 order by 列名 asc|desc;
- 条件查询 select 列名[,列名]... from 表名 where 列名/表达式 比较/逻辑运算符 order by 列名 asc|desc;
- 区间查询 where 列名 between 开始条件 and 结束条件;//等价于 开始条件<=列的值<=结束条件
- 模糊查询 select * from 表名 where 列名 like '%值_';//%匹配任意字符 _匹配单个字符
- 分页查询 select * from 表名 where 条件 order by 列名 asc|desc limit num;//查询前num条记录 select * from 表名 where 条件 order by 列名 asc|desc limit start num;//从第start条开始,向后查num条 select * from 表名 where 条件 order by 列名 asc|desc limit num offset start;//从第start条开始,向后查num条
3. 更新
update 表名 set 列名=值 where 条件 order by 子句 limit num;//如果不指定条件和limit的数量就会更新整表
4. 删除
delete from 表名 where 条件 order by 子句 limit num;//如果不指定条件和limit的数量就会删除整表
select distinct id,name,avg(age) from student where class_id=1 join class on student.class_id=class.id group by student.id having avg(age)>0 order by student.id asc limit 100;
一条SQL语句中,各部分的执行顺序:
from->join on->where->group by->having->select->distinct->order by->limit
19. 视图
视图是一个虚拟的表,基于一个或多个基础表或其他视图的查询的结果集,视图本身不存储数据,通过执行查询来动态生成数据
用户可以像操作普通表一样使用视图进行查询、更新和管理
视图本身不占用物理存储空间,它仅仅是一个查询的逻辑表示,物理上它依赖于基础表中的数据
语法:
create view view_name [(column_list)] as select_statement
为了不报错(因为列重复),可以给重复的列名起一个别名用来区别彼此:
create view v_student_score as(
select s.student_id,
s.name as student_name,
cls.class_id,
cls.name as class_name,
c.course_id,
c.name (as) course_name,
sc.score
from student s,class cls,course c,score sc
where s.class_id=cls.class_id
and sc.student_id=s.student_id
and sc.course_id=c.course_id
order by s.student_id
);
可以通过show create view v_student_score;来查看创建视图的语句
使用视图:select * from v_student_score;
可以指定列来创建视图(不用给重复列起别名):
指定列名之后,视图会根据指定的列名创建,查询结果集中是否重名不重要
create view v_student_score (
id,name,class_id,class_name,course_id,cource_name,score
) as (
select s.student_id,
s.name,
cls.class_id,
cls.name,
c.course_id,
c.name,
sc.score
from student s,class cls,course c,score sc
where s.class_id=cls.class_id
and sc.student_id=s.student_id
and sc.course_id=c.course_id
order by s.student_id
);
注意:修改真实表会影响视图,修改视图也会影响表!创建视图时使用order by不允许更新!
删除视图:drop view view_name;
视图的优点:
- 简单性:视图可以将复杂的查询封装成一个简单的查询。例如,针对一个复杂的多表连接查询,可以创建一个视图,用户只需查询视图而无需了解底层的复杂逻辑。
- 安全性:通过视图,可以隐藏表中的敏感数据。例如,一个系统的用户表中,可以创建一个不包含密码列视图,普通用户只能访问这个视图,而不能访问原始表。
- 逻辑数据独立性:视图提供了一种逻辑数据独立性,即使底层表结构发生变化,只需修改视图定义,而无需修改依赖视图的应用程序。使用到应用程序与数据库的解耦
- 重命名列:视图允许用户重命名列名,以增强数据可读性。
原文地址:https://blog.csdn.net/2301_80802299/article/details/140997348
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!