欢迎光临散文网 会员登陆 & 注册

0731-MySql(2)

2023-07-31 20:20 作者:GHWNM  | 我要投稿


----------------------------------------------------------以下的可以看作跟=,<,>等等一样的特殊运算符----------------------------------------

模糊查询(低效率):

like 

% 替换0,1或以上的字符

_ 替换1个

rlike

这个是以正则查找

用法示例:select name from students where name rlike "^周.*";


范围查询

in 在某个非连续范围内 ;not in 反之

select name,age from students where age in (12,18,34);

between 在某个连续的范围内(包含头包含尾) ; not between 反之 但是这是一种固定用法 不能age not (between 18 and 34),会挂

select name,age from students where age not between 18 and 34;


判断空

is null; 或者 is NULL;

is not null; 反之

select name,height from students where height is null;


到此为止------------------------------------------------------------------------------------------------------------------------------------------


聚合函数(可以就看作python里一样的函数)

count 计数

select count(*) as 男性人数 from students where gender = "男";

select count(*) as 女性人数 from students where gender = "女";

# 前面应该记录过as...吧?


max/min 最大/最小值

select max(age) from students where gender = 2;

select min(height) from students where gender = 1;


sum 求和

select sum(age) from students;


avg 求平均值

select avg(age) from students;

说了这么多,这个应该也看出来了可以支持运算的,所以还可以这么写

select sum(age)/count(*) from students;


round 保留小数位数,【四舍五入】

select round( (sum(age)/count(*)) , 2 ) from students;

# C语言底层在内存中存储数据的时候都是约等于,而绝大多数语言的解释器都是用C语言编写的,所以他们也会约等于,就产生了误差

# 而在银行等等这些对数据要求很精密的地方,直接把数据扩大多少倍(100,1000,1^4...),最终记得要除上相同的倍数

# 总之,这种不能有误差的地方在存储的时候不要用小数


select round(avg(height), 2) from students;

如果round前面加个name,那是不能的,会挂,需要用到接下来的功能-->分组


分组(一般跟聚合一起用)

group by

select gender from students group by gender; --根据性别分组

前面写上条件,要唯一能标记这个组的条件

跟聚合函数混在一起:

select gender,count(*) from students group by gender;

这时候是把分的组里面的每个元素进行操作,不是对原表操作

而且不止count,刚才所学的所有的聚合函数都能使用

select gender, round(sum(age)/count(*),2) from students group by gender;

还可以写上group_concat(name)来把具体的name拿出来,还可以加条件,加在group by前面

select gender,group_concat(name, age, id) from students where gender=1 group by gender;

group_concat实际上是把这几个东西链接在一起显示出来

所以上面是这仨东西连在一起输出的,那么我们可以在中间加任意字符分割,就是这样group_concat("名字:",name, ",年龄:", age, ",ID:", id)


having

这个感觉跟在group前面加where很像

select group,group_concat(name),avg(age) from students group gender having avg(age) > 30;

但是他跟where还是不一样,having是对这个组进行判断,where是直接对原表进行判断


链接查询:多个表的关联查询

# 回顾 外键:存的是某个表的主键,帮我们限制数据的范围

直白来讲,就是把多个表中的共有数据取出来查询

一共分为三种:

1. 内连接查询

inner join --固定语法,不能拆开

--      表A     表B

select * from students inner join classes;

这个就是简单的把俩表合起来,只是语法正确而已


on 后面加条件

select * from students inner join classes on students.cls_id = classes.id;

这个是找的到的就合并并显示,找不到的干脆不会显示,也就是超过3(因为classes表id一共三个)的

这个合并是咋合并呢,很简单,直接把俩拼接一起(

就是左边是表A所有符合On的数据,右边是所有对应的表B的数据

可以分别让他显示一部分,就像这样

select students.*, classes.name from students inner join classes on students.cls_id = classes.id; --可以短一点,用as

select s.*, c.name from students as s inner join classes as c on s.cls_id = c.id;

总结下,on后面的对的上的话(产生交集),他就取两个表的交际部分一一对应,你也有,他也有才显示

还可以跟order by结合,好像是个排序的玩意,反正前面讲过...应该

select c.name, s.* from students as s inner join classes as c on s.slc_id = c.id order by c.name,s.id;


左连接和右连接(大体都是外连接):

直白来讲:内间接取交接,左连接是哪个表在左边,以这个表为基准去取东西,取不出来的默认为null

语法(左连接)left join --还真是好理解(

select c.name, s.* from students as s left join classes as c on s.slc_id = c.id order by c.name,s.id

这个输出结果会多三个,这仨是右边找不到的,会显示null

再和前面结合下

select c.name, s.* from students as s left join classes as c on s.slc_id = c.id order by c.name,s.id where c.id is null;

where c.id is null 跟 having c.id is null一样的


自关联:自己其中一个字段跟另一个字段关联

比如地址

id   name  pid

1     xxx1      null

2     xxx2      null

3     xx1        2

4     xx2        2

5     x1     3

6     x2         3

就像这样,pid表示他的上级(老大)


子查询:比子关联稍微慢一点

一个select里面套另外一个select

select * from students where height = (select max(height) from students);



数据库(表)设计:

有专业的软件可以设计,如果大公司还有专门的人员负责

继软件三大范式之后,数据库设计三大范式(其实有8种,但是一般前三种就够):

1NF: 一个数据一个字段,不要一堆数据塞一个字段里,要求把每个信息拆成一个字段

2NF:如果表里面的主键有多个字段组成,直接依赖于所有的主键,我理解就是如果有别的主键就把他专门拆开拆成一个新的数据表,新表有个外关联跟原本的表关联

3NF:如果一堆信息都依赖于某个主键,那个主键依赖于另一个主键,那他们不能把信息都塞一个表里

什么意思呢,就是比如一个订单表

里面有订单ID,订单信息,客户ID,客户信息

那么客户ID依赖于订单ID对吧,那他们就要拆开

订单ID单独一张表,里面有订单信息,ID和客户ID

客户ID单独一张表,这样的话如果这个客户多次下单就不会出现重复的客户信息了


这三大范式遵循了可以达到节省空间的效果,极大的缩减了数据的规模和重复性

而且把这个拆分成这样就解耦了,这个有点像MVC架构奉行的理念,高内聚,低耦合,各干各的

这就是为什么叫关系型数据库,关系非常强,后面还会学的NoSql等等非关系型数据库这些就不一样,他们是一张表就是一张表,没有任何关系


E-R模型

E(entry)实体,就像一个类一样,一个抽象的模板

R(relationship)关系,描述两个实体间的规则,可以为一对一,多对一等等,这个也是需要一个字段来描述的

一对一和多对一很简单,都是在左边加,但是多对多呢

多对多有点麻烦,得新开个表,存储每个表的主键,这样的表我们称之为聚合表


python操作mysql

流程:导入-->创建connection对象-->创建cursor-->执行mysql语句...-->关闭cursor-->关闭connection对象-->结束

基本就是操作中间部分,其他都是差不多固定的

    conn = connect(host="localhost", port=3306, user="root", password="123456", database="jing_dong", charset='utf-8')

    cs1 = conn.cursor()

    

    cs1.execute("--执行的sql语句")

    # 这个东西的返回值是生效的行数,也就是所查询到的行数,要数据的话就调游标对象对应的行数

    cs1.fetchone()  # 这个是一条一条取,返回元组类型

    cs1.fetchmany() # 返回个元组套元组,里面输入的参数决定返回几个,


sql注入攻击

就是直接写sql语句进去,让原本的name,变成一个sql语句

原来有个网址,乌云WooYun,东哥原来经常进去看,确实能学到不少东西,有帮人经常把他们sql攻击的图片啥的全截图下来发上去晒

后来东哥自己去试了下把某通快递公司的订单号全给拿出来了,里面收货人的手机号,地址啥的全都有

而且人家明明告诉了某通说让他改,人就是不改,后来什么中通啊,圆通啊,国通啊数据都泄露了,反正各大企业都泄露了

(网址已经被封了,被国家约谈了,抓了百多个人进去,现在法律规定,只要获取个人信息累加50条以上就寄了)

[我还真找到乌云遗产了,甚至找到个群和乌云的网址备份,15年的群了,8年了居然还没挂,具体信息存储于本篇附件内,不会跟笔记一起发布]

以及其实可以试试我自己写个mysql注入的字典,存txt里,里面写有可能的sql注入语句,程序接收返回结果,用循环自动化测试

找到结果后记录到log里,不过这应该是个很长的过程,而且几乎找不到测试案例,只能希望自己写个网站或者试试阿三哥的那个平台能不能用吧



    


    cs1.close()

    conn.close()


0731-MySql(2)的评论 (共 条)

分享到微博请遵守国家法律