数据库科普:
一、数据库的好处
1.可以持久化数据到本地
2.结构化查询
二、数据库的常见概念
1.DB: 数据库,存储数据的容器
2.DBMS: 数据库管理系统,又称为数据库软件或数据库产品,用于创建或管理DB
3.SQL: 结构化查询语言,用于和数据库通信的语言,不是某个数据库软件特有的,而是几乎所有的主流数据库软件通用的语言
三、数据库存储数据的特点
1.数据存放到表中,然后表再放到库中
2.一个库中可以有多张表,每张表具有唯一的表名用来标识自己
3.表中有一个或多个列,列又称为“字段”
四、MySQL服务的启动和停止
1.通过命令行: net start 服务名 net stop 服务名
2.计算机--右击--管理--服务
五、MySQL服务的登录和退出
登录:mysql [-h 主机名 -p 端口号] -u用户名 -p 密码
退出:exit 或 ctrl+c
MySQL的常见命令:
1.查看当前所有的数据库
show databases;
2.打开指定的库
use 库名
3.查看当前库的所有表
show tables;
4.查看其他库的所有表
show tables from 库名;
5.创建表
create table 表名(
列名 列类型,
列名 列类型,
。。。
);
6.查看表结构
desc 表名;
7.查看服务器的版本
(1)登录到mysql服务端: select version();
(2)没有登录到mysql服务端
mysql --version 或 mysql --V
8.起别名
(1)使用as : select 100%98 as 结果
(2)使用空格 : select 100%98 结果
9.mysql中的+号
仅仅只有一个功能:运算符
select 100+90; #190 (两个操作数都为数值型,则做加法运算)
select '123'+90; #213 (转换成功,则继续做加法运算)
select ‘john’+90; #90 (转换失败,则将字符型数值转换成0)
select null+90; #null (只要一方为null,则结果肯定为null)
10.DISTINCT 去重
exp: SELECT DISTINCT job_id FROM employees;
11.模糊查询 LIKE _ %
exp1: SELECT salary FROM employees WHERE last_name LIKE '__n_l%'
exp2:查询员工名中第二个字符为_的员工名
exp2: SELECT last_name FROM employees WHERE last_name LIKE '_$_%' ESCAPE '$' (自定义转义字符)
12.安全等于 <=> (基本不用)
既可=NULL,又可=12000 (数值)
13.排序查询
order by 排序列表 【asc | desc】 (默认asc 升序)
14.upper、lower 大小写转换
SELECT UPPER('john');
SELECT LOWER('joHn');
exp: 将姓变大写,名变小写,然后拼接
exp: SELECT CONCAT( UPPER(last_name),LOWER(first_name) ) 姓名 FROM employees;
15.substr、substring字符截取 (注:索引从1开始)
#截取从指定索引处后面所有的字符(包含)
SELECT SUBSTR('李莫愁爱上了陆展元',7) out_put;
#截取从指定索引处后面指定字符长度的字符(包含)
SELECT SUBSTR('李莫愁爱上了陆展元',1,3) out_put;
exp: 姓名中首字符大写,其他字符小写然后用_拼接,显示出来
exp: SELECT CONCAT(UPPER(SUBSTR(last_name,1,1)),LOWER(SUBSTR(last_name,2))) out_put
16.instr返回子串第一次出现的索引,如果找不到返回0
SELECT INSTR('ABCDEFGHIJ','HIJ') AS out_put;
17.trim 清除两端的空格
SELECT LENGTH(TRIM(' ABC ')) AS out_put; # 3
SEKECT TRIM('aa' FROM 'aaaaaaaWaaaaaaaERaaaaa') AS out_put; # aWaaaaaaaERa
18.lpad、rpad用指定的字符实现左、右填充指定长度
SELECT LPAD('ABC',2,'@') AS out_put; # AB
SELECT LPAD('ABC',6,'@') AS out_put; # @@@ABC
SELECT RPAD('ABC',6,'ab') AS out_put # ABCaba
19.replace替换
SELECT REPLACE('ABCABCWWWEEERRRABC','ABC','UP') AS out_put; # UPUPWWWEEERRRUP
19.数学函数: round四舍五入、ceil向上取整、floor向下取整、truncate截断、mod取余
SELECT ROUND(-1.55); # -2
SELECT ROUND(1.567,2); # 1.57
SELECT CEIL(1.02); # 2
SELECT FLOOR(9.99); # 9
SELECT TRUNCATE(1.69999,1); # 1.6
SELECT MOD(10,3); # 1
20.时间函数: %Y %y %m %c %d %H %h %i %s
%Y 四位的年份 %y 2位的年份 %m 月份(01,02,...,11,12) %c 月份(1,2,...,11,12) %d 日(01,02,...)
%H 小时(24小时制) %h 小时(12小时制) %i 分钟(00,01,...,59) %s 秒(00,01,...,59)
21.日期函数:NOW()、CURDATE()、CURTIME()、YEAR()、MONTH()、STR_TO_DATE()、DATE_FORMAT()
SELECT NOW(); #now 返回当前系统日期+时间
SELECT CURDATE(); #curdate 返回当前系统日期,不包含时间
SELECT CURTIME(); #curtime 返回当前时间,不包含日期
#可以获取指定的部分,年,月,日,小时,分钟,秒
SELECT YEAR(NOW()) 年;
SELECT YEAR(hiredate) 年 FROM employees
SELECT MONTH(NOW()) 月; # 数字
SELECT MONTHNAME(NOW()) 月; # 英文
#str_to_date 将字符通过指定的格式转换成日期
SELECT STR_TO_DATE('1998-3-2','%Y-%c-%d') AS out_put;
#查询入职日期为1992-4-3的员工信息
SELECT * FROM employees WHERE hiredate = '1992-4-3';
SELECT * FROM employees WHERE hiredate = STR_TO_DATE('4-3 1992','%c-%d %Y');
#date_format 将日期转换成字符
SELECT DATE_FORMAT(NOW(),'%y年%m月%d日') AS out_put; # 21年5月12日
#查询有奖金的员工名和入职日期(xx月/xx日 xx年)
SELECT last_name, DATE_FORMAT(hiredate,‘%m月/%d日 %y年’)入职日期
FROM employees WHERE commission_pct IS NOT NULL;
22.流程控制函数
(1)if函数: SELECT IF(10>5,'大','小')
(2)case函数的使用一: (switch case 的效果)
case 要判断的字段或表达式
when 常量1 then 要显示的值1或语句1;
when 常量2 then 要显示的值2或语句2;
...
else 要显示的值n或语句n;
end
exp:
SELECT salary 原始工资,department_id,
CASE department_id
WHEN 30 THEN salary*1.1
WHEN 40 THEN salary*1.2
ELSE salary
END AS 新工资
FROM employees;
(2)case函数的使用二: (类似于 多重if)
case
when 条件1 then 要显示的值1或语句1;
when 条件2 then 要显示的值2或语句2;
...
else 要显示的值n或语句n
end
exp:查询员工的工资的情况
如果工资>20000,显示A级别,如果工资>15000,显示B级别,否则,显示C级别
SELECT salary,
CASE
WHEN salary>20000 THEN 'A'
WHEN salary>15000 THEN 'B'
ELSE 'C'
END AS 工资级别
FROM employees;
23.分组函数: sum求和、avg平均值、max最大值、min最小值、count计算个数(这5种都忽略空值)
于分组函数一同查询的字段要求是group by后的字段
24.sql99语法:
select 查询列表
from 表一 别名 【连接类型】
join 表二 别名 (inner、left、right、full、cross)
on 连接条件
【where 筛选条件】
【group by分组】
【having 筛选条件】
【order by 排序列表】
【limit [offset , ] size】
25:子查询:出现在其他语句中的select语句
(1)按子查询出现的位置分类:
select后面: 仅仅支持标量子查询
from后面: 支持表子查询 (将子查询结果充当一张表,要求必须起别名)
where或having后面: ☆标量、列子、行子查询
exists后面:(相关子查询)表子查询
(2)按结果集的行列数不同:
标量(一行一列)、列子(一列多行)、行子(一行多列)、表子查询(多行多列)
exp1:谁的工资比Abel高?
①查询Abel的工资
SELECT salary
FROM employees
WHERE last_name = 'Abel';
②查询员工的信息,满足salary>①的结果
SELECT *
FROM employees
WHERE salary>(
SELECT salary
FROM employees
WHERE last_name = 'Abel'
);
exp2:查询每个部门的平均工资的工资等级
①查询每个部门的平均工资
SELECT AVG(salary),department_id
FROM employees
GROUP BY department_id
②连接①的结果集和job_grades表,筛选条件平均工资 between lowest_sal and highest_sal
SELECT avg_dep.* , g.grade_level
FROM(
SELECT AVG(salary) avg , department_id
FROM employees
GROUP BY department_id
) avg_dep
INNER JOIN job_grades g
ON avg_dep.avg BETWEEN lowest_sal AND highest_sal;
exists(完整的查询语句) # 结果:1或0
exp3:查询有员工的部门名
SELECT department_name
FROM departments d
WHERE EXISTS(
SELECT *
FROM employees e
WHERE d.department_id = e.department_id
);
或 (能有exists的绝对能用in实现)
SELECT department_name
FROM departments d
WHERE d.department_id IN(
SELECT department_id
FROM employees
);
26:多行子查询:IN / NOT IN、ANY|SOME、ALL
IN / NOT IN:等于列表中的任意一个
ANY|SOME:和子查询返回的某一个值比较
ALL:和子查询返回的所有值比较
27.分页查询 LIMIT (公式: 要显示的页数page,每页条目数size limit (page-1)*size,size ; )
exp:查询前五条员工信息
SELECT * FROM employees LIMIT 0,5;
SELECT * FROM employees LIMIT 5;
28.联合查询 UNION 将多条查询语句的结果合并成一个结果
语法: 查询语句1 union 查询语句2 union ...
应用场景:要查询的结果来自于多个表,且多个表没有直接的连接关系,但查询的信息一致时
特点:☆
1.要求多条查询语句列数是一致的
2.要求多条查询语句的查询的每一列的类型和顺序最好一致
3.union关键字默认去重,如果使用union all可以包含重复项
exp:查询中国用户中男性的用户信息以及外国用户中男性的用户信息 结果# id cname csex
SELECT id,cname,csex FROM t_ca WHERE csex='男' 2 李雷 男
UNION 3 李明 男
SELECT t_id,t_name,t_csex FROM t_ua WHERE t_csex='male' 1 john male
4 jack male
29.DML语言(数据操作语言)insert、update、delete
#插入语句
#插入方式一 (支持插入多行、子查询)
语法:insert into 表名(列名, ...)values(值1, ...) [,(...),(...)] ; # 加[ ]里的内容则为插入多行
(1)插入的值的类型要与列的类型一致或兼容
(2)不可以为null的列必须插入值,可以为null的列可插入null值或者不写
(3)列的顺序可以调换
(4)列数和值的个数必须一致
(5)可以省略列名,默认所有列,而且列的顺序和表中列的顺序一致
exp: INSERT INTO beauty VALUES( 18 , '张飞' , '男' , ‘119’ , NULL , NULL )
exp: INSERT INTO beauty(id,NAME,phone) #插入子查询的结果集则省略values
SELECT 26,'宋茜',‘11809866’;
#插入方式二 (不支持插入多行、子查询)
语法:insert into 表名 set 列名=值,列名=值,...
exp: INSERT INTO beauty SET id=19,NAME='刘涛',phone='999';
#修改语句
#修改单表的记录
语法:update 表名 set 列=新值,列=新值,... where 筛选条件;
exp: UPDATE boys SET boyname='张飞',usercp=10 WHERE id=2;
#修改多表的记录
语法:update 表1 别名 inner|left|right join 表2 别名 on 连接条件 set 列=新值, ... where筛选条件:
exp: 修改张无忌的女朋友的手机号为114
UPDATE boys bo
INNER JOIN beauty b ON bo.id=b.boyfriend_id
SET b.phone='114'
WHERE bo.boyName='张无忌';
#删除语句
方式一:delete
语法:单表的删除:delete from 表名 where 筛选条件
多表的删除:delete 表1的别名,表2的别名 from 表1 别名 inner|left|right join 表2 别名 on 连接条件 where 筛选条件;
exp: 删除张无忌的女朋友的信息 (多表的删除可以删除一个表或多个表的数据,如:DELETE b,bo ... )
DELETE b
FROM beauty b
INNER JOIN boys bo ON b.boyfriend_id = bo.id
WHERE bo.boyName='张无忌';
方式二:truncate
语法: truncate table 表名;
exp: TRUNCATE TABLE boys;
dalete VS truncate
1.delete可以加where条件,truncate不能
2.truncate删除,效率高一点
3.假如要删除的表中有自增长列,如果用delete删除后,再插入数据,自增长列的值从断点开始,而用truncate则从1开始
4.truncate删除没有返回值,delete删除有返回值(执行命令时是否显示:共n行受到影响)
5.truncate删除不能回滚,delete删除可以回滚
30.DDL (数据定义语言) create、alter、drop
#库的管理
CREATE DATABASE IF NOT EXISTS books; #创建库books
RENAME DATABASE books TO 新库名; #修改库名
ALTER DARABASE books CHARCTER SET gbk; #更改库的字符集
DROP DATABASE 【IF EXISTS】books; #库的删除
#表的管理
#表的创建,语法:
create table 表名(
列名 列的类型 【(长度)约束】,
列名 列的类型 【(长度)约束】,
...
列名 列的类型 【(长度)约束】
)
exp:
CREATE TABLE book(
id INT,
bName VARCHAR(20),
price DOUBLE,
authorId INT UNSIGNED,
publishDate DATETIME
);
#表的修改
#语法:alter table 表名 add|drop|modify|change column 列名 【列类型 约束】;
ALTER TABLE book CHANGE COLUMN publishdate pubDate DATETIME; #修改列名
ALTER TABLE book MODIFY COLUMN annual DOUBLE; #修改列的类型或约束
ALTER TABLE author DROP COLUMN annual; #删除列
ALTER TABLE author RENAME TO book_author; #修改表名
#表的删除
DROP TABLE book_author;
#表的复制
(1)仅仅复制表的结构
CREATE TABLE copy LIKE author;
(2)复制表的结构+数据 (也可复制部分数据,如复制部分列,或者加筛选条件)
CREATE TABLE copy2
SELECT * FROM author;
(3)仅仅复制某些字段 (列名)
CREATE TABLE copy3
SELECT id,au_name
FROM author
WHERE 1=2; (或者 WHERE 0 )
31.数值类型Tinyint、Smallint、Mediumint、Int | Interger、Bigint (占用字节分别为:1,2,3,4,8)
数值型:整型
小数:定点数 浮点数
字符型:较短的文本:char、varchar
较长的文本:text、blob(较长的二进制数据)
其他:binary和varbinary用于保存较短的二进制
enum用于保存枚举
set用于保存集合
日期型:只保存日期 date
只保存时间 time
只保存年 year # 字节 范围 时区等的影响
保存日期+时间 datetime 8 1000-9999 不受
保存日期+时间 timestamp 4 1970-2038 受
整型特点:
(1)如果不设置,默认是有符号,设置则添加unsigned关键字
(2)如果插入的数值超出了整形范围,会报out of range异常,并且插入临界值
(3)如果不设置长度,会有默认长度
小数特点:
浮点型 float(M,D) double(M,D) M:整数部位+小数部位
定点型 dec(M,D) decimal(M,D) D:小数部位
(1)如果超过范围,则插入临界值
(2)M和D都可以省略
(如果是decimal,则M默认为10,D默认为0;如果是float和double,则会根据插入的数值的精度来决定精度)
字符型特点:
写法 M的意思 特点 空间的耗费 效率
char char(M) 最大字符数,可以省略,默认为1 固定长度的字符 比较耗费 高
varchar varchar(M) 最大字符数,不可以省略 可变长度的字符 比较节省 低
31.六大约束 (含义:一种限制,用于限制表中的数据,为了保证表中的数据的准确和可靠性)
NOT NULL : 非空,用于保证该字段的值不能为空
DEFAULT : 默认,用于保存该字段的默认值
PRIMARY KEY : 主键,用于保证该字段的值具有唯一性,并且非空
UNIQUE : 唯一,用于保证该字段的值具有唯一性,可以为空
CHECK : 检查约束 【mysql中不支持】
FOREIGN KEY : 外键,用于限制两个表的关系,用于保证该字段的值必须来自于主表的关联列的值
在从表添加外键约束,用于引用主表中某列的值
添加约束的时机: 1.创建表时 2.修改表时
约束的添加分类: 1.列级约束 # 六大约束语法上都支持,但外键约束没有效果
2.表级约束 # 除了非空、默认,其他的都支持
添加表级约束的语法: 在各个字段的最下面添加: constraint 约束名 约束类型 (字段名)
#创建表时添加约束
CREATTE TABLE 表名(
字段名 字段类型 列级约束,
字段名 字段类型,
表级约束
)
#添加列级约束和表级约束(通用的写法)
exp:
CREATE TABLE IF NOT EXISTS stuinfo(
id INT PRIMARY KEY, # 主键
stuName VARCHAR(20) NOT NULL, # 非空
gender CHAR(1) CHECK (gender='男' OR gender='女'), # 检查
seat INT UNIQUE, # 唯一
age INT DEFAULT 18, # 默认约束
majorId INT FOREIGN KEY REFERENCES major(id) # 外键
CONSTRANT pk PRIMARY KEY(id), # 主键
CONSTRANT uq UNIQUE(seat), # 唯一键
CONSTRAINT fk_stuinfo_major FOREIGN KEY(majorid) REFERENCES major(id) # 外键
);
CREATE TABLE major(
id INT PRIMARY KEY,
majorName VARCHAR(20)
);
SHOW INDEX FROM stuinfo; # 查看表中的所有索引,包括主键、外键、唯一
主键 VS 唯一:
保证唯一性 是否允许为空 一个表中可以有多少个 是否允许组合
主键 √ × 至多有1个 √,但不推荐
唯一 √ √ 可以有多个 √,但不推荐
外键:
(1)要求在从表设置外键关系
(2)从表的外键列的类型和主表的关联列的类型要求一致或兼容,名称无要求
(3)主表的关联列必须是一个key (一般是主键或唯一)
(4)插入数据时,先插入主表,再插入从表;删除数据时,先删除从表,再删除主表
#修改表时添加约束
(1)添加列级约束: alter table 表名 modify column 字段名 字段类型 新约束;
(2)添加表级约束: alter table 表名 add [constraint 约束名] 约束类型(字段名) 【外键的引用】;
CREATE TABLE stuinfo(
id INT,
stuname VARCHAR(20),
gender CHAR(1),
seat INT,
age INT,
majorid INT
);
ALTER TABLE stuinfo MODIFY COLUMN stuname VARCHAR(20) NOT NULL; # 添加非空约束
ALTER TABLE stuinfo MODIFY COLUMN age INT DEFAULT 18; # 添加默认约束
#添加主键
ALTER TABLE stuinfo MODIFY COLUMN id INT PRIMARY KEY; # 列级约束
ALTER TABLE stuinfo ADD PRIMARY KEY(id); # 表级约束
#添加唯一
ALTER TABLE stuinfo MODIFY COLUMN seat INT UNIQUE; # 列级约束
ALTER TABLE stuinfo ADD UNIQUE(seat); # 表级约束
#添加外键
ALTER TABLE stuinfo ADD FOREIGN KEY(majorid) REFERENCES major(id);
#修改表时删除约束
ALTER TABLE stuinfo MODIFY COLUMN stuname VARCHAR(20) NULL; # 删除非空约束
ALTER TABLE stuinfo MODIFY COLUMN age INT; # 删除默认约束
ALTER TABLE stuinfo DROP PRIMARY KEY; # 删除主键
ALTER TABLE stuinfo DROP INDEX seat; # 删除唯一 (如果不知道唯一约束名称,可以先 SHOW INDEX FROM stuinfo; )
ALTER TABLE stuinfo DROP FOREIGN KEY mojorid; # 删除外键 (同理:可以先 SHOW INDEX FROM stuinfo; )
mysql踩坑:
1.mysql函数str_to_date(date,format)使用时报错。
排查问题,发现str_to_date(date,format)函数的第一个参数不能是空字符串,反而为null时并不影响。
解决方案:STR_TO_DATE(if(date=’’, null , date), format)