总结10
总结10
多表查询
笛卡尔积
多表查询的简单粗暴方式是笛卡尔积:select * from emp,dep;
这种方式的查询是将两表中的记录两两结合,所以结合为mxn条记录,不过内部有大半的数据为无效数据,所以不可能使用这种方式查询表,即使可以通过后面筛选掉无效数据,这一步骤也会带来平方级别的时间损耗。
所以一般使用另外两种查询方式
连表查询
- inner join内连接
- left join左连接
- right join右连接
- 左sql union 右sql 全连接
这四种连接中几乎只使用第一种,因为内连接连接的是两者都有关联的数据,而其他的连接方式,即使在另一张表中没有对应的关系,也会展示出来,只会在强调一张表的记录时,才会使用。
-
内连接(及左右连接的)用法:
select .. from t1 inner join t2 on t1.field1=t2.field2
其中on后的是判断依据,是两张表中互相呼应的两个字段(一般会有外键相连,也可以不以外键)
-
全连接的用法是:
select .. from 左连接表 union select .. from 右连接表
连表查询的结果相对于子查询更适合目标字段分散在多张表中。
子查询
将一条select的sql语句的结果作为表,通过这个表进行二次查询的方式就是子查询。
子查询的结果有两种形式,分别适用不同的场景:
-
子查询只有一个字段,结果是单列的
这种结果适合做where后的成员运算用来筛选
-
子查询有多个字段,结果是多列的
这种结果适合做from后的查询表,通过起别名的方式,我们可以对其中的字段进行抓取。
甚至可以对多个子查询的结果表进行连表拼接。
第三方模块之pymysql
模块使用
-
安装模块
pip install pymysql
(终端环境) -
建立与mysql的连接
conn = pymysql.connect( host='127.0.0.1', # 与本地数据库建立连接,可以尝试其他电脑的ip地址 port=3306, # 端口可写可不写,默认3306 user='root', password="111", database="navicat_test1", # 选择一个库,关键字可以简化为db charset="utf8mb4", autocommit=True # <---自动确认增删改 ) # 更多参数可以点进connect的源码去看
-
产生游标对象
cursor = conn.cursor() # 括号内不填写额外参数 数据是元组 指定性不强 [(),()] cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # [{},{}]
-
编写sql
sql = "select * from class"
-
交由服务端执行
affect_rows = cursor.execute(sql) # 返回sql影响的数据行数
-
获取执行的结果
cursor.fetchone() # 从当前位置 拿到一条执行结果 cursor.fetchall() # 拿到所有结果 cursor.fetchmany(n) # 从当前位置 拿到多个结果
-
移动执行结果查看光标
cursor.scroll(1,'relative') # 基于当前位置往后移动 cursor.scroll(0,'absolute') # 基于数据的开头往后移动
sql注入问题
通过构造sql语法来避开我们正常业务逻辑的问题。
这类问题现在已经比较少了,是通过限制一些字符的输入来避免sql语法的形成。
这个限制的过程pymysql也已经帮助我们做了,我们不要自己将用户输入的字符串与sql语句直接拼接了,直接通过execute(带%s的伪sql,(元组字符串元素按位置传入%s))
sql = " select * from a_pro_user.teacher where name=%s and pwd=%s " # 用占位符来占位
cursor.execute(sql, (username, password(password)) # 直接在execute方法中用元组参数的方式传入占位字符。
而关于py模块的sql语句,也可以一次多次重复执行,并一次传入多个参数,如我们要插入多条数据:
sql = "insert into a_table values(%s,%s,%s)"
executemany(sql,[(),(),(),()...]) #一次用列表元组执行,方法名是executemany()
mysql概念补充
视图
将表的一次查询结果存储起来方便下次使用。
使用时注意:
- 视图表不能增删改,器数据来自其他真实的表
- 拒绝滥用,防止其与真实表相混淆
语法:create view 视图名 as 查询sql语句
create view teacher2course as
select * from teacher inner join course on teacher.tid = course.teacher_id;
修改休止符-存储过程-函数
修改休止符:delimiter 符号
这个语法的必要性是因为以下两个功能:
存储过程
是自定义的函数,将sql语句封装起来以便下次使用,神奇的是,这个存储过程是存在我们的数据库中,所以退出程序后依然可以在下次登录后继续使用。
详细语法如下:
delimiter $$
create procedure p1( # 存储过程名
in m int, # in表示这个参数必须只能是传入不能被返回出去
out res int # out表示这个参数可以被返回出去,还有一个inout表示即可以传入也可以被返回出去
) # 创建存储过程
begin # 子代码开始
select * from cmd; # 因为修改了休止符所以这里sql语句没有结束
set res=0; # 从外面可以拿到
end $$ # 子代码结束并以$$结束
delimiter ; # 改回原本的休止符
# 返回值需要在定义前定义
set @res=10; # 定义
call p1(1,@res) #调用存储过程
call p1(1,10) # 报错
select @res #查看
# pymysql使用
cursor.callproc('p1', (1,10)) # 这个可以直接传,内部帮我们定义过了
cursor.execute("select @_p1_1") # 这里的1指的是参数位置,对应的是第二个参数
# 0参数位置对应第一个参数
函数
类似于python中的内置函数,sql本身存储的一些可调用的方法
常用的方法有:
可以看成是python中的内置函数
"ps:可以通过 help 函数名 查看帮助信息!"
# 1.移除指定字符
Trim、LTrim、RTrim
# 2.大小写转换
Lower、Upper
# 3.获取左右起始指定个数字符
Left、Right
# 4.返回读音相似值(对英文效果)
Soundex
"""
eg:客户表中有一个顾客登记的用户名为J.Lee
但如果这是输入错误真名其实叫J.Lie,可以使用soundex匹配发音类似的
where Soundex(name)=Soundex('J.Lie')
"""
# 5.日期格式:date_format
mysql中的时间和python中的datetime数据类型类似。
# 按照年月来分组
select date_format(sub_time,'%Y-%m'),count(id) from blog group by date_format(sub_time,'%Y-%m');
- where Date(sub_time) = '2015-03-01' # date代表年月日
- where Year(sub_time)=2016 AND Month(sub_time)=07; # 时间每一段可以单独筛选
# 更多日期处理相关函数
adddate 增加一个日期
addtime 增加一个时间
datediff计算两个日期差值
触发器
类似于魔法方法,当然也是存储在数据库中,可以随时触发。
创建触发器:
# 与存储过程一样,需要用到delimiter来改休止符
create trigger 触发器的名字 before/after insert/update/delete on 表名 for each row
begin
sql语句
end
# 命名:tri缩写_前后_操作_针对的表
查看和删除triggle的sql:
# 查看所有的触发器
show triggers;
# 删除触发器
drop trigger tri_after_insert_cmd;
事务
事务的四大特性(ACID)
-
a - atomatic 原子性
事务的一系列操作要么全部生效要么都不生效
-
c - consistent 一致性
事务前后的两种状态在某个方面是一致的
-
i - isolation 隔离性
每个事务之间是相互隔离的
-
d - durable 持续性
又称永久性,生效后不再拥有回滚属性,永久生效
事务的操作
- 开启事务:
start transaction
- 设置额外回滚点:
savepoint 回滚点名;
- 回滚事务:
rollback;
|rollback 回滚点名;
- 确认生效:
commit
sql中的隔离级别
在SQL标准中定义了四种隔离级别,每一种级别都规定了一个事务中所做的修改
InnoDB支持所有隔离级别
set transaction isolation level 级别
- read uncommitted(未提交读)
事务中的修改即使没有提交,对其他事务也都是可见的,事务可以读取未提交的数据,这一现象也称之为"脏读" - read committed(提交读)
大多数数据库系统默认的隔离级别
一个事务从开始直到提交之前所作的任何修改对其他事务都是不可见的,这种级别也叫做"不可重复读" - repeatable read(可重复读) # MySQL默认隔离级别
能够解决"脏读"问题,但是无法解决"幻读"
所谓幻读指的是当某个事务在读取某个范围内的记录时另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录会产生幻行,InnoDB和XtraDB通过多版本并发控制(MVCC)及间隙锁策略解决该问题 - serializable(可串行读)
强制事务串行执行,很少使用该级别
多版本并发控制(MVCC)
MVCC只能在read committed(提交读)、repeatable read(可重复读)两种隔离级别下工作,其他两个不兼容(read uncommitted:总是读取最新 serializable:所有的行都加锁)
特征:读不加锁,读写不冲突。在读多写少的OLTP应用中,读写不冲突是非常重要的,极大的增加了系统的并发性能,这也是为什么现阶段,几乎所有的RDBMS,都支持了MVCC。
在MVCC并发控制中,读操作可以分成两类:快照读 (snapshot read)与当前读 (current read)。快照读,读取的是记录的可见版本 (有可能是历史版本),不用加锁。当前读,读取的是记录的最新版本,并且,当前读返回的记录,都会加上锁,保证其他事务不会再并发修改这条记录。
流程控制
# 分支结构
declare i int default 0;
IF i = 1 THEN
SELECT 1;
ELSEIF i = 2 THEN
SELECT 2;
ELSE
SELECT 7;
END IF;
# 循环结构
DECLARE num INT ;
SET num = 0 ;
WHILE num < 10 DO
SELECT num ;
SET num = num + 1 ;
END WHILE ;
索引
索引
索引相关概念
索引是帮助我们快速获取数据的方法,索引在MySQL中也叫做“键”,是存储引擎用于快速找到记录的一种数据结构。
mysql中的索引
- primary key 主键
- unique key
- index key
这三种键都带有键属性,也就是索引属性,都可以加快字段数据的搜索,其中主键是帮助我们快速搜索所有记录的索引键。注,外键并不属于索引。
这些结合原理会更好理解
索引底层机制
建立索引会采取各种各样的策略,其中很多采取B+树的构造策略。
B+树是基于B树做优化的结构,它们都是有序的多叉树,可以通过当前遍历的节点找到目标节点处于那一部分,从而缩短搜索的路程。
B树的根节点、树枝节点、叶子节点等所有节点都会存储记录的全貌,而B+树则将这些节点都只存储到叶子节点中,根节点和树枝节点只存储索引键值,并且B+树的叶子节点间也有指向相邻记录的指针,方便按顺序索引。
一些小概念
聚集索引与辅助索引
- 聚集索引就是通过B+树的根节点、树枝节点存储主键,叶子节点存储记录的所有数据。
- 辅助索引就是通过B+树的根节点、树枝节点存储其他键,叶子节点存储对应的主键。
所以我们通过辅助索引的键字段寻找不同字段的时候,实际上是先通过辅助索引找到对应的主键,然后在通过聚集索引找到对应的记录,再取出相应字段。
这个过程也称为非覆盖索引。
慢查询优化
explain sql语句的方式检测sql语句的扫描效率,分为7个等级
1)index 我们只要避免是最差的index等级就可以了。
2)range
3)ref
4)eq_ref
5)const
6)system
7)null
前端http协议及html
http协议
socket层之上的应用层也需要客户端和服务端之间进行协定才能交互,而http协议就是负责BS架构的软件的前端交互。
http协议有一类包括html、css、js,分别负责前端内容、样式、动效等内容。
html是什么?
- 超文本标记语言(Hypertext Markup Language, HTML)是一种用于创建网页的标记语言。
- 本质上是浏览器可识别的规则,我们按照规则写网页,浏览器根据规则渲染我们的网页。对于不同的浏览器,对同一个标签可能会有不同的解释。(兼容性问题)
- 网页文件的扩展名:.html或.htm
html四大特性
-
基于请求响应
B浏览器发送请求,S服务端回应响应,请求和响应都基于一定的格式
-
基于tcp、ip作用于应用层之上的协议
-
无状态
服务端不会保护客户端的状态,每次输入网址都相当于浏览器第一次访问服务端
-
无/短链接
浏览器客户端发送请求后,服务端短暂的将html文件发送回去,后续两端不保持连接
请求和响应格式
-
请求格式
请求首行(请求方式有很多的协议版本) 请求头(一大堆kv键值对) 换行\r\n 请求体(存放敏感信息,并不是所有的请求都有请求体)
-
响应格式
响应首行(状态码 协议版本) 响应头(一大堆kv键值对) 换行\r\n 响应体(给浏览器展示的数据)
响应状态码
状态码 | 意义 |
---|---|
1xx | 服务端已经接收到了你的请求正在处理,客户端可以继续发送或者等待 |
2xx | 200 OK 请求成功,服务端发送了对应的响应 |
3xx | 重定向(想访问网页A但是自动调到了网页B) 302临时跳转一定操作后返回原网页,304永久跳转到一个界面 |
4xx | 客户端问题导致无法访问 403访问权限不够,404请求资源不存在 |
5xx | 服务端问题导致无法访问 |
在一些项目中,我们可能还会自己定义一些状态码,通常以10000打头。
html文档结构
响应体可以返回很多内容,而内容最好使用html文件,其基本结构为:
<!DOCTYPE html> 声明html5文档
<html lang="en"> <!---lang属性是对html中语言进行说明,en表英文,ch表中文--->
<head> 给浏览器头部的
<meta charset="UTF-8">
<title>本地页面</title>
</head>
<body>
浏览器主题显示
</body>
</html> html页面的根元素
html文件之标签
html文本就是有各种各样的标签组成的,标签会被浏览器实时的渲染成页面上的各种小组件。
html标签分类
-
单标签:有
<img/>
之类,其特点就是单个标签就闭合了格式:<标签名 属性1=“属性值1” 属性2=“属性值2”…… />
-
双标签:有
<head></head>
等,除了标签,两个对应标签中间所包含的文本也是这个标签的内容,双标签之间也可以按照一定的方式嵌套,标签中塞标签格式:<标签名 属性1=“属性值1” 属性2=“属性值2”……>内容部分</标签名>
-
行内标签:只能存在于行中的标签,随内容的大小而定。
-
块级标签:自己独占一行,p标签为最小的块级标签。
一般来说块级标签可以包含行内标签和其他块级标签,但是p标签只能包含行内标签。
head内的标签
-
title网页小标题
-
meta定义网页源信息
-
style内部支持编写css代码
-
link引入外部css文件
<link rel="stylesheet" href="mycss.css">
-
script支持内部编写js代码,也可以引入外部js代码
引入 <scipt src="js文件.js"></script>
body内的标签
基础标签
- b\i\u\s 加粗、斜体、下划线、删除线
- p段落标签
- h1~h6标题标签
- br换行标签
- hr水平线标签
特殊符号
-  
- >
- <
- &
- ¥
- ©
- ®
布局标签
div标签和span标签,分别是块级标签和行内标签,主要帮助我们最开始构筑html
img标签
显示图片的标签
- src属性:图片路径
- alt:加载失效时显示
- title:图片名称,悬停时展示
- width height:图片宽高,只设置一项时等比缩放
a标签
超链接标签,点击可调转指定网页
- href属性:指定网页url,指定相对url,指定业内id
- target属性:指定跳转方式,
_blank
新建空白页跳转,_self
从当前页跳转
列表标签
-
无序列表
ul - li
-
有序列表
ol - li
-
标题列表
表格标签
table - thead | tbody - tr - th|td
form标签
input系列标签
name属性:键
value属性:值或者默认值
type属性值:
- text 文本
- password 密文
- date 日期
- checkbox 复选框
- radio 单选框 多个单选或者复选框应该写同一个name属性值联系,可以用checked默认选中
- submit 提交按钮
- reset 充值按钮
- buttom 空白按钮
- hidden 隐藏输入框
- file 文件选择按钮 可以加multiple属性,多选文件
select标签
下拉框,内部+option文件提供下拉选项,name属性在select中,value在option中
textarea文本框
提供文本框区域供用户输入,可以设置一些属性。
css样式
对选定的html标签的样式进行调整。
选择器 {样式名:属性}
导入css的多种方式:
- style标签中直接书写
- link引入css文件
- 标签内部通过style属性直接编写(内联样式)
选择器
一个标签可以从标签类型,id属性和class属性来划分
基础选择器:
- 标签选择器:div{}
- id选择器:#d1{}
- 类选择器:.c1{}
- 通用选择器:*{}
组合选择器:
- 后代选择器:选择器1 选择器2
- 儿子选择器:选择器1>选择器2
- 毗邻选择器:选择器1+选择器2
- 弟弟选择器:选择器1~选择器2
组合嵌套:
-
组合:逗号隔开多个选择器,合并所有的选择结果做样式调整
选择器1,选择器2
-
嵌套:两个选择器紧贴,选择两个选择器都要满足的标签
标签选择器属性选择器(或类选择器)
属性选择器:
- [属性名]:含这个属性的标签
- [属性名]="属性值":属性的值满足的标签
- div[属性名]="属性值":标签选择器嵌套属性选择器
伪类选择器:
对标签的某种状态的样式进行修改
- a:hover:a标签的光标悬停状态
- input:focus:input标签的获取焦点状态
伪元素选择器:
通过css的方式给首字母设置大小,前后加入内容。
以这种方式添加的内容,html页面中无法选中,可应用于简单的防爬。
选择器优先级:
- 内联优先最高,因为其最近也最精准
- 就近原则,越晚加载的最终生效
- 就精原则,id选择器>类选择器>标签选择器
- 打破优先级,样式后面添加关键字,
样式 !important,
样式调节
文字属性名:
- font-size
- font-weight
- color
- text-align
- text-decoration
- text-indent
颜色属性值:
#颜色代号
|颜色名
|rgb和rgba
背景属性:
- background-size|-color|-image|-repeat|-position
这些前缀相同的属性一般都可以在前缀属性中直接整合:background
隐藏属性:
-
display:none
-
visibility:hidden
边框:border
- border:5px solid red;
- border-width:一二三四个参数分别代表着分别对四条表进行设置
盒子模型:margin|border|padding|content
- margin与padding的用法与border的用法相似,也可以分开和统一设置每边
- 对齐看真实边界,margin和padding不会叠加。
浮动:
-
浮动将标签从一个平面拉出来,可以将默认上下布局调整成左右布局
-
浮动可能会导致父标签塌陷,用
.clearfix
固定格式处理,.clearfix:after { content:''; /*加一个空内容*/ display: block; /*将这个标签设置为块级标签*/ clear: both; /*两侧都不能有浮动标签标签*/ }
溢出:overflow
- hidden属性值,修剪多余内容
- scroll属性值,只展示在限定范围,可滚动
定位:
定位 | 属性值 | 描述 |
---|---|---|
静态定位 | static | 标签的位置不能被参数修改,随文件流安排位置 |
相对定位 | relative | 标签的位置相对原本所在的位置做移动,但文件流所占的位置不变 |
绝对定位 | absolute | 标签的位置相对已定位的父标签参照做改动,但不占据文件流的空间 |
固定定位 | fixed | 相对于浏览器的窗口是不动的,也不占据文件流空间 |