MySQL数据库详解(上)
MySQL(一)
1.登陆
mysql -uroot -pMyPassword
使用默认的root用户名登陆,将MyPassword改成自己的密码
2.基本操作
--注释
updata mysql .user set authentication_string=password('123456') where user = 'root' and Host='localhost'; --修改用户密码
flush privileges; --刷新权限
show databases; --显示所有库
use dataBaseName; --切换数据库名
show tables; --显示所有表名
describe tableName; --显示所有表信息
create database newDatabase --创建一个新库
exit --退出连接
drop database databaseName --删除k
3.数据类型
1.数值
类型 | 大小 | 描述 |
---|---|---|
tinyint | 1字节 | 十分小的数据 |
smallint | 2字节 | 较小的数据 |
mediumint | 3字节 | 中等大小的数据 |
int | 4字节 | 标准的整数(常用) |
bigint | 8字节 | 较大的数据 |
类型 | 大小 | 描述 |
---|---|---|
float | 4字节 | 浮点数 |
double | 8字节 | 浮点数 |
decimal | 8个字节 | 字符串形浮点数 |
文本
类型 | 大小 | 描述 |
---|---|---|
char | 0~255 | 大小固定的字符串 |
varchar | 0~65535 | 常用的字符串 String (常用) |
tinytext | 2^8-1 | 微型文本 |
text | 2^16-1 | 文本串(常用) |
日期类型
类型 | 大小 | 描述 |
---|---|---|
data | YYYY-MM-DD | 日期格式 |
time | HH:mm:ss | 时间格式 |
datatime | YYYY-MM-DD HH:mm:ss | 常用的时间格式 |
timestamp | 1970到现在的毫秒数 | 时间戳(常用) |
null
无数不介意使用
4.数据库的字段类型
unsigned:只有整数能用,不能申明为负数
zerofill:不足的位数用0填充
auto_increment:自增,在上一条基础上自增必须是整数类型
NULL or NOT NULL:空或者非空
default:默认值
5.创建表
根据上面的信息可以通过Mysql语句创建如下表
CREATE TABLE IF NOT EXISTS `teacher`(
`id` INT(4) NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` VARCHAR(10) DEFAULT('匿名') COMMENT 'name',
`user` VARCHAR(20) NOT NULL COMMENT 'USER',
`pwd` VARCHAR(15) NOT NULL COMMENT 'PASSWORD',
`sex` VARCHAR(2) DEFAULT('男') COMMENT 'SEX',
`birthday` DATETIME DEFAULT(NULL) COMMENT 'Birthday',
PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
通过总结,可以获得一条创建表的公式
"--"代表空格 [ ]代表可选 最后一条语句不加,
#`keyName`--类型--[不可空?--默认值--自动递增--键值--备注]
`id` INT(4) NOT NULL AUTO_INCREMENT COMMENT 'id'
#可以在最后设置剪纸,也可以直接在最后设置
PRIMARY KEY(`id`)
#设置表的引擎
ENGINE=INNODB
6.表引擎
- INNODB 默认使用
- MYISAM 早些年使用
功能 | MYISAM | INNODB |
---|---|---|
事务支持 | 不支持 | 支持 |
数据行锁定 | 不支持 | 支持 |
全文索引 | 支持 | 不支持 |
表空间大小 | 较小 | 较大 |
总结:MYISAM节约空间,速度较快;INNODB安全性高、事务的处理、多表多用户操作。
7.修改和删除字段
mysql语句中可以通过ALTER命令来修改表名、添加字段、修改表的字段
ALTER TABLE #修改表元素
参数 | 描述 |
---|---|
RENAME AS | 重命名表名 |
ADD | 添加字段 |
MODIFY | 修改约束 |
CHANG | 修改字段名 |
DROP | 删除表中字段 |
#ALTER TABLE 表名 RENAME 旧表名 RENAME AS 新表名
ALTER TABLE teacher RENAME AS student; #修改表名
#ALTER TABLE 表名 ADD 字段名 新属性
ALTER TABLE student ADD age INT(11); #添加字段
#ALTER TABLE 表名 MODIFY 字段名 列属性[...]
ALTER TABLE student MODIFY age VARCHAR(11); #修改约束
#ALTER TABLE 表名 CHANGE 旧名字 新名字 列属性
ALTER TABLE student CHANGE age age1 INT(1); #修改字段名
#删除表的字段:ALTER TABLE 表名 DROP 字段名
ALTER TABLE student DROP age1;
DESC student; #查询结果
DROP #删除表
参数 | 描述 |
---|---|
TABLE | 指定表 |
DROP TABLE IF EXISTS student;
DELETE #删除单个数据
参数 | 描述 |
---|---|
FROM | 指定表 |
WHRER | 筛选数据 |
#DELETE FROM 表名 WHERE 条件
DELETE FROM `film` WHERE title ='127小时10.0';
8.MySQL管理
在简单的操作MySQL数据库之后,要学会更好的管理MySQL数据库
8.1添加外键
MySQL 外键约束(FOREIGN KEY)用来在两个表的数据之间建立链接,它可以是一列或者多列。 一个表可以有一个或多个外键。 外键对应的是参照完整性,一个表的外键可以为空值,若不为空值,则每一个外键的值必须等于另一个表中主键的某个值
添加外键的方法很多,只讲最简单最好理解的
分别执行以下两个MySQL语句,创建两个表
#创建年级表
CREATE TABLE IF NOT EXISTS `graded`(
`gradeParId` INT(4) NOT NULL COMMENT "年级id",
`gradeName` VARCHAR(3) NOT NULL COMMENT "年级名称",
PRIMARY KEY(`gradeParId`)
)
#创建学生表
CREATE TABLE IF NOT EXISTS `student`(
`id` INT(4) NOT NULL AUTO_INCREMENT COMMENT '学号',
`name` VARCHAR(5) NOT NULL COMMENT '姓名',
`sex` VARCHAR(2) DEFAULT('男') COMMENT '性别',
`gradeId` INT(10) NOT NULL COMMENT '年级id',
PRIMARY KEY(`id`)
)DEFAULT CHARSET=utf8
给表添加外键,使得两个表的某项值相互关联,可以理解为添加一个字段,使得这个字段等于另外一张表的某个值
在上一节通过ALTER来给表添加新的字段并且设置字段的属性,以同样的方式,在创建完两个表之后,通过ALTER来新增一个字段
#ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY(被关联的外键字段) references 外表名(关联的字段)
ALTER TABLE `student` ADD CONSTRAINT `FK_gradeId` FOREIGN KEY(`gradeId`) REFERENCES `graded`(`gradeParId`);
- CONSTRAINT:约束
- FOREIGN:外界
- REFERENCES:引用
8.2 DML语言
Data Manipulation Language(DML):数据库操纵语言
Insert
通过Insert语句INTO参数对可以选中某个表插入其中一条数据
#INSERT INTO 表名([字段1],[字段2],[字段3]...) VALUES (数据1,数据2,数据3.....);
INSERT INTO `student`(`name`,`sex`,`gradeId`) VALUES ("李四","男",1803);
注意点:插入的数据的类型要与表中的字段一一对应,比如字段1是varchar因此VALUES后面括号第一个字段应该是String类型而不是数值
省略:可以省略字段1,字段2,字段3然后写VALUE后面的数据,MySQL将默认自己匹配,但不介意这么写
也可以插入多条数据
INSERT INTO `student`(`name`,`sex`,`gradeId`) VALUES ("小明","男",1804),("小张","男",1804),("小龙","男",1804);
Update
通过Update可以对表中字段就行一个修改
#UPDATE 表名 SET 要修改的字段=要修改的数据 WHERE 条件;
UPDATE `student` SET `name`= "李明" WHERE `name`="张三"; #把name叫张三的修改为李明
WHERE:筛选条件,可以是被修改字段的任何值,比如....WHERE id
=1
;修改id为1的字段
同样的方式可以修改多个值
UPDATE `student` SET `name`= "李明",`gradeId`=1804 WHERE `name`="张三";
注意:如果不加WHERE将会修改所有字段,切勿如此操作,如此操作后请立即删库跑路
Delete
通过delete语句删除一个字段 以及 清空表
#DELETE FROM 表名 WHERE 条件 //删除字段
DELETE FROM `student` WHERE `name`="李明";
#TRUNCATE 表名 //清空表
TRUNCATE student;
注意:如果不加WHERE将会删除所有字段,切勿如此操作,如此操作后请立即跑路
DELETE 和 TRUNCATE 的区别:
- DELETE不会重置自增的计数器,TRUNCATE会
- TRUNCATE不会影响事务,DELETE会
8.3 DQL 语言
Data Query Language(DQL):数据库查询语言
- 本节的关键主要围绕Select展开
- 查询语句有点多
8.3.1 SELECT的简单查询
先从最简单的查询开始
#SELECT 字段/* from 表明;
SELECT * FROM `film`;
SELECT `title`,`time` FROM `film` #查询多个字段
SELECT后面可以跟要查询的字段,老规矩查询多个字段逗号隔开,所有要查询所有字段可填*
除此之外,可以通过AS来对字段或者表做别名
SELECT `title` AS 标题,`time` AS 时间 FROM `film` #查询多个字段 输出时title变为了标题 time变为时间
#对表命名
SELECT `title`,`time` FROM `film` AS flim;
拓展:concat(a,b) //拼接a和b字符串为一个完整的字符串
SELECT CONCAT("标题",title) AS 标题 FROM `film`; #输出后给每条查询结果加上标题这个字段
如果查询的字段有许多重复的数据,那么可以使用DISTINCT来去重
SELECT DISTINCT `id` FROM Result;
还能对查询的结果就行一系列的运算处理,比如把要查询的ID+1
SELECT DISTINCT `id`+1 AS newId FROM Result;
8.3.2 SELECT配合WHERE进行模糊查询
模糊查询,是一种很方便的查询方式,用来查询符合某种指定格式的数据,比如想查询所有包含a字符的数据,就可以使用模糊查询。 2. 模糊查询语法 模糊查询是利用“_”表示单个字符和“%”表示任意个字符进行匹配的。
MySQL允许使用Like语句进行模糊查询
- %代表某个字符前或后的所有字符
- _代表字符前或后的单个字符
比如说:
#查询title中包含“天”字的电影
SELECT `title` AS 影名,`time` AS 时间 FROM `film` WHERE `title` LIKE "%天%";
#查询title中包含“天”字且三个字的电影名
SELECT `title` AS 电影名,`time` AS 时间 FROM `film` WHERE `title` LIKE "天__" OR `title` LIKE "_天_" OR `title` LIKE "__天";
MySQL允许使用In语句进行范围的搜索
- In后面括号跟具体多个值 不能使用Like的%和_
- 只要条件满足括号内的值就返回真
比如说:
#查询类型为科幻片、纪录片、恐怖片的电影
SELECT `title` AS 电影名,`class` AS 类型 FROM `film` WHERE `class` IN ("科幻片","纪录片","恐怖片");
IS NULL or IS NOT NULL
比如:
#查询指定字段为NULL或者不是NULL的记录
SELECT `title` AS 电影名,`class` AS 类型 FROM `film` WHERE `class` IS NULL;
8.3.3 连表查询
(个人理解)
概念引入:能查A表数据,能查B表数据,但有时候需要得到的数据是需要把A表和B表结合起来的数据,此时就需要运用连表查询
知难而退(?):连表查询是MySQL的重难点,也是最常用的查询方式,是新手和入门级大佬的分水岭
图1
从简单的开始讲,连表查询需要有一个集合的框架,如上图所示,有A集合和B集合两个集合
- 其中数据根据集合可分为三大板块(以A集合为例):A集合、B集合、AB集合公共部分
- 在根据1中互相组合可以组合成上图的七个部分
在学习语句之前,得先有一个术语的概念,在上图中A为左表,B为右表
(由于是个人建立的假数据学习,所以各方面演示都比较笼统,建议自己动手测试)
下面开始学习MySQL的四种查询方式:
- LEFT JOIN
- RIGHT JOIN
- UNION
- INNER JOIN
为了方便理解创建如下两张表
a表:
b表:
8.3.3.1 INNER JOIN
INNER JOIN:查询左表与右表的公共部分
SELECT a.*,b.* FROM `afrom` AS a
INNER JOIN `bfrom` AS b
on a.name=b.id;
现在还没用的知识:FROM后面跟着的被定义为左表(即图1的A集合),INNER JOIN后面跟的被定义为右表(即图1的B集合)
查询A表的name与b表id相等的结果
8.3.3.2 RIGHT JOIN
LEFT JOIN:以右表为主,当遇到右表有左表没有的时候,相对应字段用NULL填充
SELECT b.*,a.* FROM `afrom` AS a
RIGHT JOIN `bfrom` AS b
on a.name=b.id;
在如上查询中,右表为主,可以理解为先列出右表的所有内容,在根据右表的id与左表的name一一对应的查询显示,遇到如id为1050在左表存在,右表不存在的情况下,对应字段使用null填充
8.3.3.3 LEFT JOIN
LEFT JOIN:以左表为主,当遇到左表有右表没有的时候,相对应字段用NULL填充
SELECT b.*,a.* FROM `afrom` AS a
LEFT JOIN `bfrom` AS b
on a.name=b.id
;
同RIGHT JOIN差不多不多讲了看结果
8.3.3.4 union == full JOIN
union:将两个查询结果,重复的记录会合并
SELECT b.*,a.* FROM `afrom` AS a
LEFT JOIN `bfrom` AS b
on a.name=b.id #记录1
UNION
SELECT b.*,a.* FROM `afrom` AS a
RIGHT JOIN `bfrom` AS b #记录B
on a.name=b.id;
8.3.3.5 JOIN & WHERE
在掌握了上述的连表查询方法之后,已经学会了图1中1、2、3三种查询方式
剩下的四种需要配合WHERE语句就行进阶的查询,先要理清楚LEFT JOIN 和RIGHT JOIN
LEFT JOIN是以左表为主,RIGHT JOIN是以右表为主
假设A表+B表为一个全集U,利用MySQL语句查询CuB,即A表有中B没有的集合,因此可以根据查询结果后加WHERE对其就行处理
思路:在以A表为左表使用LEFT JOIN查询,肯定会列出了所有A表的数据,如果发现A表存在B表不存在的数据,对应的字段用NULL填充,则对查询LEFT JOIN查询的结果后使用WHERE语句筛选出B表字段为null的结果,那么就是查询A表有中B没有的数据(图1中的4)
SELECT b.*,a.* FROM `afrom` AS a
LEFT JOIN `bfrom` AS b
on a.name=b.id
WHERE b.id IS NULL;
如果你理解了上述讲的不是很好的概念,那么使用RIGHT JOIN查询表1中第六种情况也很简单
SELECT b.*,a.* FROM `afrom` AS a
RIGHT JOIN `bfrom` AS b
on a.name=b.id
WHERE a.name IS NULL;
那么两种结果使用union连起来就是,第七种情况
SELECT b.*,a.* FROM `afrom` AS a
LEFT JOIN `bfrom` AS b
on a.name=b.id
WHERE b.id IS NULL
UNION
SELECT b.*,a.* FROM `afrom` AS a
RIGHT JOIN `bfrom` AS b
on a.name=b.id
WHERE a.name IS NULL;
总结&练习
在原有的基础上完善一下数据
改变a表的班级,创建规则如下,十位数代表几,个位数代表班级,如下:
通过以下MySQL创建班级的id表
INSERT INTO `gradetest`(`id`,`name`) VALUES
(11,"大一一班"),(12,"大一二班"),(13,"大一三班"),(14,"大一四班"),(15,"大一五班"),
(16,"大一六班"),(17,"大一七班"),(18,"大一八班"),(19,"大一九班"),
(21,"大二一班"),(22,"大二二班"),(23,"大二三班"),(24,"大二四班"),(25,"大二五班"),
(26,"大二六班"),(27,"大二七班"),(28,"大二八班"),(29,"大二九班"),
(31,"大三一班"),(32,"大三二班"),(33,"大三三班"),(34,"大三四班"),(35,"大三五班"),
(36,"大三六班"),(37,"大三七班"),(38,"大三八班"),(39,"大三九班"),
(41,"大四一班"),(42,"大四二班"),(43,"大四三班"),(44,"大四四班"),(45,"大四五班"),
(46,"大四六班"),(47,"大四七班"),(48,"大四八班"),(49,"大四九班")
接下来开始练习:
-- 查询成绩高于60同学的详细信息(信息完全的同学)
-- 列出学号、姓名、性别、班级、成绩
SELECT
b.id AS 学号,b.name AS 姓名,a.sex AS 性别, -- 列出学号 、姓名、性别
aGrade.`name` AS 班级,a.score AS 分数 -- 列出班级、分数
FROM `afrom` AS a INNER JOIN `bfrom` AS b ON a.`name`=b.id
INNER JOIN `gradetest` AS `aGrade` ON a.gradeId=aGrade.id
WHERE a.score > 85
;
8.4查询的微末细节
关于group by、having、where三者的用法(摘自网上su_bao博主)
WHERE语句在GROUP BY语句之前;SQL会在分组之前计算WHERE语句。
HAVING语句在GROUP BY语句之后;SQL会在分组之后计算HAVING语句。
先通过WHERE语句进行对结果的筛选,之后通过GROUP BY语句进行过滤,HAVING为组后过滤,即分组后再过滤
8.5子查询语句
在之前的学习中Where语句后面都是跟随的固定值,但实际上where的条件可以是一条查询语句,这条语句为称之为子查询语句
比如查询某个年级段大于80分的成绩
SELECT a.`name` AS 学号,b.`name` AS 姓名,a.sex AS 性别, a.score AS 分数,a.gradeId AS 年级id
FROM afrom a INNER JOIN bfrom b ON b.id=a.`name`
WHERE a.gradeId IN (SELECT id FROM gradetest WHERE `id` BETWEEN 10 AND 20)
AND a.score>80;
9.事物基本了解
事务(Transaction),一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务通常由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写的用户程序的执行所引起,并用形如begin transaction和end transaction语句(或函数调用)来界定。事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。 ——百度百科
最经典还是属于银行转账的例子,假设A要给B转账,如果转账过程中A突然断网了,在没做好事物处理的时候,就会出现A转出去了,B没收到,或者B收到了A没转出去的BUG,事务就是为了针对这一问题,将两件事情同步执行,要么都成功要么都失败,同时事物也具有四个特性:
- 原子性
- 事务是多件事情执行,但事物的原子性保证了所有事情看成一个整体,一荣俱荣一损俱损
- 一致性
- 事务中,所有DML语句操作数据时,执行前后数据要保持一致性,"总量必须不变"
- 隔离性
- 事务A和事务B具有完全的隔离,互不相干
- 持续性
- 事务在最后结束时,都将内存数据持久化到硬盘中
9.1事务的基本操作
To be or not to be,This is a question.
- commit:提交
- rollback:回滚
MySQL默认是事务开启的状态,对此在以往的Insert、update、delete语句执行过程中不会出现差错
每次调用增删改三个语句时,MySQL会自动创建一个事务提交 即事务的自动提交
如何关闭和开启事务的自动提交??
SET autocommit = 0|1|ON|OFF; -- 0和OFF为关闭 1和ON为开启
为了方便学习事务的基本操作,这次不在使用MySQL可视化工具来演示,而采用控制台窗口
回顾之前的登陆MySQL,并且关闭自动提交
set autocommit = 0;
查询结果
show variables like 'autocommit'
创建银行表(先通过use进入库)
create table if not exists `bank`(`name` varchar(4) not null comment "name",money int(4) not null comment"money")engine=innodb default charset=utf8;
插入数据
insert into bank(`name`,`money`) values ("张三","1000"),("李四","100");
select * from bank; -- 查询结果
模拟张三给李四转账
mysql> select * from bank;
+------+-------+
| name | money |
+------+-------+
| 张三 | 1000 |
| 李四 | 100 |
+------+-------+
2 rows in set (0.00 sec)
mysql> updata bank set money=money-500 where `name`="张三";
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'updata bank set money=money-500 where `name`="张三"' at line 1
mysql> update bank set money=money-500 where `name`="张三";
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update bank set money=money+500 where `name`="李四";
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from bank;
+------+-------+
| name | money |
+------+-------+
| 张三 | 500 |
| 李四 | 600 |
+------+-------+
2 rows in set (0.00 sec)
看似好像是转账成功了,别急,我们重新打开一个cmd窗口连接上数据看看
mysql> select * from bank;
Empty set (0.00 sec)
为什么是空的?回顾之前的操作,我们先关闭了数据库的自动提交,在创建表再插入数据,由于没有执行commit因此对于tables的增删改查只是做到了创建表
为了验证猜想,打开第一个MySQL窗口输入
mysql> commit;
Query OK, 0 rows affected (0.01 sec)
在重新查询,发现查到了之前的改的
mysql> select * from bank;
+------+-------+
| name | money |
+------+-------+
| 张三 | 500 |
| 李四 | 600 |
+------+-------+
2 rows in set (0.01 sec)
rollback与commit是同理,在语句执行失败的时候,就行回滚操作,将在下篇讨论......
下篇地址:等待更新....