初来乍到,在到明年全面投入到考研之前这段时间,我将在此记录我的学习历程,大致方向:Web 安全-->渗透测试-->红蓝对抗,将近一年的时间,每天学习记录,每周总结更新。
关系型数据库通过外键关联来建立表与表之间的关系,非关系型数据库通常指数据以对象的形式存储在数据库中,而对象之间的关系通过每个对象自身的属性来决定 。
https://uule.iteye.com/blog/2429681 https://www.cnblogs.com/wanghongyun/p/6193912.html https://www.cnblogs.com/lina520/p/7919551.html
用于保存整数,常见的有 tinyint ,smallint ,mediumint ,int ,bigint
MariaDB [test]> create table people( - > name varchar(32) not null default '' comment '用户名', - > age tinyint unsigned not null default 0 comment '年龄' - > )charset=utf8 engine=myisam;Query OK, 0 rows affected (0.013 sec)
zerofill 叫做0填充
举例说明:
MariaDB [test]> create table test( -> num int, -> num2 int(4) zerofill, -> num3 int(4) unsigned zerofill);Query OK, 0 rows affected (0.014 sec)
当 int(4) zerofill 使用,如果添加的整数不够 4 位,则数值的左边使用 0 进行填充.
MariaDB [test]> insert into test values(1,23,345);Query OK, 1 row affected (0.010 sec)MariaDB [test]> select * from test;+------+------+------+| num | num2 | num3 |+------+------+------+| 1 | 0023 | 0345 |+------+------+------+1 row in set (0.000 sec)
int(4) 不能理解成最大只能是 4 位的数,而应该理解成是 0填充的宽度
MariaDB [test]> insert into test values(1,23456,34567);Query OK, 1 row affected (0.004 sec)MariaDB [test]> select * from test;+------+-------+-------+| num | num2 | num3 |+------+-------+-------+| 1 | 0023 | 0345 || 1 | 23456 | 34567 |+------+-------+-------+2 rows in set (0.000 sec)
当一个字段被 zerofill 修饰时,那么这个字段就自动成为 unsigned
MariaDB [test]> insert into test values(1,-1,34567);ERROR 1264 (22003): Out of range value for column 'num2' at row 1
MariaDB [test]> create table test2(id int zerofill,age int);Query OK, 0 rows affected (0.040 sec)MariaDB [test]> insert into test2 values(1,18);Query OK, 1 row affected (0.005 sec)MariaDB [test]> select * from test2;+------------+------+| id | age |+------------+------+| 0000000001 | 18 |+------------+------+1 row in set (0.000 sec)
bit 类型就是位类型
MariaDB [test]> create table test10(id int,a bit(7));Query OK, 0 rows affected (0.005 sec)MariaDB [test]> insert into test10 values(1,64);Query OK, 1 row affected (0.010 sec)MariaDB [test]> select * from test10;+------+------+| id | a |+------+------+| 1 | @ |+------+------+1 row in set (0.000 sec)这里有一个困惑:a 这个字段,bit 位数为 7 的时候刚好,小了不行解惑:bit(1) 这里 1 呢 就是一个 bit 位,意思是只能有 1 位来表示你的数据,就只能表示 0 和 1
可见,bit 字段在显示时,按照对应的 ascii 码对应的字符显示
MariaDB [test]> select * from test10 where a=64;+------+------+| id | a |+------+------+| 1 | @ |+------+------+1 row in set (0.000 sec)MariaDB [test]> select * from test10 where a='@';Empty set, 1 warning (0.001 sec)
float(4,2)表示的范围是 -99.99~99.99float(4,2) unsigned 表示的范围是 0-99.99decimal(5,2)表示的范围是 -999.99~999.99decimal(5,2) unsigned 表示的范围是 0-999.99指定长度,指定小数点位数
MariaDB [test]> create table `user300`( -> id int unsigned not null default 0, -> name varchar(64) not null default '', -> post_code char(6) not null default '' -> )charset=utf8 engine=myisam;Query OK, 0 rows affected (0.013 sec)MariaDB [test]> insert into user300 values(100,'你好','hello');Query OK, 1 row affected (0.010 sec)MariaDB [test]> select * from user300;+-----+--------+-----------+| id | name | post_code |+-----+--------+-----------+| 100 | 你好 | hello |+-----+--------+-----------+1 row in set (0.002 sec)
注意:
char(4) 是定长 这里既是插入的是 'aa' ,也是占用分配的4个字节varchar(4) 是变长,如果插入了 'aa' ,实际占用空间大小是L+1L:实际数据的长度加的一个字节用来记录长度
date,datetime,timestamp
MariaDB [test]> create table `user901`( -> id int, -> birthday date, -> cardtime datetime, -> login_time timestamp -> )charset=utf8 engine=myisam;Query OK, 0 rows affected (0.010 sec)MariaDB [test]> insert into user901 values(100,'2019-8-3','2019-8-8 8:8:4','2011-1-11 11:22:33');Query OK, 1 row affected (0.009 sec)MariaDB [test]> select * from user901;+------+------------+---------------------+---------------------+| id | birthday | cardtime | login_time |+------+------------+---------------------+---------------------+| 100 | 2019-08-03 | 2019-08-08 08:08:04 | 2011-01-11 11:22:33 |+------+------------+---------------------+---------------------+1 row in set (0.001 sec)
MariaDB [test]> create table `user902`( -> id int unsigned not null default 1, -> hobby set('A','B','C','D') not null default 'A' comment '选项', -> sex enum('男','女') not null default '男' comment '性别' -> )charset=utf8 engine=myisam;Query OK, 0 rows affected (0.009 sec)MariaDB [test]> insert into user902 values(100,'A','男');Query OK, 1 row affected (0.000 sec)MariaDB [test]> insert into user902 values(200,'A,B','男');Query OK, 1 row affected (0.000 sec)MariaDB [test]> select * from user902;+-----+-------+-----+| id | hobby | sex |+-----+-------+-----+| 100 | A | 男 || 200 | A,B | 男 |+-----+-------+-----+2 rows in set (0.002 sec)
MariaDB [test]> insert into user902 values(300,'C',1);Query OK, 1 row affected (0.000 sec)MariaDB [test]> insert into user902 values(400,'D',2);Query OK, 1 row affected (0.000 sec)MariaDB [test]> select * from user902;+-----+-------+-----+| id | hobby | sex |+-----+-------+-----+| 100 | A | 男 || 200 | A,B | 男 || 300 | C | 男 || 400 | D | 女 |+-----+-------+-----+4 rows in set (0.000 sec)
A B C D1 2 4 67 => 1+2+4
要借助函数select * from user where find_in_set('A',hobby);find_in_set('A',hobby) 返回'A'在 hobby 集合中处于第几位
通常不会直接存储在数据库汇中,实际开发中存放的是路径地址,然后通过地址去读取。
head_img varchar(64) //存储路径
MariaDB [test]> create table employee( -> id int unsigned not null default 0 comment '雇员id', -> name varchar(64) not null default '' comment '姓名', -> sex enum('男','女','保密') not null default '保密' comment '性别', -> birthday date not null comment '生日', -> entry_date date not null comment '入职时间', -> job varchar(32) not null default '' comment '职位', -> salary decimal(10,2) not null default 0.0 comment '薪水', -> resume text not null comment '个人介绍' -> )charset=utf8 engine=myisam;Query OK, 0 rows affected (0.004 sec)
MariaDB [test]> insert into employee values(100,'小妖怪','男','2001-10-11','2012-11-11','巡山',2300.00,'大王.我来巡山');Query OK, 1 row affected (0.001 sec)MariaDB [test]> insert into employee values(200,'老妖怪','女','1999-10-11','2010-11-11','捶背',4300.00,'我给大王捶背');Query OK, 1 row affected (0.000 sec)
MariaDB [test]> select * from employee;+-----+-----------+-----+------------+------------+--------+---------+-----------------------+| id | name | sex | birthday | entry_date | job | salary | resume |+-----+-----------+-----+------------+------------+--------+---------+-----------------------+| 100 | 小妖怪 | 男 | 2001-10-11 | 2012-11-11 | 巡山 | 2300.00 | 大王叫我来巡山 || 200 | 老妖怪 | 女 | 1999-10-11 | 2010-11-11 | 捶背 | 4300.00 | 我给大王捶背 |+-----+-----------+-----+------------+------------+--------+---------+-----------------------+2 rows in set (0.002 sec)
登录 MySQLMySQL -u root -p --dafault-character-set=latin1进入 MySQL 之后 set names gbk;
修改表,就是指,当我们的表创建好了,根据业务逻辑的需要, 我们要对表进行修改(比如 修改表名, 增加字段,删除字段,修改字段长度,修改字段类型)。
1.在上面员工表增加一个 image 列(要求在 resume 后面) alter table employee add image varchar(64) not null default '' after resume;2.修改 job 列,将其长度改为 60 alter table employee modify job varchar(60) not null default ''; 其实就是重写字段将原来的覆盖3.删除 sex 列 alter table employee drop sex;4.表名修改为 worker rename table employee to worker;5.修改表的字符集 alter table worker character set utf8;6.将列名 name 修改为 user_name alter table worker change name user_name varchar(64) not null default '';
crud 操作,表示是增删改查. c[create] / r[read] / u[update] /d[delete]
insert into tablename [(column1 [,column2,,...])]values (value1 [,value2...]);
字段 id name priceinsert into goods values(10,'可口可乐',3.0);insert into goods (id,name,price) values(20,'小小酥',2.5);insert into goods (id,name) values(30,'红牛');
update tablename set col_name1=expr1 [,col_name2=expr2...] [where expr];
将老妖怪的薪水在原有基础上增加 1000 元update worker set salary=(select salary from worker where user_name='老妖怪')+1000 where user_name='老妖怪';-------------------update worker set salary = salary + 1000 where user_name='老妖怪';
delete from tablename where expr;
create table worker2 like worker; //会创建一张空表,结构与 worker 相同insert into worker2 select * from worker;
select [distinct] *|{column1,column2,column3..} from tablename;如果我们希望过滤重复的数据,则加上 distinct* 号表示将所有的字段都检索出来,一般来说我们开发中不会使用 select * 语句,这种语句会返回所有字段,效率较低如果我们只希望检索某几列,则写清楚字段名就可以我们的使用原则是,需要什么字段,就取回什么字段select distinct * from student;
select *|{column1 | expression,column2..} from tablename;别名写法select name,chinese+english+math from student;select name,chinese+english+math as totalgrade from student;MariaDB [test]> select name,(chinese+english+math)totalgrade from student;+-----------+------------+| name | totalgrade |+-----------+------------+| 韩顺平 | 257.00 || 宋江 | 242.00 || 关羽 | 276.00 || 赵云 | 233.00 || 欧阳锋 | 185.00 || 黄蓉 | 170.00 |+-----------+------------+6 rows in set (0.000 sec)
,<, <,=, >,=, =, <> ,!= betwween ... and ... in(set) like not like is null
- 逻辑运算符
and,or,not
用于排序
select name,math from student order by math desc;select name,math from student order by math asc; //默认升序select name,math from student order by math desc,name asc;
count 函数是进行统计满足条件的记录数有多少条, 是按照分组的形式统计
1.统计班里共有多少学生 select count(*) from student;select count(*) from student where math > 90;
Sum 函数返回满足 where 条件的记录的总和
select sum(math) from student; //返回的结果是班级所有同学数学成绩总和select sum(math)+sum(chinese)+sum(english) from student; //这种写法是一定正确的select sum(math+chinese+english) from student; //这种写法要求所求记录中不能包含空值,数值会出错select sum(chinese)/count(*) from student;
ifnull函数 ifnull(expr1,expr2), 如果 expr1 为 null ,则取 expr2 的值 如果 expr1 不为空,就取第一个表达式的值
select sum(ifnull(math,0.0)+ifnull(chinese,0.0)+ifnull(english,0.0)) from student where id >= 100;
AVG函数返回满足 where 条件的列的平均值
select avg(math) from student;
返回满足 where 条件的列的最大/最小值也需要保证每个字段中不能包含空值
group by 就是对数据(列)进行分组统计, 如果我们需要对分组的结果进行过滤则可以使用关键字 having
select max(salary),min(salary),deptno from emp group by deptno;
亚元表,可以作为一个测试表,可以当做一个空表,没有表用的时候可以拿来用,补位的意思
MySQL> select now() from dual;+---------------------+| now() |+---------------------+| 2019-08-07 01:29:06 |+---------------------+1 row in set (0.01 sec)
MySQL> select charset('nihao');+------------------+| charset('nihao') |+------------------+| gbk |+------------------+1 row in set (0.01 sec)
MySQL> select concat('name:',name,' year:',year) as info from user;+---------------------+| info |+---------------------+| name:huahua year:4 |+---------------------+1 row in set (0.00 sec)
MySQL> select ucase('abc'),lcase('DEF');+--------------+--------------+| ucase('abc') | lcase('DEF') |+--------------+--------------+| ABC | def |+--------------+--------------+1 row in set (0.00 sec)
MySQL> select left('nihao',3);+-----------------+| left('nihao',3) |+-----------------+| nih |+-----------------+1 row in set (0.01 sec)
MySQL> select length('nihao');+-----------------+| length('nihao') |+-----------------+| 5 |+-----------------+1 row in set (0.00 sec)
如图,全部查找,全部替换MySQL> select replace('nihaoyyyyyy','y','!');+--------------------------------+| replace('nihaoyyyyyy','y','!') |+--------------------------------+| nihao!!!!!! |+--------------------------------+1 row in set (0.00 sec)
MySQL> select strcmp('a','a');+-----------------+| strcmp('a','a') |+-----------------+| 0 |+-----------------+1 row in set (0.00 sec)MySQL> select strcmp('a','A');+-----------------+| strcmp('a','A') |+-----------------+| 0 |+-----------------+1 row in set (0.00 sec)------------------------------------------------MySQL> select strcmp('a','b');+-----------------+| strcmp('a','b') |+-----------------+| -1 |+-----------------+1 row in set (0.00 sec)
MySQL> select substring('nihao world',6,6);+------------------------------+| substring('nihao world',6,6) |+------------------------------+| world |+------------------------------+1 row in set (0.00 sec)MySQL> select substring('nihao world',6);+----------------------------+| substring('nihao world',6) |+----------------------------+| world |+----------------------------+1 row in set (0.00 sec)
MySQL> select length(' nihao! ');+----------------------------+| length(' nihao! ') |+----------------------------+| 16 |+----------------------------+MySQL> select length(trim(' nihao! '));+----------------------------------+| length(trim(' nihao! ')) |+----------------------------------+| 6 |+----------------------------------+1 row in set (0.00 sec)
MySQL> select conv(10,10,2);+---------------+| conv(10,10,2) |+---------------+| 1010 |+---------------+1 row in set (0.00 sec)MySQL> select conv(10,10,16);+----------------+| conv(10,10,16) |+----------------+| A |+----------------+1 row in set (0.00 sec)
select casewhen expr1 then expr2when expr3 then expr4else expr5end;
MySQL> select md5('nihao');+----------------------------------+| md5('nihao') |+----------------------------------+| 194ce5d0b89c47ff6b30bfb491f9dc26 |+----------------------------------+1 row in set (0.01 sec)MySQL> select password('nihao');+-------------------------------------------+| password('nihao') |+-------------------------------------------+| *364870DF09C7E82F6A8ED19ED529F3375E57B3CF |+-------------------------------------------+1 row in set (0.00 sec)
计算每个雇员的年薪select (ifnull(sal,0.0)+ifnull(comm,0.0)) * 12 as 年薪 from emp;
select * from emp where sal between 2000 and 3000;select * from emp where sal>=2000 and sal<=3000;
显示首字符为 SS 的员工姓名和工资select ename,sal from emp where 'S'=left(ename,1);select ename,sal from emp where ename like 'S%';
显示第三个字符为大写 o 的所有员工的姓名和工资select ename,sal from emp where ename like '__O%';
显示 empno 为 123 , 234 , 800 的雇员情况select * from emp where empo in (123,234,800);
显示没有上级的雇员情况select * from emp where mgr is null;
select * from emp where (sal>500 or job='MANAGER') and ename like 'J%';
按照工资从高到低的顺序显示select * from emp order by sal;
按照部门号升序而雇员的工资降序排序select * from emp order by deptno,sal desc;
实际查询时,不可能把所有的记录都返回,而是一页一页返回,这是我们就会使用分页查询 (limit)
select 列名 from 表名 limit ($pageNow-1)*$pageSize,$pageSize;
select chinese from student limit 0,1;
select avg(sal),deptno from emp where deptno=20;
显示工资最高的员工和其工作岗位select * from emp where sal=(select max(sal) from emp)
显示工资高于平均工资的员工信息select * from emp where sal>(select avg(sal) from emp);
显示每个部门的平均工资和最高工资select avg(sal),max(sal) from emp group by deptno;
显示每个部门的每种岗位的平均工资和最低工资select avg(sal),max(sal) from emp group by deptno,job;
显示平均工资低于 2000 的部门号和它的平均工资select avg(sal) as myavg,deptno from emp group by deptno having myavg<2000;
同时出现书写顺序 group by、having、order by统计各个部门的平均工资,并且是大于 2000 ,按照平均工资从高到低排序select avg(sal) as myavg from emp group by deptno having myavg>2000 order by myavg desc;
多表查询是指基于两个和两个以上的表或是视图的查询.在实际应用中,查询单个表可能不能满足你的需求,(如显示 sales 部门位置和其员工的姓名),这种情况下需要使用到( dept 表和 emp 表)
select * from emp,dept;
select * from emp,dept where emp.deptno=dept.deptno;
若两表中关联的字段名称不相同,也可以不加表名限制select ename,sal,dname,dept.deptno from emp,dept where emp.deptno=dept.deptno;
显示emp所有字段加dept表中的dnameselect emp.*,dept.dname from emp,dept where emp.deptno=dept.deptno;
select dept.dname,emp.dname,emp.sal from emp,dept where emp.deptno=dept.deptno and emp.deptno=10;
自连接是指在同一张表的连接查询
select * from emp where empno=(select mgr from emp where ename='ford');
select worker.ename,boss.ename from emp as worker,emp as boss where worker.mgr = boss.empno;
子查询是指嵌入在其它 sql 查询语句中的 select 语句,也叫嵌套查询
单行子查询是指只返回一行数据的子查询语句select * from emp where deptno=(select deptno from emp where ename='smith');
多行子查询指返回多行数据的子查询 使用关键字 in
如何查询和 10 号部门的工作相同的雇员的信息,但是不含 10 号部门的雇员。select * from emp where job in (select distinct job from emp where deptno=10)and deptno <>10;
如果我们的一个子查询,返回的 结果是多列,就叫做列子查询
查询和宋江数学,英语,语文完全相同的学生select * from student where (math,english,chinese) = (select math,english,chinese from student where name='宋江');
select ename, sal, temp. myavg,emp.deptno from emp, (select avg(sal) as myavg , deptno from emp group by deptno) as tempwhere emp.deptno = temp.deptno ANDemp.sal > temp. myavg;
合并多个 select 语句的结果,可以使用集合操作符 union,union all
union 合并查询select 语句1 union select 语句2;
两个 sql 语句结果合并返回,而且会去掉重复的记录
union all 和 union 唯一的区别就是 union all 不去重
内连接实际上就是利用 where 子句对多表形成的笛卡尔积进行筛选前面我们使用的那种语法都属于内连接select 列名 from 表1 inner join 表2 inner join 表3 ON 条件 ....
分两种:左外连接,右外连接
select 列名 表1 left join 表2 on 条件;
MySQL> select * from stu;+------+------+| id | name |+------+------+| 1 | name || 2 | jack || 3 | tom || 4 | kity |+------+------+4 rows in set (0.00 sec)MySQL> select * from exam;+------+-------+| id | grade |+------+-------+| 1 | 55 || 2 | 45 || 3 | 89 |+------+-------+3 rows in set (0.00 sec)
select * from stu left join exam on stu.id=exam.id;
MySQL> select stu.id,name,grade from stu left join exam on stu.id=exam.id;+------+------+-------+| id | name | grade |+------+------+-------+| 1 | name | 55 || 2 | jack | 45 || 3 | tom | 89 || 4 | kity | NULL |+------+------+-------+4 rows in set (0.00 sec)
select stu.id,name,ifnull(grade,0) as grade from stu left join exam on stu.id=exam.id;
如果右侧的表完全显示我们就说是右外连接select 列名 from 表1 right join 表2 ON 条件
显示所有分数,没有对应人的分数对应的 name 置为无名MySQL> select stu.id,ifnull(name,'wuiming'),grade from stu right join exam on stu.id=exam.id;+------+------------------------+-------+| id | ifnull(name,'wuiming') | grade |+------+------------------------+-------+| 1 | name | 55 || 2 | jack | 45 || 3 | tom | 89 || NULL | wuiming | 99 |+------+------------------------+-------+4 rows in set (0.00 sec)
约束是用于维护数据的完整性, 所谓数据的完整性指的是,根据业务逻辑的需要,我们将表的某些字段设置成一种约束,从而保证数据的合理性和完整性,比如身份证编号就是唯一,我们就可以使用 unique 这个约束。
create table `user`( id int, name varchar(32) not null default '', email varchar(32) not null default '', primary key (id,name) )charset=utf8 engine=muisam;
当我们希望某个字段的值不能出现重复值时,我们就可以将该字段设置成 unique
用于定义表和和从表之间的关系:外键约束要定义在从表上,主表则必须具有主键约束或是 unique 约束,当定义外键约束后,要求外键列数据必须在主表的主键列存在或是为 nullforeign key (外键(本表)字段) references 主表(字段);
MySQL> create table my_class( -> class_id int primary key, -> class_name varchar(64) not null unique, -> class_intro text not null -> )charset=utf8 engine=innodb;Query OK, 0 rows affected (0.02 sec)
MySQL> create table stu( -> id int primary key, -> name varchar(64) not null default '', -> class_id int, -> /*定义外键*/ -> foreign key (class_id) references my_class(class_id) -> )charset=utf8 engine=innodb;Query OK, 0 rows affected (0.02 sec)
`MySQL> insert into stu values(1,'张三',1); ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`stu`, CONSTRAINT `stu_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `my_class` (`class_id`))`
本文首发于 GitChat,未经授权不得转载,转载需与 GitChat 联系。
阅读全文: http://gitbook.cn/gitchat/activity/5d4e3283511b817a170e5a2a
您还可以下载 CSDN 旗下精品原创内容社区 GitChat App ,阅读更多 GitChat 专享技术内容哦。