===================================================
0x01 数据库基本概念
数据库:信息存储的仓库。可以把数据存储在数据库中。
非关系型数据库系统,键值对的方式存储数据,redis 数据库。
关系型数据库系统:
- 表 一个数据库中可以有若干张表(形式上你可以看做日常生活中建立的表)
- 字段 表里面的信息会分若干个栏目来存,这些栏目呢,我们在数据库技术中叫"字段",栏目里面存的具体信息叫"字段值"
- 记录 一条信息我们叫一条记录
一个数据库管理系统(DBMS)中可以建立若干个数据库(DB),每个数据库中又可以建立若干张表(table),每张表中可以有若干条记录。
MySQL 是数据库管理系统,其中可以存储很多数据库。
0x02 MySQL支持的数据类型
数值类型、日期类型、字符串(文本)类型。
数值类型
- 整数类型 tinyint、smallint、mediumint、int和bigint
- zerofill属性 配合int(数字)来用,表示显示的时候一个显示宽度
- 主键 主键可以唯一标识某条记录的一个字段或者多个字段,可以通过主键定位到唯一一条记录。 在创建表的时候就定义好主键。
create table 表名(字段名称 类型 primary key,....);
create table 表名(字段名称1 类型,....,primary key(字段名称1));
alter table 表名 drop primary key;
# 注意:如果字段具有auto_increment属性必须先删除auto_increment属性
- 小数的表示
- 浮点数
- 单精度(float):单精度的浮点数精确到大约7位小数位(整数部分加上小数部分的位数)
- 双精度精度(double):双精度的浮点数精确到大约15位小数位(整数部分加上小数部分的位数)、
- 定点数
decimal(7,2)
日期类型
DATETIME是常用的日期类型
create table t1(dt datetime);
insert into t1 values(now());
字符串类型
CHAR(M) M为0~255之间的整数,表示可以存M个字符(不管是中文还是英文字符总共个数是M个就OK) VARCHAR(M) M为0~65535之间的整数,表示可以存M个字符,具体M最大多大和字符集有密切关系
TINYTEXT 允许长度0~255字符 TEXT 允许长度0~65535字符 MEDIUMTEXT 允许长度0~16,777,215字符 LONGTEXT 允许长度0~4,294,967,295字符
- 注意点:
char与varchar列的区别 char类型的字符所占的存储空间是固定,不管你用的时候存了几个字符,它所占的空间都是你当初设定的字符空间,比如char(255) 哪怕你存的只是1个a,那么它也是占255个字符长度的空间!varchar列所占的存储空间是可变的,根据存入的字符长度来确定实际占多少的空间!varchar(255) 实际所占的空间就是实际字符的长度+1个字节!varchar(超过255) 实际所占的空间就是实际字符的长度+2个字节!更节省空间!在检索时,char列删除尾部的空格,而varchar则保留这些空格。
选择:由于char是固定长度,所以它的处理速度比varchar快,但是缺点是浪费存储空间。所以对于那些长度变化不大的数据可以选择此列
0x03 (My)SQL使用入门
MySQL 是关系型数据库系统,其中存储了大量的数据。
SQL ,结构化查询语言,对数据库进行操作的语句
SQL分类
- DDL(Data Definition Languages)语句 数据定义语句,通过这类语言可以对数据库进行创建删除更改
- DML(Data Manipulation Language)语句 数据操纵语句,用于添加、删除、更新和查询数据库记录并检查数据完整性
- DCL(Data Control Language)语句 数据控制语句,通过此类语句可以对数据库的相关权限进行设置
0x04 DDL语句
对数据库内部的对象(数据库、表、字段)进行创建、删除、修改等操作的语言,DDL语句更多的是由数据库管理员(DBA)使用。
登录数据库
mysql -uroot -proot
- 查看MYSQL 都有哪些数据库
show databases; #查看数据库列表
创建数据库
创建一个数据库,名为bbs。
create database bbs;
进入数据库
use bbs; #Database changed
查看数据库中所有的数据表
show tables;
删除数据库
drop database bbs;
创建表
首先需要明确,要操作的数据库,然后用use
命令选择数据库。 推荐使用phpMyAdmin 来创建表.
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
- 数据库规划
user
id # 用户id
username # 用户名
password # 用户密码
message
id # 留言的ID
uid # 该条留言的主人
title # 留言的题目
content # 留言的内容
查看表的定义
desc user;
查看创建表的SQL语句
show create table user G
G
就是用来代替;
使用,以显示更多的内容。
删除表
drop table user;
修改表的定义
- 修改表的字段类型
alter table 表名 modify [column] 字段定义 [first|after 字段名];
- 增加表字段
alter table 表名 add [column] 字段定义 [first|after 字段名];
- 删除表字段
alter table 表名 drop [column] 字段名;
- 字段改名
alter table 表名 change [column] 旧的字段名 字段定义 [first|after 字段名];
- 注意
change
与modify
都可以修改表的定义,不同的是change后面需要接两次列名,不方便,但是优点是change可以修改字段名称 - 修改字段排列排序 前面介绍的字段增加和修改语法(add/change/modify)中,都有一个可选项
first|after 字段名
,这个选择可以用来修改
字段在表中的位置新增的字段默认是加载在表中最后位置,而change/modify 默认都不会改变字段的位置
alter table t1 modify id2 tinyint first;
alter table t1 modify id2 tinyint after id1;
注意:change/first|after 字段名 这些关键字都是属于MySQL在标准SQL上的扩展,在其他的数据库上不一定适用
- 更改表名
alter table 表名 rename [to] 新的表名;
0x05 DML语句
查询表中所有内容
select * from user;
注意:select
语句不会修改表中原来的数据
插入记录
- 插入记录
insert into user(username,password)values('ajest','123.com');
- 一次插入多条记录
insert into user(username,password)values('root','123456'),('admin',123456);
更新记录
- 更新一个表
update user set password='123.com' where id=1;
- 更新多个表中数据
update 表1,表2,...表n set 表1.字段1=表达式1,表n.字段n=表达式n [where 条件];
update t1,t2 set t1.age=2000,t2.age=3000 where t1.id=1 and t2.id=1;
删除记录
- 删除单表中的数据
delete from 表名 [where 条件];
- 删除多个表中的数据
delete 表1,表2,...表n from 表1,表2,...表n [where 条件];
不管是单表还是多表,不加where条件将会把表中的所有记录删除,所以操作时一定要小心。
查询记录
- 基本语法
select password from user;
select username from user;
select username,password from user;
select id,username,password from user;
select * from user;
- 查询不重复的记录
distinct
放在字段前面,起到修饰作用,过滤掉重复记录。
select distinct password from user;
条件查询
where
对查询结果,按照一定的条件进行过滤。
select * from user where id=1;
select * from user where id = 4;
select * from user where id = 4;
select * from user where id > 4;
select * from user where id >= 5;
select * from user where id <> 5;
select * from user where id != 5;
select * from user where id=5 or id=6;
select * from user where username = 'ajest' and password = '123456';
select * from user where username = "ajest" and password = "123.com";
select * from user where username = ("ajest") and password = ("123.com");
select * from user where username = ('ajest') and password = ('123.com');
以上语句中的=
|>
| <
|>=
|<=
|<>
等都是比较运算符。 'ajest'
和 '123456'
是数据内容,是字符型。 4
,5
,6
是数据内容,是数字型。
排序
order by
对查询结果,按照一定的规律进行排序 asc
,升序排列。 desc
,降序排列。
select * from user order by id;
select * from user order by id asc;
select * from user order by 4 desc;
限制
可以用limit
关键字取得结果集合中的从(第几条开始,取得几条)记录
select * from user limit 1,2;
聚合
对表中记录进行统计。
sum
求和
select sum(id) from user;
count
记录总数
select count(*) from bbs.user;
select count(*) from information_schema.tables;
max
最大值
select max(id) from user;
min
最小值
select min(id) from user;
GROUP BY
分类聚合
select * from user group by password;
select count(*) from user group by password;
select count(*),password from user group by password;
表连接
显示多个表中的字段的时候即可使用表连接,实现跨表查询
- 连接分类
- 内连接:选取两张表中相互匹配的记录
- 外连接:不仅仅选取两张相互匹配的记录,并且会选出其他不匹配的记录
- 内连接
select title from message;
select content from message;
select title,content from message;
select title,username,content from message;
select message.id,user.username,message.title,message.content from user,message where message.uid = user.id;
select m.id,user.username,m.title,m.content from user,message as m where m.uid = user.id;
子查询
需求:一个查询需要另外一个查询的结果参与的时候
in
结果是否在子查询里。
# 筛选出留过言的用户名
select username from user where id in(select uid from message);
not in
# 查询出没有留过言的用户
select username from user where id not in(select uid from message);
exists
select exists(select * from user where id=1);
select exists(select * from user );
not exists
与exists相反
联合查询
联合两张表的查询结果。
select * from user union select * from message;
select * from user union select * from message;
select * from user union select 1,2,3;
select * from message union select 1,2,3,4;
- 两张表列数相同
- 字段类型相同
0x06 MySQL中的常见运算符
MySQL提供了一些运算符号供我们在SQL语句中使用,比如我们需要对SQL语句中的某个值,或者某个字段做运算操作的时候,就可以使用这些运算符。
比较运算符
=
>
<
>=
<=
<>
逻辑运算符
or
and
!
select true;
select false;
select !false;
select 1>2 or 1<2; # 1
算数运算符
+
-
*
/
select 1+3=2+2;
运算符优先级
and
的优先级高于or
。
select 1=1 or 1=2 and 1=2;
select true or false and false;
select true or false;
select true;
0x07 information_schema
MySQL 是DBMS(DataBase Manager System),数据库管理系统,会存储很多数据库。
MySQL 数据库层级关系
库
--> 表
--> 字段(列)
--> 记录
。
show databases; # 查询所有的库名
show tables; # 查询所有的表名,前提进入数据库里(eg. use bbs)
desc user; # 查询所有的字段,查看表的定义(user 是表名)
select * from user; # 查询user 表中所有的记录
information_schema
information_schema
这个数据库是MySQL 自定义的。- 用来存储MySQL 数据库管理系统中,元数据(库名、表名、字段名等)的数据库。
- 默认情况下,数据库的任何用户都有访问权限。
information_schema
|
+-- schemata # 所有的库名
| |
| `-- schema_name # 库名
|
+-- tables # 存储了MySQL 数据库中所有的表
| |
| +-- table_name # 表名
| |
| `-- table_schema # 表名所属的库名
|
`-- columns # 存储了MySQL 中所有的字段
|
+-- column_name # 字段名
|
+-- table_name # 字段所属的表名
|
`-- table_schema # 字段所属的库
元数据查询
select schema_name from information_schema.schemata; # show databases;
select table_name from information_schema.tables where table_schema='bbs';
select column_name from information_schema.columns where table_schema='bbs' and table_name='message';
0x08 常用函数和语句
- 函数用于SQL语句中。
- 跟MySQL 版本有关。
函数速查
函数名字含义CONCAT(S1,S2,...Sn)连接S1,S2,...Sn为一个字符串concat_ws()含有分隔符的连接字符串,第一个参数是分隔符group_concat()连接一组字符串,使用逗号隔开LOWER(str)将字符串str中所有字符变为小写UPPER(str)将字符串str中所有字符变为大写LEFT(str,x)返回字符串str最左边的x个字符RIGHT(str,x)返回字符串str最右边的x个字符SUBSTRING(str,x,y)返回从字符串str x位置起y个字符长度的字符串substr(str,x,y)同上LENGTH(str)返回字符串长度DATABASE()返回当前数据库名VERSION()返回当前数据库版本USER()返回当前登录用户名MD5(str)返回字符串str的MD5值sleep(x)让数据库沉睡x 秒钟的时间。ABS(x)返回x的绝对值FLOOR(x)返回小于x的最大整数值RAND()返回(0,1)内的随机值ROUND(x,y)返回参数x的四舍五入,保留y 位小数ascii(x)返回字母x 的ascii 码值ord(x)同上char(x)返回数字x 对应的字母hex(x)计算数字x 的十六进制IF(value,t,f)如果value是真,返回t,否则返回f
concat()
select concat(1,2,3);
select concat('a','bc','def');
select concat(username,':',password) from user;
select concat(username,0x3a,password) from user;
select concat(id,username,password) from user;
concat_ws()
select concat_ws(0x5e,id,username,password) from user;
select concat_ws(0x5f,id,uid,title,content) from message;
group_concat()
select group_concat(title) from message;
left()
select left('abcd',2);
substring()|substr()
select substring('abcd',4,1);
select substr('abcd',4,1);
select substr(database(),2,1);
length()
select length(database());
floor()
select floor(4.99);
rand()
select rand();
round()
select round(3.1415);
ascii()|ord()
select ascii('a');
select ord('a');
hex()
select hex('^');
if()
select if(1<2
select if(substr(database(),1,1)='a',1,0);
select if(substr(database(),2,1)='n',sleep(5),0); #延时注入的payload
0x09 知识补充:数据库字符编码
MySQL支持的字符集
- 查看所有可用的字符集
show character set;
或者查看information_schema.character_sets,也可以显示所有的字符集和该字符集默认的校对规则。
- MySQL的字符集包括字符集(character)和校对规则(collation)两个概念。
- 字符集用来定义MySQL存储字符串的方式
- 校对规则用来定义字符串比较的方式
- 字符集和校对规则是一对多的关系,一个字符集有多个校对规则供你选择!
- 校对规则命名约定
- 它们以相关的字符集名开始,通常包括一个语言名,并且以
- _ci(忽略大小写)
- _cs(大小写敏感)
- _bin(二元,即比较是基于字符编码的值而与language无关)结束。
- 查看字符集的校对规则
show collation like 'utf8%';
MySQL内部的字符集和校对规则设置
- 服务器字符集和校对规则设置
- 数据库字符集和校对规则设置
CREATE DATABASE db_name
[[DEFAULT] CHARACTER SET charset_name]
[[DEFAULT] COLLATE collation_name]
- 查看当前数据库的字符集和校对规则
show variables like 'character_set_database';
show variables like 'collation_database';
- 修改数据库的字符集和校对规则
ALTER DATABASE db_name
[[DEFAULT] CHARACTER SET charset_name]
[[DEFAULT] COLLATE collation_name]
- 表字符集和校对规则设置
CREATE TABLE tbl_name (column_list)
[DEFAULT CHARACTER SET charset_name [COLLATE collation_name]]
ALTER TABLE tbl_name
[DEFAULT CHARACTER SET charset_name] [COLLATE collation_name]
- 字段(列)字符集和校对规则
MySQL连接字符集设置
过程中要设置正确,诚实守信,这样子如果全部设置正常,服务器端会自动的去按照你设置的字符集转换,但是也要避免想换转换的过程,最好都设置成一样的编码!
连接字符集设置:客户端和服务器之间交互的字符集
- 对于客户端和服务器段的交互操作,MySQL提供了3个不同的参数:
- character_set_client:客户端来源数据使用的字符集
- character_set_connection:连接层字符集
- character_set_results:返回结果字符集
知识拓展:数据在客户端和服务器之间交互的过程中字符集转换的大概过程
- MySQL Server收到请求时将请求数据从character_set_client转换为character_set_connection;
- 进行内部操作前将请求数据从character_set_connection转换为内部操作字符集,内部操作字符集的确定方法如下: 1>使用每个数据字段设定的字符集; 2>若上述值不存在,则使用对应数据表设定的字符集; 3>若上述值不存在,则使用对应数据库设定的字符集; 4>若上述值不存在,则使用服务器设定的字符集。
- 将操作结果从内部操作字符集转换为character_set_results。
这3个参数设定的字符集应该相同,并且客户端使用的字符集确实是参数character_set_client的值,才可以确保用户的数据可以正确的返回且输出。 查看当前设置
show variables like 'character_set%';
修改:
set names 字符集
可以同时修改3个参数的值,对本次有效 也可以在配置文件中设置:
[mysql]
default-character-set=字符集
修改CMD命令行字符集:
chcp 65001 #换成utf-8代码页(设置为utf-8之后最好手动修改显示字体 )
chcp 936 #换成默认的gbk
客户端使用字符,连接层使用的字符集,内部使用的字符集,返回使用的字符集,最好都设置成一样的,并且客户端使用的字符集确实是character_set_client参数的值,这样就绝对不会出现问题!