javaweb+MySQL阶段总结

4 篇文章 0 订阅
2 篇文章 0 订阅

目录

一 什么是javaweb

JavaWeb:是使用Java技术解决相关web互联网领域的技术总和; web:简单理解网页的意思

二 Http传输协议

1 Http协议(超文本传输协议),用来规定浏览器与服务器之间进行通信的规则; 默认端口号:80(特点:每次请求-响应都是独立的。多次请求不能共享数据。Java中使用会话技术(Cookie、Session)来解决这个问题。)
2 请求数据分为3部分
请求行:请求数据的第一行。
请求头:第二行开始,格式为key:value形式
请求体:POST请求的最后一部分,存放请求参数
3 请求方法(request)、(reponse)相应状态码介绍
get、post方法
get方法:请求携带参数少(参数在请求行内),大小有限制,携带参数会在URL地址栏显示,不安全,但是高效
post方法:请求携带参数(参数在请求体内),大小无限制,携带参数不会在URL地址栏显示,安全,低产
reponse状态码
100:响应中一临时状态码,表示请求已经接收,告诉客户端应该继续请求或者如果它已经完成则忽略它
200:代表请求成功
3xx:请求重定向
4xx:找不到资源
5xx:服务器代码错误(502代表网关错误)

三 MVC和三层架构

MVC

1(开发模式)

  • C : controller 控制层

  • V:视图成(html,jsp,vue)

  • M:模型层(分两种:第一种service,dao业务模型,第二种entity实体类模型)

2 有可供借鉴的页面

C:servlet

M:service(serviceimp)

M:dao(daoimp)

M:entity

V:前端视图

三层架构

三层架构是指:视图层 View、服务层 Service,与持久层 Dao。它们分别完成不同的功能。

View 层:用于接收用户提交请求的代码在这里编写。

Service 层:系统的业务逻辑主要在这里完成。

Dao 层:直接操作数据库的代码在这里编写。
为了更好的降低各层间的耦合度,在三层架构程序设计中,采用面向抽象编程。 即上层对下层的调用,是通过接口实现的。 而下层对上层的真正服务提供者,是下层接口的实现类。 服务标准(接口)是相同的,服务提供者(实现类)可以更换。 这就实现了层间解耦合。

在这里插入图片描述
在这里插入图片描述

四 servlet

1 Servlet接口SUN公司定义了两个默认实现类,分别为:GenericServlet、HttpServlet。HttpServlet是GenericServlet的子类,又是在GenericServlet的基础上做了增强。
2 HttpServlet指能够处理HTTP请求的servlet,它在原有Servlet接口上添加了一些与HTTP协议处理方法,它比Servlet接口的功能更为强大。因此开发人员在编写Servlet时,通常应继承这个类,而避免直接去实现Servlet接口。
3 HttpServlet在实现Servlet接口时,覆写了service方法,该方法体内的代码会自动判断用户的请求方式,如为GET请求,则调用HttpServlet的doGet方法,如为Post请求,则调用doPost方法。因此,开发人员在编写Servlet时,通常只需要覆写doGet或doPost方法,而不要去覆写service方法。

servlet接收前端数据和响应结果的基本操作

接收前端提交的数据

http://localhost:8080/webapp/servlet-url?key=value&k1=v1&k2=v2…
request对象getParameter(key) , 获取请求参数
getParameter 方法的返回值是String类型,使用的时候需要注意数据类型的转换
如果前端没有提交该参数, getParameter 返回值是null
如果前端提交的中文出现乱码, 设置编码为utf-8:request.setCharacterEncoding(“utf-8”)

响应结果

通过response对象的getWriter() 方法,得到输出流
通过输出流,输出字符串内容,作为响应结果
设置响应结果的类型 和字符编码:resp.setContentType(“text/html;charset=UTF-8”)
text/html , 这个是浏览器能解析的html格式
application/json , 这个是浏览器能解析的json格式 (后期在ajax中使用)
浏览器对不能解析的格式,就提示你下载(test/html , 就是浏览器不能解析的格式,就 提示下载。

cookie和session和使用

为什么要用cookie和seession?

HTTP协议是无状态的,每次浏览器向服务器请求时,服务器都会将该请求视为新的请求,因此我们需要会话跟踪技术来实现会话内数据共享

会话

会话: 既用户打开浏览器,访问多个web资源后,关闭浏览器的过程,称之为会话;

有状态会话

有状态会话:既用户访问过页面后,下次再来访问时,服务器能够识别出用户曾经访问过该页面的过程;

保存会话的两种机制

cookie : 客户端技术
Session : 服务器技术

1.1 cookie的使用
cookie: 用于保存客户端的状态的计数。 当我们有多次请求的时候,这个多次请求被看做一个整 体,这个整体中有些数据需要保存的时候,可以使用cookie,把数据保存在浏览器中。

cookie使用的方式:

服务器端代码中,创建cookie对象,在response中添加cookie
客户端访问服务器的时候,会将把当前访问路径有关的cookie发送到服务器端
服务器端可以在request中获取到cookie数据,然后对这些数据进行使用
浏览器可以设置禁用cookie,或者用户可以删除cookie数据,用户可以查看到cookie数据, 所以重要数据不能直接保存在cookie中。
cookie中存储的是string , 并且存储的数据大小也有限。
cookie 可以设置有效期,过期之后,cookie会被浏览器清除掉
1.2 session的使用
状态管理
cookie : 客户端状态管理的技术
session:服务器端状态管理技术
session中保存数据
getSession(): 规则就是如果有就根据sessionid获取session对象,如果没有就直接创建一个 session对象。
getSession(boolean) : true, 同getSession()功能, false , 如果找不到session对象,就返回null.

请求转发和重定向的区别

请求转发
将存在一个request中的信息从web组件1转发到web组件2中,这就是请求转发(Forward)
在这里插入图片描述

request.getRequestDispatcher("/要跳转的地址").forward(request, response);

重定向
web组件1处理完请求后返回一个response响应,这个响应中包含了web组件2资源的url,告诉浏览器,让你重新向web组件2发送一个请求。这就是重定向
在这里插入图片描述

response.sendRedirect("/要跳转的地址");

1、请求次数

重定向是浏览器向服务器发送一个请求并收到响应后再次向一个新地址发出请求,转发是服务器收到请求后为了完成响应跳转到一个新的地址;重定向至少请求两次,转发请求一次;

2、地址栏不同

重定向地址栏会发生变化,转发地址栏不会发生变化;

3、是否共享数据

重定向两次请求不共享数据,转发一次请求共享数据(在request级别使用信息共享,使用重定向必然出错);

4、跳转限制

重定向可以跳转到任意URL,转发只能跳转本站点资源;

5、发生行为不同

重定向是客户端行为,转发是服务器端行为;

五 javaweb在tomcat服务器上运行流程

1 tomcat及其体系结构(目前只知道tomcat是一个服务器,能处理请求和响应数据)

以下为tomcat体系结构
(1)Server
服务器元素代表整个catalina servlet容器。是单例模式。

(2)Service
Service是这样一个集合:它由一个或者多个Connector组成,以及一个Engine,负责处理所有Connector所获得的客户请求。

(3)Connector

**一个Connector将在某个指定端口上侦听客户请求,并将获得的请求交给Engine来处理,**从Engine处获得回应并返回客户。TOMCAT有两个典型的Connector,一个直接侦听来自browser的http请求,一个侦听来自其它WebServer的请求

Coyote Http/1.1 Connector 在端口8080处侦听来自客户browser的http请求
Coyote JK2 Connector 在端口8009处侦听来自其它WebServer(Apache)的servlet/jsp代理请求

(4) Engine
  Engine下可以配置多个虚拟主机Virtual Host,每个虚拟主机都有一个域名,当Engine获得一个请求时,它把该请求匹配到某个Host上,然后把该请求交给该Host来处理,Engine有一个默认虚拟主机,当请求无法匹配到任何一个Host上的时候,将交给该默认Host来处理

(5)Host
  代表一个Virtual Host,虚拟主机,每个虚拟主机和某个网络域名Domain Name相匹配,每个虚拟主机下都可以部署(deploy)一个或者多个Web App,每个Web App对应于一个Context,有一个Context path,当Host获得一个请求时,将把该请求匹配到某个Context上,然后把该请求交给该Context来处理,匹配的方法是“最长匹配”,所以一个path==""的Context将成为该Host的默认Context,所有无法和其它Context的路径名匹配的请求都将最终和该默认Context匹配

(6)Context
一个Context对应于一个Web Application,一个Web Application由一个或者多个Servlet组成,Context在创建的时候将根据配置文件 C A T A L I N A H O M E / c o n f / w e b . x m l 和 CATALINA_HOME/conf/web.xml和 CATALINAHOME/conf/web.xmlWEBAPP_HOME/WEB-INF/web.xml载入Servlet类,当Context获得请求时,将在自己的映射表(mapping table)中寻找相匹配的Servlet类,如果找到,则执行该类,获得请求的回应,并返回。
在这里插入图片描述
其中Container-容器组件
用于封装和管理 Servlet ,以及具体处理Request请求,在Connector内部包含了4个子容器:

Engine:最顶层容器组件,其下可以包含多个 Host。
Host:一个 Host 代表一个虚拟主机,其下可以包含多个 Context。
Context:一个 Context 代表一个 Web 应用,其下可以包含多个 Wrapper。 Wrapper:一个 Wrapper 代表一个 Servlet。
在这里插入图片描述
Tomcat 的web目录,对应关系实际是这样的:Webapps 对应的就是 Host 组件,example 对应的就是 Context 组件,Wrapper 就是容器内的 Servlet了。
在这里插入图片描述

2 Tomcat Server处理一个http请求的过程

启动Tomcat服务器,tomcat进行初始化,加载相关配置,Connector将在某个指定端口上侦听客户请求

假设来自客户的请求为:

http://localhost:8080/test/indexServlet

1.用户在浏览器中输入网址localhost:8080/test/indexServlet,电脑内置的DNS解析器会解析这段URL,之后请求被发送到本机(也就是localhoset)8080的端口(tomcat),被在那里监听的Coyote HTTP/1.1 Connector获得;

2.Connector把该请求交给它所在的Service的Engine(Container)来处理,并等待Engine的回应;

3.Engine获得请求localhost/test/indexServlet,匹配所有的虚拟主机Host;

4.Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机),名为localhost的Host获得请求/test/Servlet,匹配它所拥有的所有Context。Host匹配到路径为/test的Context(如果匹配不到就把该请求交给路径名为“ ”的Context去处理);

5.path=“/test”的Context获得请求/indexServlet,在它的mapping table中寻找出对应的Servlet。Context匹配到URL Pattern对应的Servlet,对应于Servlet类;

6.构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用Servlet的doGet()或doPost(),执行业务逻辑、数据存储等;

7.Context把执行完之后的HttpServletResponse对象返回给Host;

8.Host把HttpServletResponse对象返回给Engine;

9.Engine把HttpServletResponse对象返回Connector;

10.Connector把HttpServletResponse对象返回给客户Browser。

11.客服端浏览器拿到数据进行解析并渲染页面

数据库(MySQL)

1.mysql常用命令:

// 1 查看mysql有哪些数据库
show databases;
// 2 选择数据库
use 数据库名
// 3 创建数据库
create database 数据库名
// 4 查看数据库里面有哪些表
show tables

//查看mysql数据库版本号:
select version();

//查看当前使用的是哪一个数据库

select database();

注意:mysql是不见“;”不执行,“;”表示结束  

        \c可以用来终止一条命令的输入。

2.创建表和使用表

2.1介绍表

数据库最基本的单元:表(table)

什么是表table?为什么用表来存储数据呢?
 
	姓名	性别	年龄(列:字段) 
	---------------------------
	张三	男			20            ------->行(记录)
	李四	女			21            ------->行(记录)
	王五	男			22            ------->行(记录)
 
数据库当中是以表格的形式表示数据的。
因为表比较直观。
 
任何一张表都有行和列:
	行(row):被称为数据/记录。
	列(column):被称为字段。
 
姓名字段、性别字段、年龄字段。
 
了解一下:
	每一个字段都有:字段名、数据类型、约束等属性。
	字段名可以理解,是一个普通的名字,见名知意就行。
	数据类型:字符串,数字,日期等,后期讲。
 
	约束:约束也有很多,其中一个叫做唯一性约束,
		这种约束添加之后,该字段中的数据不能重复。

2.2创建表

# 语法
    create table 表名(
	字段名1 数据类型, 
	字段名2 数据类型, 
	字段名3 数据类型
);
 
表名:建议以t_ 或者 tbl_开始,可读性强。见名知意。
字段名:见名知意。
表名和字段名都属于标识符。
 
代码示例:
 
    创建一个学生表?
 
	学号、姓名、年龄、性别、邮箱地址
	create table t_student(
		no int,
		name varchar(32),
		sex char(1),
		age int(3),
		email varchar(255)
	);

注意:
1、在同一张表中,字段名不能相同
2、宽度 和 约束条件为可选参数,字段名 和 字段名下记录的类型 是必须的
3、最后一个字段后不能加逗号

2.2.1 mysql中的数据类型

很多数据类型,我们只需要掌握一些常见的数据类型即可。

varchar(最长255)
    可变长度的字符串
    比较智能,节省空间。
    会根据实际的数据长度动态分配空间。

    优点:节省空间
    缺点:需要动态分配空间,速度慢。

char(最长255)
    定长字符串
    不管实际的数据长度是多少。
    分配固定长度的空间去存储数据。
    使用不恰当的时候,可能会导致空间的浪费。

    优点:不需要动态分配空间,速度快。
    缺点:使用不当可能会导致空间的浪费。

    varchar和char我们应该怎么选择?
        性别字段你选什么?因为性别是固定长度的字符串,所以选择char。
        姓名字段你选什么?每一个人的名字长度不同,所以选择varchar。

int(最长11)
    数字中的整数型。等同于java的int。

bigint
    数字中的长整型。等同于java中的long。

float    
    单精度浮点型数据

double
    双精度浮点型数据

date
    短日期类型

datetime
    长日期类型

clob
    字符大对象
    最多可以存储4G的字符串。
    比如:存储一篇文章,存储一个说明。
    超过255个字符的都要采用CLOB字符大对象来存储。
    Character Large OBject:CLOB

 blob
    二进制大对象
    Binary Large OBject
    专门用来存储图片、声音、视频等流媒体数据。
    往BLOB类型的字段上插入数据的时候,例如插入一个图片、视频等,
    你需要使用IO流才行。

2.3更新表

2.3.1添加列(字段)
语法:
alter table table_name add column 列名 字段类型
 
示例:
 
alter table 表名 add column 列名 varchar(30);

注意:

在实际的开发中,需求一旦确定之后,表一旦设计好之后,很少的进行表结构的修改。因为开发进行中的时候,修改表结构,本比较高。修改表的结构,对应的java代码就需要进行大量的修改。成本是比较高的。
这个责任应该由设计人员来承担!

2.3.2删除列(字段)
语法:
alter table table_name
drop column 字段名
 
示例:
alter table 学生表
drop column 学号

2.4查询表

2.4.1查询单个字段
语法:
select 字段名 from table_name
示例:
select 姓名 from 员工表
2.4.2查询多个字段
语法:
 
select 字段名1,字段名2 from table_name
 
示例:
 
select 姓名,性别 from 员工表
2.4.3查询整个表
语法:
select * from table_name
示例:
select * from 员工表

这种方式的缺点:
1、效率低
2、可读性差。
在实际开发中不建议,可以自己玩没问题。
你可以在DOS命令窗口中想快速的看一看全表数据可以采用这种方式。

2.4.4 把查询结果去除重复记录【distinct】
语法:
select distinct 字段名 from table_name
示例:
select distinct 性别 from 员工表

注意:原表数据不会被修改,只是查询结果去重

2.4.5查询排序数据【order by】

1 按一个字段排序

语法:
select 字段名 from table_name order by 字段名
示例:
select 身高 from 学生表 order by 身高

2 按多个字段排序

语法:
select 字段名1,字段名2 from table_name order by 字段名1,字段名2
示例:
select 字段名1,字段名2 from 学生表 order by 字段名1,字段名2

3 指定排序方向

语法:
--升序排列
select 字段名 from table_name order by 字段名 asc
 
--降序排列
select 字段名 from table_name order by 字段名 desc
示例:
--升序排列
select 身高 from 学生表 order by 身高 asc
 
--降序排列
select 身高 from 学生表 order by 身高 desc
2.4.6过滤数据【where】
1 使用where数据
语法:
select 字段名1,字段名2 from table_name where 限制条件
示例:
select *from 学生表 where 性别 = '男'
2 不匹配检查
语法:
select 字段名1,字段名2 from 学生表 where 字段名 <> 某个值
 
示例:
 列出不是团员的所有学生信息
select *from 学生表 where 党员 <> 1

注意:!= 和 <> 通常可以互换,但是并不是所有的DBMS都支持这两种不等于操作符。

示例:
 列出不是团员的所有学生信息
select *from 学生表 where 团员 <> 1
3 范围值检查

在where子句中使用between…and…between匹配范围中所有的值,包括指定的开始值和结束值

示例:
查找身高在1.60~1.70之间的学生信息
select *from 学生表 where 身高 between 1.50 and 1.80
4 空值检查
语法:
当一个列不包含值时,称其包含空值NULL
示例:
使用select语句的is null子句来检查空值
 
select *from 学生表 where 性别 is null
5 组合where语句(1 and 2 or 3 in 4 not 5 like)
1 and操作符
语法:
要通过不止一个列进行过滤,可以使用and操作符给where子句附加条件
示例:
select *from 学生表 where 性别 = '男'  and 团员 = 1
2 or操作符
语法:
or操作符与and操作符正好相反,它指示检索匹配任一条件的行。
示例:
select *from 学生表 where 性别 = '男'  or 团员 = 1
求值顺序

where子句可以包含任意数目的andor操作符。允许两者结合以进行复杂、高级的过滤。

示例:
select *from 学生表 where (性别 = '女'  or 团员 = 1) and 身高 > 1.70
注意:SQL在处理or操作符前,优先处理and操作符,即and在求值过程中优先级更高。
3 in操作符
语法:
        in操作符用来指定条件范围,范围中的每个条件都可以进行匹配
        in取一组由逗号分隔、括在圆括号中的合法值。

 
示例:
select *from 学生表 where 身高 in ('1.60','1.55','1.75')
4 not 操作符
语法:
        where子句的not操作符有且只有一个功能,否定器后所跟的任何条件
        not关键字可以用在要过滤的列前,而不是列后。

 
示例:
select *from 学生表 where not 团员 = 1
5 like关键字(模糊查询)

称为模糊查询,支持%或下划线匹配
%匹配任意多个字符
下划线:任意一个字符。
(%是一个特殊的符号,_ 也是一个特殊符号)

  找出名字中含有A的
 
select 字段名 from 表名 where 字段名 like '%A%';
 
找出名字以T结尾的
 
select 字段名 from 表名 where 字段名 like '%T';
 
找出名字以G开始的
 
select 字段名 from 表名 where 字段名 like 'G%';
 
找出第二个母是C的?
 
select 字段名 from 表名 where 字段名 like '_C%';
2.4.7数据处理函数

数据处理函数又被称为单行处理函数

单行处理函数的特点:一个输入对应一个输出。

和单行处理函数相对的是:多行处理函数。(多行处理函数特点:多个输入,对应1个输出!)

常用文本处理函数说明
left()返回字符串串左边的字符
right返回字符串右边的字符
length()返回字符串的长度
trim()去掉字符串左边的空格
lower()将字符串转为小写
upper()将字符串转为大写
rtrim()去掉字符串右边的空格
soundex()返回字符串的soundex值
substr()或substring()提取字符串的组成部分

分组函数(多行处理函数)

   多行处理函数的特点:输入多行,最终输出一行。

注意:
分组函数在使用的时候必须先进行分组,然后才能用。
如果你没有对数据进行分组,整张表默认为一组。

函数说明
avg()返回某列平均值
count()返回某列的行数
max()返回某列的最大值
min()返回某列的最小值
sum()返回某列之和
AVG()函数

AVG()通过对表中行数计数并计算其列值之和,求得该列的平均值。

AVG()可以用来返回所有列的平均值,也可以用来返回特定列或行的平均值。

示例:
求出成绩表中的平均成绩:
select AVG(成绩) as 平均成绩 from 成绩表

COUNT()

COUNT()函数进行计数

示例:
求出学生表中的总人数
 
select COUNT(*) as 总人数 from 学生表

注意:

1.使用COUNT(*)对表中的数据数目进行计数,不管表列中包含的是空值(NULL)还是非空值

2.使用COUNT(column)对特定列中具有值得行进行计数,忽略NULL值

组合分组函数

select语句可以根据需要包含多个分组函数

示例:
select COUNT(*) as 商品数目
		MIN(价格) as 最低商品价格
		MAX(价格) as 最高商品价格
		AVG(价格) as 商品均价
from 商品表
2.4.8分组查询

分组:

是使用select语句的group by子句建立的

求出每种商品的商品数量

select 商品名,COUNT(*) as 商品数量	
from 商品表
group by 商品名

重点结论:
在一条select语句当中,如果有group by语句的话,
select后面只能跟:参加分组的字段,以及分组函数。
其它的一律不能跟。

过滤分组(having)

使用having可以对分完组之后的数据进一步过滤。
having不能单独使用,having不能代替where,having必须和group by联合使用。

优化策略:
where和having,优先选择where,where实在完成不了了,再选择
having。

示例:
求出商品数量大于等于2的商品数量
 
select 商品名,COUNT(*) as 商品数量
from 商品表
group by 商品名
having COUNT(*)>=2
where在数据分组前进行过滤,having在数据分组后进行过滤
2.4.9使用子查询

子查询:

select语句中嵌套select语句,被嵌套的select语句称为子查询。

利用子查询进行过滤

在select 中子查询总是从内向外进行处理,作为子查询的select语句只能查询单个列

示例:
select
		..(select).
	from
		..(select).
	where
		..(select)
 
 
select * from 选课表 where 学号 in 
(select 学号 from 学生表 where 性别 = '男')

2.5连接查询

什么是连接查询?

从一张表中单独查询,称为单表查询。 emp表和dept表联合起来查询数据,从emp表中取员工名字,从dept表中取部门名字。 这种跨表查询,多张表联合起来查询数据,被称为连接查询。

根据表连接的方式分类:
内连接:
等值连接
非等值连接
自连接

外连接:
左外连接(左连接)
右外连接(右连接)
全连接

当两张表进行连接查询时,没有任何条件的限制会发生什么现象?

当两张表进行连接查询,没有任何条件限制的时候,最终查询结果条数,是两张表条数的乘积,这种现象被称为:笛卡尔积现象。(笛卡尔发现的,这是一个数学现象。)

怎么避免笛卡尔积现象?

连接时加条件,满足这个条件的记录被筛选出来!

语法:
select 员工表的员工名字,部门表的部门名
from 员工表,部门表
where 员工表.名字=部门表.部门名
 
示例:
select 
	emp.ename,dept.dname 
from 
	emp, dept
where
	emp.deptno = dept.deptno;
注意:通过笛卡尔积现象得出,表的连接次数越多效率越低,尽量避免表的连接次数
2.5.1 内连接之非等值连接
--inner可以省略(带着inner可读性更好!!!一眼就能看出来是内连接)
select 
	e.ename,d.dname
from
	emp e    -- as省略了,给字段起别名,效率更高
inner join
	dept d
on
	e.deptno = d.deptno; -- 条件是等量关系,所以被称为等值连接。
2.5.2内连接之非等值连接

案例:找出每个员工的薪资等级,要求显示员工名、薪资、薪资等级?

select 
	e.ename, e.sal, s.grade
from
	emp e
join
	salgrade s
on
	e.sal between s.losal and s.hisal; // 条件不是一个等量关系,称为非等值连接。
2.5.3内连接之自连接

案例:查询员工的上级领导,要求显示员工名和对应的领导名?

emp a 员工表               emp b 领导表

select 
	a.ename as '员工名', b.ename as '领导名'
from
	emp a
join
	emp b
on
	a.mgr = b.empno; --员工的领导编号 = 领导的员工编号
以上就是内连接中的:自连接,技巧:一张表看做两张表

注意:

内连接:(A和B连接,AB两张表没有主次关系。平等的。)

2.5.4外连接(右外连接)
语法:
select 员工表.员工名,部门表.部门名 
from 员工表 right join 部门表 on 员工表.编号=部门表.编号
 
语法
-- outer是可以省略的,带着可读性强。
select 
	e.ename,d.dname
from
	emp e 
right outer join 
	dept d
on
	e.deptno = d.deptno;

right代表什么:表示将join关键字右边的这张表看成主表,主要是为了将 这张表的数据全部查询出来,捎带着关联查询左边的表。 在外连接当中,两张表连接,产生了主次关系。

2.5.5外连接(左外连接)
语法:
select 员工表.员工名,部门表.部门名 
from 部门表 right join 员工表 on 员工表.编号=部门表.编号
 
 
-- outer是可以省略的,带着可读性强。
select 
	e.ename,d.dname
from
	dept d 
left outer join 
	emp e
on
	e.deptno = d.deptno;

带有right的是右外连接,又叫做右连接。

带有left的是左外连接,又叫做左连接。

任何一个右连接都有左连接的写法。

任何一个左连接都有右连接的写法。

三张表,四张表怎么连接?

语法:
		select 
			...
		from
			a
		join
			b
		on
			a和b的连接条件
		join
			c
		on
			a和c的连接条件
		right join
			d
		on
			a和d的连接条件
2.5.6 union合并查询结果集
语法;
select 字段名1,字段名2,字段名3
from table_name
where 限制条件1
union
select 字段名1,字段名2,字段名3
from table_name
where 限制条件2
 
示例:
select 姓名,性别
from 学生表
where 学号 in ('01','02','03')
union
select 姓名,性别
from 学生表
where 学号 ='04'

注意:union的效率要高一些。对于表连接来说,每连接一次新表,则匹配的次数满足笛卡尔积,成倍的翻。但是union可以减少匹配的次数。在减少匹配次数的情况下,还可以完成两个结果集的拼接。

2.6 limit(非常重要)

limit作用:将查询结果集的一部分取出来。通常使用在分页查询当中。 百度默认:一页显示10条记录。 分页的作用是为了提高用户的体验,因为一次全部都查出来,用户体验差。 可以一页一页翻页看。

完整用法:limit (startIndex, length)
startIndex是起始下标,length是长度 。起始下标从0开始。

按照薪资降序,取出排名在前5名的员工?

select 
	ename,sal
from
	emp
order by 
	sal desc
limit 5; --取前5

缺省用法:limit 5; 这是取前5.

注意:mysql当中limit在order by之后执行

取出工资排名在[3-5]名的员工?

select 
		ename,sal
	from
		emp
	order by
		sal desc
	limit
		2, 3;

2.7表的查询学完了(总结)

select 
		...
	from
		...
	where
		...
	group by
		...
	having
		...
	order by
		...
	limit
		...


 
 
以上关键字只能按照这个顺序来,不能颠倒。
 
执行顺序?
	1.from
	2.where
	3.group by
	4.having
	5.select
	6.order by
	7.limit..
 
从某张表中查询数据,
先经过where条件筛选出有价值的数据。
对这些有价值的数据进行分组。
分组之后可以使用having继续筛选。
select查询出来。
最后排序输出!

2.8插入数据insert

语法格式:
	insert into 表名(字段名1,字段名2,字段名3...) values(1,2,3);

insert语句中的“字段名”可以省略

注意:前面的字段名省略的话,等于都写上了!所以值也要都写上!

语法:
insert into table_name 
values(1,2,....)
 
示例:
insert into 学生表01
values('李明','男','1.70')

2.9修改update

语法:
update table_name
set
字段名1='值',
字段名2='值'
where 限制条件
示例:
update 学生表
set
姓名='小红',
性别='女'
where 学号='01'
注意:没有条件限制会导致所有数据全部更新。

2.10删除数据 delete

语法;
delete from table_name
where 要删除行的信息
 
示例:
delete from 学生表
where 学号='01'
快速删除表中的数据?【truncate比较重要,必须掌握】
 
--删除dept_bak表中的数据
delete from dept_bak; --这种删除数据的方式比较慢。
 
用法:truncate table dept_bak; (这种操作属于DDL操作。)
 
删除表操作?
	drop table 表名; -- 这不是删除表中的数据,这是把表删除。

delete语句删除数据的原理?(delete属于DML语句!!!)
表中的数据被删除了,但是这个数据在硬盘上的真实存储空间不会被释放!!!
这种删除缺点是:删除效率比较低。
这种删除优点是:支持回滚,后悔了可以再恢复数据!!!

truncate语句删除数据的原理?
这种删除效率比较高,表被一次截断,物理删除。
这种删除缺点:不支持回滚。
这种删除优点:快速。

大表非常大,上亿条记录?
删除的时候,使用delete,也许需要执行1个小时才能删除完!效率较低。
可以选择使用truncate删除表中的数据。只需要不到1秒钟的时间就删除结束。效率较高。
但是使用truncate之前,必须仔细询问客户是否真的要删除,并警告删除之后不可恢复!

**truncate**是删除表中的数据,表还在!

3视图(view)

什么是视图?

view:站在不同的角度去看待同一份数据。

数据库中的建立的表table叫物理表

view是查询结果的保存,它是虚拟表

怎么创建视图对象?怎么删除视图对象?

表复制:
create table dept2 as select * from dept;
 
dept2表中的数据:
mysql> select * from dept2;
+--------+------------+----------+
| DEPTNO | DNAME      | LOC      |
+--------+------------+----------+
|     10 | ACCOUNTING | NEW YORK |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  |
|     40 | OPERATIONS | BOSTON   |
+--------+------------+----------+
 
创建视图对象:
	create view dept2_view as select * from dept2;
 
删除视图对象:
	drop view dept2_view;
 
注意:只有DQL语句才能以view的形式创建。
	create view view_name as 这里的语句必须是DQL语句;

用视图做什么?

我们可以面向视图对象进行增删改查,对视图对象的增删改查,会导致原表被操作!(视图的特点:通过对视图的操作,会影响到原表数据。)

--面向视图查询
select * from dept2_view; 
 
-- 面向视图插入
insert into dept2_view(deptno,dname,loc) values(60,'SALES', 'BEIJING');
 
-- 查询原表数据
mysql> select * from dept2;
+--------+------------+----------+
| DEPTNO | DNAME      | LOC      |
+--------+------------+----------+
|     10 | ACCOUNTING | NEW YORK |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  |
|     40 | OPERATIONS | BOSTON   |
|     60 | SALES      | BEIJING  |
+--------+------------+----------+
 
-- 面向视图删除
delete from dept2_view;
 
-- 查询原表数据
mysql> select * from dept2;
Empty set (0.00 sec)

创建视图:

语法:
create view table_name as
select 创建视图的相应信息
 
示例:
create view 
	emp_dept_view
as
	select 
		e.ename,e.sal,d.dname
	from
		emp e
	join
		dept d
	on
		e.deptno = d.deptno;

视图对象在实际开发中到底有什么用?

《方便,简化开发,利于维护》

假设有一条非常复杂的SQL语句,而这条SQL语句需要在不同的位置上反复使用。
每一次使用这个sql语句的时候都需要重新编写,很长,很麻烦,怎么办?
可以把这条复杂的SQL语句以视图对象的形式新建。
在需要编写这条SQL语句的位置直接使用视图对象,可以大大简化开发。
并且利于后期的维护,因为修改的时候也只需要修改一个位置就行,只需要
修改视图对象所映射的SQL语句。

我们以后面向视图开发的时候,使用视图的时候可以像使用table一样。
可以对视图进行增删改查等操作。视图不是在内存当中,视图对象也是
存储在硬盘上的,不会消失。

再提醒一下:
    视图对应的语句只能是DQL语句。
    但是视图对象创建完成之后,可以对视图进行增删改查等操作。

4.约束(constraint)

1.约束的作用?

在创建表时我们需要给表中的字段增加一些约束,来保证表数据的完整性,有效性

2.约束包括哪些?

  1. 非空约束 not null

  2. 唯一性约束 unique

  3. 主键约束 primary key(简称pk)

  4. 外键约束 foreign key (简称fk)

  5. 检查约束 check(MYSQL不支持,Orace支持)

1.非空约束 not null
非空约束所约束的字段不能为null。

drop table if exists t_vip;
create table t_vip(
	id int,
	name varchar(255) not null
);

mysql> insert into t_vip(id) values(1);
ERROR 1364 (HY000): Field ‘name’ doesn’t have a default value

2.唯一性约束:unique
唯一性约束unique约束的字段不能重复,但是可以为NULL。

drop table if exists t_vip;
create table t_vip(
	id int,
	name varchar(255) unique,
	email varchar(255)
);
insert into t_vip(id,name,email) values(1,'wangwu','wangwu@qq.com');

如果再插入一条wangwu,就会报错

mysql> insert into t_vip(id,name,email) values(1,‘wangwu’,‘lisu@qq.com’);
ERROR 1062 (23000): Duplicate entry ‘wangwu’ for key ‘name’

新需求:name和email两个字段联合起来具有唯一性

create table t_vip(
	id int,
	name varchar(255) unique,
	email varchar(255) unique //约束添加在列的后面,被称为列级约束
);
insert into t_vip(id,name,email) values(1,'wangwu','wangwu@qq.com');
insert into t_vip(id,name,email) values(2,'wangwu','wangwu@sina.com');

这样达不到新的需求,插入数据会报错,因为wangwu和wangwu重复。这样创建表示,name和email各自唯一。

两个字段联合唯一

create table t_vip(
	id int,
	name varchar(255),
	email varchar(255),
	unique(name,email)  //这样约束被称为表级约束
);

两个字段同时一样,才插入失败。

3.unique和not null 可以联合

drop table if exists t_vip;
create table t_vip(
	id int,
	name varchar(255) not null unique
);

在mysql中,如果一个字段同时被 not null 和 unique 约束的话,该字段自动变成主键字段。(但Oracle不一样)

4.主键约束(primary key,简称PK)
主键约束的相关术语:主键约束、主键字段、主键值。
主键值是每一行记录的唯一标识。

注意:任何一张表都应该有主键,没有主键,表无效!

主键的特征:not null + unique(不能为空,同时不能重复)

添加主键约束:

DROP TABLE t_vip;
CREATE TABLE t_vip(
id INT PRIMARY KEY,
NAME VARCHAR(255)
);
 
INSERT INTO t_vip(id,NAME) VALUES(1,'zhangsan');
INSERT INTO t_vip(id,NAME) VALUES(2,'lisi');
INSERT INTO t_vip(id,NAME) VALUES(2,'baiye');
错误信息:Duplicate entry '2' for key 'PRIMARY'

也可以这样写表示表级约束,前面是列级约束

CREATE TABLE t_vip(
id INT,
NAME VARCHAR(255),
PRIMARY KEY(id)
);

表级约束主要给多个字段起来添加约束

在mysql中有一种机制可以帮助我们自动维护一个主键值

CREATE TABLE t_vip(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(255)
);
 
INSERT INTO t_vip(NAME) VALUES('zhangsan');
INSERT INTO t_vip(NAME) VALUES('lisi');
INSERT INTO t_vip(NAME) VALUES('baiye');
INSERT INTO t_vip(NAME) VALUES('baiye');
AUTO_INCREMENT表示自增,从1开始

5.外键约束 foreign key 简称 fk(重点)
当两张表有父子关系时,子表上与父表关联的字段为保证数据有效需要加外键约束,被引用的字段可以不是主键可以为null但是必须具有唯一性

设计数据库表,描述“班级和学生”信息:
班级一张表、学生一张表

t_class 班级表
classno(pk)    classname
100				北京市大兴区亦庄镇第二中学高三1101				北京市大兴区亦庄镇第二中学高三2班
 
t_student 学生表
no(pk)          name         cno(fk引用t_class这张表的classno)
1				jack			100
2				luck			100
3				lilei			100
4				zhaf			101
5				wan				101
6				zhaoliu			101

当cno字段没有任何约束的时候,可能会导致数据无效。
所以为了保证cno字段中的值都是t_class表中的classno,需要给cno添加一个外键约束。

注意:

添加了外键约束,表与表之间产生了父子关系。
t_class是父表、t_student是子表。
删除表的顺序:先删子,再删父。
创建表的顺序:先创建父,再创建子。
删除数据的顺序:先删子,再删父。
插入数据的顺序:先插入父,再插入子。

drop table if exists t_student; //先删子
drop table if exists t_class;
 
create table t_class(  //先创建父
	classno int primary key,
	classname varchar(255),
);
create table t_student(
	no int primary key auto_increment,
	name varchar(255),
	cno int,
	foreign key(cno) references t_class(classno)
);

注意:

子表中的外键引用的附表中的某个字段,被引用的这个字段不一定是主键。但至少具有unique唯一性。
外键可以为null。

5.存储引擎

1.存储引擎介绍
存储引擎是MySQL中特有的一个术语,其他数据库中没有。
实际上存储引擎是一个表存储/组织数据的方式,不同的存储引擎,表存储数据的方式不同。

mysql默认的存储引擎是:InnoDB
mysql默认的字符编码方式是:utf8

可以在建表的时候给表指定存储引擎,在小括号")"的右边使用:ENGINE来指定存储引擎;CHARSET来指定这张表的字符编码方式。

create table t_product(
	id int primary key,
	name varchar(255)
) engine=InnoDB default charset=gbk;

查看mysql支持哪些存储引擎
命令:show engines \G
总共有9种存储引擎,不同版本支持的情况不一样。

6.事务(重点)

6.1认识事务

一个事务其实就是一个完整的业务逻辑,是一个最小的工作单元。要么同时成功,要么同时失败,不可再分。

假设转账,从A账户向B账户转账10000
A账户的钱减去10000(update语句)
B账户的钱加上10000(update语句)
这就是一个完整的业务逻辑

这两个update语句要求必须同时成功或者同时失败,才能保证钱是正确的。

只有DML语句才会有事务这一说,其他语句和事务无关。
insert、delete、update。
一旦你的操作涉及到增、删、改,那么就一定要考虑安全问题。

6.2事务的实现

事务:就是批量的DML语句同时成功,或者同时失败。

事务是怎么做到多条DML语句同时成功和同时失败的?
InnoDB存储引擎:提供一组用来记录事务性活动的日志文件。

事务开启: insert delete update … 事务结束

在事务执行过程中。每一条DML的操作都会记录到“事务性活日志文”中

在事务执行过程中我们可以提交事务也可以回滚事务

提交事务:清空事务性活动的日志文件,将数据全部彻底持久化到数据库表中,标志着事物成功结束

回滚事务:清空事务性活动的日志文件,将所有的DML操作全部撤销,标志着事务失败结束

6.3怎么提交事务,怎么回滚事务?

提交事务:commit

回滚事务:rollback

mysql默认情况下自动提交事务,那怎么自己提交事务呢?

START TRANSACTION;

SELECT * FROM dept;
START TRANSACTION;
INSERT INTO dept VALUE(50,'jjj','yyyy');
SELECT * FROM dept;
ROLLBACK;
SELECT * FROM dept;

事务一旦提交回滚就没有作用

SELECT * FROM dept;
START TRANSACTION;
INSERT INTO dept VALUE(50,‘jjj’,‘yyyy’);
SELECT * FROM dept;
COMMIT;
ROLLBACK;
SELECT * FROM dept;

6.4事务的4个特性

ACID

  • 原子性(A):说明事务是最小的工作单元,不可再分。
  • 一致性(C):所有事务要求,在同一个事务当中,所有操作必须同时成功,或者同时失败,以保证数据的一致性。
  • 隔离性(I):A事务和B事务之间具有一定的隔离。相当于多线程并发访问的每个线程。
  • 持久性(D):事务最终结束的一个保障。事务提交,就相当于将没有保存到硬盘上的数据保存到硬盘上!

事务与事务之间有4个隔离级别

  • 读未提交:read uncommitted(最低隔离级别)

事务A可以读取到事务B未提交的数据。(没有提交就读取到了)
这种隔离级别存在的问题就是:脏读现象(Dirty Read),我们称堵到了脏数据。
这种隔离级别一般都是理论上的,大多数的数据库隔离级别都是二挡起步。

  • 读已提交:read commited

事务A只能读取到事务B提交之后的数据。解决了脏读现象。
这种隔离级别存在的问题是:不可重复读取数据。
这种隔离级别是比较真实的数据,每次读到的数据是绝对真实的。
Oracle数据库默认的隔离级别是:read commited

  • 序列化/串行化:serializable(最高的隔离级别)

这是最高隔离级别,效率最低。解决了所有的问题。
这种隔离级别表示事务排队,不能并发!
synchronized,线程同步(事务同步)
每次读取到的数据都是最真实的,但是效率是最低的。

7.索引

索引是在数据库表的字段上添加的,是为了提高查询效率存在的一种机制。
一张表的一个字段可以添加一个索引,当然,多个字段联合起来也可以添加索引。
索引相当于一本书的目录,是为了缩小扫描范围而存在的一种机制。

根据SQL语句扫描:select * from t_user where name = ‘jack’,扫描name查找。
如果name字段上没有添加索引(目录),或者说没有给name字段创建索引,MySQL会进行全扫描,会将name字段上的每一个值都比对一遍。效率比较低。

MySQL在查询方面主要就是两种方式:
第一种方式:全表扫描。
第二种方式:根据索引检索。

在mysql数据库当中,索引也是需要排序的,并且这个索引的排序和TreeSet数据结构相同。TreeSet底层是一个自平衡的二叉树!在mysql当中索引是一个B-Tree数据结构。
遵循左小右大原则存放,采用中序遍历方式遍历取数据。

7.1索引的实现原理

在这里插入图片描述

什么情况下,我们会考虑给字段添加索引呢?
1.数据量庞大(到底有多么庞大算庞大,这个需要测试,因为每一个硬件环境不同)。
2.该字段经常出现在where的后面,以条件的形式存在,也就是说这个字段总是被扫描。
3.该字段很少的DML操作,因为DML之后,索引需要重新排序。

建议不要随意添加索引,因为索引也是需要维护的,太多的话反而会降低系统的性能。建议通过主键查询,建议通过unique约束的字段进行查询,效率会比较高。

7.2创建和删除索引

创建索引:
create index emp_ename_index on emp(ename);
给emp表的ename字段添加索引,起别名:emp_ename_index
 
删除索引:
drop index emp_ename_index on emp;
将emp表上的emp_ename_index索引对象删除。
 
在mysql当中,查看一个SQL语句是否使用了索引进行检索:
explain select * from emp where ename = 'KING';

7.3索引的失效

索引也有失效的情况,如下:

"%"开头的模糊查询
select * from emp where ename like ‘%T’;
尽量避免模糊查询的时候以"%"开头,这是一种优化的策略。
可以用SQL语句查看:explain select * from emp where ename like ‘%T’;

使用or
如果使用or,那么要求or两边的条件字段都要有索引,索引才生效。如果其中一个字段没有索引,那么另一个字段上的索引也会失效。所以不建议使用or,可以使用union来代替。

使用复合索引
使用复合索引的时候,要使用左侧的列查找,索引才生效。使用右侧,则失效。
复合索引:两个字段,或者更多的字段联合起来添加一个索引。
create index emp_job_sal_index on emp(job,sal);
使用左侧:explain select * from emp where job = ‘MANAGER’; 生效
使用右侧:explain select * from emp where sal= 800; 失效

索引列参与运算
在where当中索引列参加了运算,索引失效。
explain select * from emp where sal+1 = 800;

索引列使用了函数
在where当中索引列使用了函数。
explain select * from emp where lower(ename) = ‘smith’;

还有其他情况,先了解这些…

索引是各种数据库进行优化的重要手段,优化的时候优先考虑的因素就是索引。
索引在数据库当中分了很多类:

1 单一索引:一个字段上添加索引。
2 复合索引:两个字段或者更多的字段上添加索引。
3 主键索引:主键上添加索引。
4 唯一性索引:具有unique约束的字段上添加索引。(注意:唯一性比较弱的字段上添加索引的用处不大。)
例:需要在examination_info表创建以下索引,规则如下:
在duration列创建普通索引 idx_duration、在exam_id列创建唯一性索引 uniq_idx_exam_id、在tag列创建全文索引 full_idx_tag。

create index idx_duration on examination_info(duration);
create unique index uniq_idx_exam_id on examination_info(exam_id);
create fulltext index full_idx_tag on examination_info(tag);

8 DBA常用命令

新建用户
授权
回收权限
数据的备份(数据的导入和导出)

数据的导出:

注意:在windows的dos命令窗口中
mysqldump 数据库>D:\数据库.sql -uroot -p密码
也可以导出指定的表:
mysqldump bjpowernode emp>D:\bjpowernode .sql -uroot -p密码

数据导入:

注意:需要先登录到mysql数据库服务器上。
然后创建数据库:create database bjpowernode;
使用数据库:use bjpowernode;
然后初始化数据库:source D:\bjpowernode.sql

9 数据库三范式

数据库设计范式:数据库表的设计依据,教你怎么进行数据库表的设计。

第一范式:要求任何一张表必须有主键,每一个字段原子性不可再分。
第二范式:建立在第一范式的基础上,要求所有非主键字段完全依赖主键,不要产生部分依赖。
第三范式:建立在第二范式的基础上,要求所有非主键字段直接依赖主键,不要产生传递依赖。

三范式是面试官经常问的,一定要熟记于心!!!

设计数据表的时候,按照以上的范式进行,可以避免表中数据的冗余,空间的浪费。

总结数据库表的设计:
一对一,第二张表外键唯一(fk+unique)
一对多,两张表,多的表加外键!
多对多,三张表,关系表两个外键!

嘱咐:
数据库设计三范式是理论上的,实践和理论有的时候有偏差。
最终的目的都是为了满足客户的需求,有的时候会拿冗余换执行速度。
因为在SQL中,表和表之间连接次数越多,效率越低。(笛卡尔积)
有的时候可能会存在冗余,但是为了减少表的连接次数,这样做也是合理的,并且对于开发人员来说,SQL语句的编写难度也会降低。

参考链接

Tomcat处理一个HTTP请求的过程
Mysql学习总结

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值