当我们面对一个陌生的数据库的时候,我们肯定需要一种工具去跟它交流、操作,就像我们用excel,word一样,都有相应的功能去跟这个软件交流、操作,数据库也一样,需要去完成用户的各种工作,所以——SQL语句诞生了。
SQL语句也就是结构化查询语句,是Structure Query Language的缩写,一般都是用到关系数据库的一种语言。
SQL_MODE翻译过来就是SQL的模式,相当于就是SQL的标准,最早的SQL标准是出自ANSI的,也就是SQL-86,随着时间的推移,现在的标准也在慢慢的提高。
SQL_MODE定义了MySQL应当支持的MySQL语句、语法、数据校验等一些功能的规范。
比如说varchar(10)插入超过10个字符,在没有SQL_MODE的数据库下,超过部分会直接被截断,被截断部分不会显示到查询的结果上,然后在严格模式下,超过字符类型的限制,则插入SQL的语句会直接报错。
常用的SQL_MODE有以下这些(分别用在现在的5.7、8.0版本):
1、ANSI
2、STRICT_TRANS_TABLES
3、TRADITIONAL
最常用的就是以上三种,致于具体的功能,到时候会再另出一篇文章具体的去讲解这些模式的详细功能以及使用方法。
最常用的有以下几种:
1、DDL:数据定义语言(Data Definition Language)常用的语句关键词有create、drop、alter等。
2、DCL:数据控制语言(Data Control Language)常用的语句关键词有grant、revoke等。
3、DML:数据操作语言(Data Manipulation Language)常用的语句关键词有delete、update、insert、select等等。
如果进行细分,还可以在DML下分出DQL数据的查询语言(Data Query Language)常用的就是select。
的作用主要就是用来定义用户所输入的数据需要一个规范性,不然的话数据库管理起来的代价太大了,数据格式不一致也可能会导致数据库工作量过大。
数据类型有以下这些(例举平时我常用的类型):
1、数值类型:tinyint、smallint、mediumint、int、bigint、float、double、decimal、bit
2、字符串类型:char、varchar、enum(用的好能提高查询性能)
3、时间类型:date、time、datetime(普通的)、timestamp(以当地时间为准)、year
4、二进制类型:MySQL不擅长使用二进制类型的数据,因为二进制数据一般的话会存储图片、视频这一类的数据,对于性能影响可能会很大,会影响备份、复制等一些功能数据不一致的问题,如果需要存的话最好是存在文件系统下,在数据库下存储链接地址,由数据库直接跳转链接到相应目录。
5、JSON类型(5.7.8版本以后支持):varchar、text ,后期会专门写一篇文章来讲解JSON数据类型的使用方法以及需要在哪些情况下用到JSON类型的数据类型。
表的属性还有很多其它能应用的功能,比如索引、锁、事务等等,这边粗略的聊一下以下两种属性在表里面的应用。
列属性也就是相当于在DDL语句里面会用到非常多的一种,列的属性的好坏,决定了行数据的好坏,列属性定义的好,将来维护起数据来更加的得心应手,所以需要对列属性的功能更好的了解,将来才能更高效的去维护这个表,这个数据库。
我会用到的列属性有以下这些:
(表创建时增加)
primary key 主键约束
not null 非空约束
unique key 唯一键(列值不能重复)
unsigned 无符号(数字列,非负数)
(按需求)
key 索引
default 默认值
auto_increment 自增长
comment 注释
在MySQL里面有很多种数据引擎,不过最常用的就是Innodb、MyISAM这两种,用户可以根据业务的需求,对表进行相应的选择,可以选择如果存储和索引的一些数据,是否需要事务等等。
MySQL在5.7的版本下所支持的存储引擎有下面这些:
Innodb 提供事务安装表
MyISAM
Memory
CSV
BLACKHOLE
ARCHIVE
MERGE
FEDERATED
EXAMPLE
NDB 提供事务安全表
注:现在我们在新表进行创建的时候,如果不进行存储引擎的指定,则MySQL会自己选择默认的存储引擎,MySQL在5.5版本以前,新创建的表会默认选择MyISAM
的存储引擎,在5.5版本以后则把MyISAM改为了Innodb,如果需要表的修改存储引擎,可以用alter table 表名 engine='存储引擎';如果需要修改默认的
存储引擎则可以在参数中进行添加default_storage_engine
举例几个常用的:
数据库中查看字符集命令:show character set;
GBK
GB2312
UTF8 3个字节长度
UTF8mb4 4字节长度,支持emoji,mysql8.0以后默认字符集
UTF16
latin1 5.7之前mysql表创建默认字符集
目前我所用的到就这几种,Mysql相对于oracle在同一个库下只能使用同一种字符集,存在更大的灵活性。
MySQL还有一个排序规则总共有4个级别:服务器层面、数据库层面、表层面、字段层面。
如果不进行字符集的指定,则MySQL以latin1作为服务器字符集
这些命令是我以后会用到的一些命令,大家也可以参考一下:
show databases;
show tables;
show table from 库名; 查看某个指定库下的表
show create database 库名; 查看建库语句
show create table 库名.表名; 查看建表语句
show grants for root@'localhost'; 查看用户的权限信息
show charset; 查看字符集
show collation; 查看校对规则
show processlist; 查看数据库连接情况
show index from 表名; 表的索引情况
show status 数据库名; 数据库状态查看
show status like '%需要查询的单词%'; 模糊查询数据库某些状态
show variables; 查看所有配置信息
show variables like '%单词%'; 查看部分配置信息
show variables like '%innodb%'; 查看INNODB相关信息
show engines; 查看s有的存储引擎
show engine innodb status\G; 查看innodb引擎相关的状态信息
show binary logs; 列举所有的二进制日志
show master status; 查看数据库的日志位置信息
show binlog evnets in '日志名'; 查看二进制日志事件
show slave status \G; 查看从库状态
desc (show columns from 表名) 查看表的列定义信息
show relaylog events; 查看relaylog事件
作为一名合格的DBA,心里一定要有自己建库建表的一套标准,就算以后在公司里面不需要你进行建库建表,也一定给公司制定一套规范,方便以后去排查!
1、库名不能大写
2、库名不能以数字开头
3、建库时需要加字符集
4、库名要和业务相关
1、表名小写
2、不能是数字开头
3、注意字符集和存储引擎
4、表名和业务有关
5、选择合适的数据类型
6、每个列都要有注释
7、每个列设置为非空,无法保证非空,用0来填充
8、在线DDL工具pt-osc可以去了解一下
创建
create database test; 建库
create schema t1; 也是建库
create database test charset utf8; 建库时增加字符集
create database test charset utf8mb4
collate utf8mb4_bin; 有大小写校对规则的collate
删除 生产库中禁止使用
drop database test;
alter database test charset utf8; 修改字符集
以上是关于库的一些语句以及规范,以下是关于表的一些操作:
表定义:
create table tablename(
column_name_1 column_type_1 constraints,
column_name_2 column_type_2 constraints,
...
column_name_n column_type_n constraints);
下面来创建一张学生表:
CREATE TABLE student(
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '学号',
sname VARCHAR(100) NOT NULL COMMENT '姓名',
sage TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '年龄',
sgender ENUM('m','f','N') NOT NULL DEFAULT 'N' COMMENT '性别' ,
idcard CHAR(18) NOT NULL UNIQUE COMMENT '身份证',
intime TIMESTAMP NOT NULL DEFAULT NOW() COMMENT '入学时间')
ENGINE=INNODB CHARSET=utf8 COMMENT '学生表';
修改(会对表进行锁定)
alter table student add iphone varchar(20) not null unique comment '电话';
alter table student add wechat varchar(64) not null unique comment '微信号' after sname;
alter table student add num int not null comment '数字' first;
删除列:
alter table student drop num;
修改sname数据类型属性
alter table student modify sname varchar(128) not null;
alter table student change sgender sg char(1) not null default 'n' comment'性别';
create table t1 like student; 创建一张跟like后面一模一样的表
create table t2(id int unique key not null,id2 int primary key not null);
mysql[t1]>desc t2;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | NO | UNI | NULL | |
| id2 | int(11) | NO | PRI | NULL | |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)
删除unique key:ALTER TABLE t2 DROP INDEX id;
删除主键:alter table t2 drop primary key;
DCL语句的话主要是做授权用户权限这块的,一般的话没有什么特别要求使用的比较少,一般都是给自己的开发或者DBA所使用。
命令及举例如下:
命令:grant revoke
mysql> grant select,insert on test.* to 'fhd'@'localhost' identified by '123';
Query OK, 0 rows affected, 2 warnings (0.01 sec)
mysql> exit
Bye
[root@hdfeng ~]# mysql -u fhd -p
mysql> use test;
mysql> insert into test(id,name) values(2,'hdfeng');
Query OK, 1 row affected (0.00 sec)
由于某种原因,需要收回fhd的insert权限:
[root@hdfeng ~]# mysql -u root -p
mysql> revoke insert on test.* from fhd@'localhost';
Query OK, 0 rows affected, 1 warning (0.00 sec)
用户fhd再进行登录执行insert语句时提示报错:
mysql> insert into test(id,name) values(3,'hdfeng');
ERROR 1142 (42000): INSERT command denied to user 'fhd'@'localhost' for table 'test'
收回了用户fhd的insert权限
DML语句主要针对数据库中的记录进行的操作,主要包括insert、delete、update、select等操作,因为select操作过多,所以直接放到了DQL下单独操作。
对于Stduentg表进行insert操作:
mysql> insert into student values(1,'czk',18,'m','123456',now()); 传统
Query OK, 1 row affected (0.00 sec)
针对性录入insert into student values('hdf','45234526'); 如果严格模式下会报错
多行录入
mysql> insert into student(sname,idcard)
-> values
-> ('lkertdfg','67265365'),
-> ('lektrj','3446468'),
-> ('fgdhert','846783245');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> delete from student where id=3; 再进行插入会往后录,不会在3这一行录入
Query OK, 1 row affected (0.00 sec)
因为delete操作没有回收表空间的机制,所以如果有很多这类的操作,需要用truncate 命令进行清理
truncate命令实际上是把表全删除之后再进行重新创建的操作,所以在大表下最好不要这样操作
数据量过大的话,这个操作会占用大量的资源。
INSERT into stu(sname,sid) values('zhanglf','2453457347'); 不会再往3这插入
区别:
delete:DDL操作,是逻辑性质删除,逐行进行删除,速度慢
truncate:DDL操作,对与表段中的数据页进行清空,速度快
optimize table tablename;能用这个命令来清理表空间,在数据存在的情况下,truncate命令的话会把表数据也清空,而这个只会回收被delete的空间。
伪删除:用update来替代delete,最终保证业务中查不到(select)即可
1、添加状态列
ALTER table stu add state tinyint not null default 1;
2、update 替代 delete
UPDATE stu set state=0 where id=5;
3、业务语句查询
SELECT * from stu where state=1;
update必须加where,因为where是条件,where则全表删除:
mysql> update student set sname='czk2' where id=2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
执行顺序:select——from——where——group by——having——order by——limit
> select 单独使用
select查看系统参数:
select @@port; 端口查询
select @@basedir; mysql程序路径
select @@innodb_flush_log_at_trx_commit; MySQL双一标准后面会讲到
select @@socket; socket路径
select @@server_id;
select @@log_error; 报错日志路径
select @@log_bin_basename; binlog日志路径
select @@log_bin; binlog是否开启
select函数:
select now(); 当前时间
select database(); 当前库
select user(); 当前用户
拼接功能(列):select concat(user,"@",host) from mysql.user;
(行)select group_concat(user,"@",host) from mysql.user;
查看表的大小
select concat(round(sum(data_length/1024/1024),2),'MB'),concat(round(sum(index_length/1024/1024),2),'MB') from
information_schema.tables where table_schema= 'database' and table_name='tablename';
> 单表子句-from
select column1,column2 from tablename;
select * from tablename;
查询student中所有的数据(不要在生产环境中对大表进行操作,大表数据行过大,mysql打开需要很久,对系统资源占用很大)
select * from student;
查询student表中,学生姓名和入学时间
select sname,intime from student;
> 单表子句-where(需要world数据库,可以在评论留言)
格式:
select colmn1,column2 from table where colN 条件;
where配合等值查询
查询中国(CHN)所有城市信息:select * from city where countrycode='CHN';
查询北京市的信息:select * from city where name='peking';
查询中国甘肃的信息:select * from city where district='gansu';
where配合比较操作符
查询世界上少于100人的城市
select * from city where population<100;
where配合逻辑运算符(and or)
中国人口数量大于500w:select * from city where countrycode='CHN' and population>5000000;
中国或美国的城市信息:select * from city where countrycode='CHN' or
countrycode='USA' having population<1000000 and population>800000;
where配合模糊查询
查询省的名字带guang开头的:select * from city where district like 'guang%';(前面带百分号性能极差) 注:%不能放在前面,因为不走索引
where配合in语句
中国或美国的城市信息:select * from city where countrycode in ('CHN' or 'USA');
where配合between and
世界上人口数量大于100w小于200w的城市信息
select * from city where population > 1000000 and population <2000000;
select * from city where population between 1000000 and 2000000;
> 单表子句-group by
常用聚合函数:max()最大值/min()最小值/avg()平均值/sum()总和/count()个数统计/group_concat()列转行
1、统计每个国家的总人口数量
select countrycode,sum(population) from city group by countrycode;
2、统计中国每个省的总人口
select district,sum(population) from city where countrycode='CHN' group by district;
3、统计每个国家的城市数量
select countrycode,count(id) from city group by countrycode;
4、统计中国,每个省的城市名字列表
select district,group_concat(name) from city where countrycode='CHN' group by district;
5、统计一下中国,每个省的城市平均人口数
select district,avg(population) from city where countrycode='CHN' group by district;
> 单表子句-having
统计中国每个省的总人口数,只输出总人口数小于100w的信息
select district,sum(population)
from city
where countrycode='CHN'
group by district
having sum(population)<1000000;
> 单表子句-order by
查询中国的城市信息,并按人口数量从大到小进行排序
select * from city where countrycode='CHN' order by population desc大到小(降序)/asc小到大(升序);
统计中国,每个省的总人口,找出大于500w的并按总人口从大到小排序
select district,sum(population) from city
where countrycode='CHN'
group by district
having sum(population)>5000000
order by sum(population) desc;
> 单表子句-limit
统计中国,每个省的总人口,找出大于500w的并按总人口从大到小排序,只显示前3名
select district,sum(population) from city where countrycode='CHN' group by district having sum(population)>5000000
order by sum(population) desc limit 3;
limit 3,5;(跳过3,显示5)
select district,sum(population) from city where countrycode='CHN' group by district having sum(population)>5000000
order by sum(population) desc limit 5 offset 3;
LIMIT N,M
LIMIT 5,5
LIMIT M OFFSET N(显示M,隐藏N)
distinct去重
select distinct(countrycode) from city ;
> 联合查询-union all 多表连接
union all不去重复 union 去重复
中国或者美国的城市信息
select * from city where countrycode='CHN'
union all
select * from city where countrycode='USA'
注:一般情况下将IN或OR语句改写成UNION ALL(来提高性能)
> 别名查询
select a.name as an,b.name as bn,b.surfacearea as bs,a.population as ap from city as a join country as b on
a.countrycode=b.code where a.name = 'shanghai';
多表SQL练习题
1、统计zhang3,学习了几门课
select st.sname,count(score.cno) from student as st join score on st.sno=score.sno where st.sname='zhang3';
2、查询zhang3,学习的课程名称有哪些?
select st.sname,group_concat(co.name) from student as st join sc on st.sno=sc.sno join course as co on sc.cno=co.cno
where st.name='zhang3';
3、查询张三丰老师教的学生名
select te.tname,group_concat(st.sname) from student as st join sc on st.sno=sc.sno join course as co on sc.cno=co.cno
join teacher as te on co.tno=te.tno where te.tname='zhangsanfeng';
4、查询张三丰所教课程的平均分数
select te.tname,avg(sc.score) from sc join course as co on sc.cno=co.cno join teacher as te on co.tno=te.tno where
te.tname='zhangsanfeng';
5、每位教师所教课程的平均分,并按平均分排序
select te.tname,avg(sc.score) from sc join course as co on sc.cno=co.cno join teacher as te on co.tno=te.tno where
te.tname='zhnangsanfeng' or te.tname='hdfeng' or te.tname='hdfeng1' desc;
6、查询张三丰所教的不及格的学生姓名
select te.tname,st.sname,sc.score from student as st join sc on st.sno=sc.sno join course as co on sc.cno=co.cno join
teacher as te on co.tno=te.tno where sc.score<60 and te.tname='zhangsanfeng';
7、查询所有教师所教学生不及格的信息
select te.tname,st.sname,sc.score from student as st join sc on st.sno=sc.sno join course as co on sc.cno=co.cno join
teacher as te on co.tno=te.tno where sc.score<60;
MySQL内置函数更具体的可以引用mysql官方的一些函数。
视图是什么呢?在数据库里面有什么作用呢?
视图的话其实是一种虚拟存在的表,对于用户来说,在使用se视图的时候其实是透明的,视图并不是在数据库中实际存在,就是在自定义查询行和列数据的时候动态生成的一种表,并且会自动生成。
视图在数据库里的作用:能封装经常使用的SQL语句,比如说一个非常复杂的语句需要在数据库里经常用到,然后并不想每次去查询都写这么多参数和语句,就能使用这个视图进行封装,封装好以后用SQL语句调用这个封装好的视图就能使用在这个视图里面的语句进行查询了。
information_schema 视图库(虚拟库)
表:元数据+数据行
元数据存储在“基表”,是我们没法直接访问。mysql给我们提供了DDL、DCL语句来进行对原数据修改
能使用information_schema和show语句查询元数据
DESC information_schema.TABLES
TABLE_SCHEMA 库名
TABLE_NAME 表名
ENGINE 引擎
TABLE_ROWS 表的行数
AVG_ROW_LENGTH 表中行的平均行(字节)
INDEX_LENGTH 索引的占用空间大小(字节)
了解了这些以后进行视图的创建:
create table test(id int,name varchar(10)); 先进行相应测试表的创建
insert into test(id,name) values(1,'teast1'); 随便插入一些表数据
视图创建:
create view t1 as
select * from test;
现在去查询创建完的view:
mysql> select * from t1;
+------+--------+
| id | name |
+------+--------+
| 1 | teast1 |
+------+--------+
1 row in set (0.00 sec)
直接查询test表:
mysql> select * from test;
+------+--------+
| id | name |
+------+--------+
| 1 | teast1 |
+------+--------+
1 row in set (0.00 sec)
你会发现这个视图直接调用了视图里面的语句,复杂的语句如果调用这个语句真的太好用了!
关于视图表的一些命令:
1、查询整个数据库中所有库和所对应的表信息
select TABLE_SCHEMA,GROUP_CONCAT(TABLE_NAME) from information_schema.TABLES GROUP BY TABLE_SCHEMA;
2、统计所有库下的表个数
select TABLE_SCHEMA,count(TABLE_NAME) from information_schema.TABLES GROUP BY TABLE_SCHEMA;
3、查询所有innodb引擎的表及所在的库
select table_schema,table_name,engine from information_schema.TABLES where engine='innodb';
4、统计test数据库下每张表的磁盘空间占用
select table_schema,table_name,(table_rows*avg_row_length+index_length)/1024 as size_KB from information_schema.tables
where table_schema='test';
5、统计所有数据库的总的磁盘空间占用
select table_schema,concat(sum(table_rows*avg_row_length+index_length)/1024,"KB") as Total_KB from
information_schema.tables group by table_schema;
6、生成整个数据库下的所有表的单独备份语句
格式:
mysqldump -uroot -p123 test student > /tmp/test_student.sql
语句拼接
select concat("mysqldump -uroot -p123",table_schema," ",table_name,">/tmp/",table_schema,"_",table_name,".sql") from
information_schema.tables where table_schema='test' into outfile '/tmp/test.sh';
在vim /etc/my.cnf下
加入secure-file-priv=/tmp 表示允许表导出到/tmp目录下如果为null则不允许导入,如果为空,则表示不对mysqld导入导出限制
直接将这些导出的语句导出到tmp/b.sh脚本下
7、world下的3张表,都需要执行以下2条语句
格式:
alter table world.city discard tablespace; 丢弃了表空间,然后进行恢复
alter table world.city import tablespace;恢复表空间命令
从以上格式加到下面的select 里面,在没有日志的情况下也能恢复出来。
select concat("alter table",table_schema,".",tablen_name,"discard tablespace;")
from information_schema.tables
where table_schema='world'
into outfile '/tmp/discard.sql';
SQL语句练习:
需要练习文档的可以在评论区留言,我会分享出来!
本期的话就讲这些内容,如何有错误,或者有不理解的地方,欢迎小伙伴们留言!!谢谢!