数据库的概述
1. 为什么要使用数据库
数据库可以实现数据的持久化
数据库可以存储的数据量非常庞大
数据库中存储的数据类型多变
常见的数据库:Oracle,MySQL,SQL Server,DB2,PGSQL;Redis,MongoDB,ES
MySQL由瑞典的MySQL AB创立,1995年开发出的MySQL
Mysql的特点:
- 开源的,关系型数据库
- 支持千万级数据量的存储,大型的数据库
DB:database,看做是数据库文件,(类似于:.doc,.txt,.mp3,.avi)
DBMS:数据库管理系统(类似于word工具,wps工具)
MySQL数据库服务器中安装了MySQL DBMS,通过MySQL DBMS 来操作DB,使用的是MySQL语言
DBMS--执行-->SQL--操作-->DB
2.数据库与数据库管理系统
2.1数据库的相关概念
DB:数据库(Database) |
即存储数据的仓库,其本质是一个文件系统,它保存了一系列有组织的数据 |
DBMS:数据库管理系统(Database Management System) |
是一种操纵和管理数据库的大型软件,用于建立,使用和维护数据库,对数据库进行统一管理和控制,用户通过数据库管理系统访问数据库中表内的数据 |
SQL:结构化查询语言(Structured Query Language) |
专门用来与数据库通信的语言 |
2.2数据库与数据库管理系统的关系
数据库管理系统可以管理多个数据库,DBMS通过sql来操作数据库
MySQL
MySQL是一个开放的关系型数据库管理系统
RDBMS(关系型数据库)与非RDBMS(非关系型数据库)
RDBMS
DBMS以行和列的形式存储数据
SQL就是关系型数据库的查询语言
非RDBMS
非关系型数据库可以看成关系型数据库的阉割版本,
键值型的数据库
通过key-value键值的方式来存储数据,使用场景是作为内存的缓存,redis是最流行的键值型数据库
文档型数据库
可以存放XML,JSON等格式的数据文档数据库所存放的文档相当于键值数据库所存放的值
MongoDB是最流行的文档行数据库
搜索引擎数据库
核心原理是“倒排索引”主流是Es(Elasticsearch)
关系型数据库
关系型数据库的典型结构就是数据表
将数据存入表内,再将表存入数据库中
一个数据库中可以有多个表,每个表都有一个名字,用来标识自己,
ORM思想(Object Relational Mapping)
数据库中的一个表<-->Java或python中的一个类
表中的一个数据<-->类中的一个对象
表中的一列<-->类中的一个属性
表的关联关系
表与表之间的数据记录有关系
四种:一对一关联,一对多关联,多对多关联,自我引用
一对一关联
设计成一张表的话,SQL会比较简洁,但有的不常用,设计成两个表SQL虽然会很复杂,但会优化SQL的查询
一对多关联
分为主表和从表
多对多关联
要表示多对多的关系,必须创建第三个表,该表通常称为联接表,中间表至少有两个字段
自我引用
如果访问的是本机并且是3306那么可以将-P端口号-h主机名删除掉
SQL语言的分类
- DDL:(主要操作的是表结构,不是表中的数据)
数据定义语言。create \alter(修改)\ drop(删除)
- DML:(凡是对表当中的数据进行增删改的都是DML)
数据操作语言 。 insert \delete \ update
- DCL:数据控制语言 。 savepoint \ grant(授权)\ revoke(撤销权限)
- DQL:(select)
- 数据查询语言(凡是带有select关键字的都是查询语言)
- TCL:(事务控制语言)
事务提交:commit
事务回滚:rollback
SQL大小写规范
- MySQL在windows环境下是不敏感的
- MySQL在linux环境下是敏感的
-
- 数据库名,表名,表的别名,变量名是严格区分大小写的
- 关键字,函数名,列名,列的别名是忽略大小写的
- 推荐采用统一的书写规范
-
- 数据库名,表名,表的别名,字段名,字段别名都是用小写
- SQL关键字,函数名,绑定变量等都大写
- 字符串都用''来表示
SQL的注释
#是单行注释,/* */是多行注释 -- 单行注释,注释文字
Mysql的常见命令
Mysql -u root -p 密码:登录Mysql
退出mysql:exit
查看mysql有哪些数据库:show databases
怎么选择使用某个数据库:use 数据库名称
怎么创建数据库:create database 数据库名称
怎么删除数据库:drop database数据库名称
查看数据库下有哪些表:show tables
怎么将sql文件中的数据导入:source sql文件路径
查看数据库的版本号:select version();
查看当前使用的是哪个数据库:select database();
#启动MySQL服务命令
net start MySQL服务名
#停止MySQL服务命令
net stop MySQL服务名
表的理解
数据库中最基本的单位就是表,数据库当中是以表格的形式表示数据的
任何一张表都有行和列:
行(row):被称为数据
列(column):被称为字段
每一个字段都有:字段名,数据类型,约束等属性
DQL基本语句
基本的SELECT语句
SELECT...FROM
SELECT 字段名 FROM 表名
SELECT FROM是关键字,字段名和表名都是标识符
所有的sql语句都以;结尾
查询所有字段可以用*表示(但是查询效率低,可读性差)
SELECT 'name'
FROM student;
列的别名
AS:使用AS关键字,可以命名别名
SELECT 'name' AS "dname"
FROM student
去除重复记录
DISTINCT只能出现在所有字段的最前方,表示字段联合起来清除重复记录
SELECT DISTINCT department_id
FROM emloyees;
原表的数据不会被修改,只是查询结果去重
空值参与运算
NULL:NULL的意思是不知道,就算不知道,计算的时候还有其他数可以算,其值不能为NULL
有了IFNULL函数,当为NULL时,就可以按照指定值进行计算
IFNULL(commission_pct,0);
//如果字段commission_pct不为NULL,就用commission_pct本来的值计算
//如果commission_pct为NULL,就按照0计算
SELECT employee_id,lastname,commission_pct*(1+IFNULL(commission_pct,0)*12) AS 'annual salary'
FROM employees;
NULL不能用等号进行衡量,需要用is null 因为在数据库中null不表示一个值,如果不为null就用is not null表示
条件查询
如需有条件地从表中选取数据,可将 WHERE 子句添加到 SELECT 语句中
WHERE 子句中可以使用等号=来设定获取数据的条件
SELECT employees_id,last_name
FROM employees
WHERE last_name='';
and和or同时出现,and的优先级比or的优先级高,如果想要or执行,需要加()
在不确定优先级的时候都可以加()
BINARY
MySQL 的 WHERE 子句的字符串比较是不区分大小写的。 你可以使用 BINARY 关键字来设定 WHERE 子句的字符串比较是区分大小写的。
SELECT * from runoob_tbl WHERE BINARY runoob_author='runoob.com';
SELECT * from runoob_tbl WHERE BINARY runoob_author='RUNOOB.COM';
模糊查询
LIKE:LIKE 子句中使用百分号%字符来表示任意字符
#查询:last_name中包含'a'的员工信息
#%:代表任意多个的字符
SELECT last_name;
FROM employees
WHERE last_name LIKE '%a%'
#_:一个_代表任意一个的字符
SELECT last_name;
FROM employees
WHERE last_name LIKE '_a%'
#要找带有_的要用转义字符\_
between and
SELECT name,number
FROM student
# WHERE number<=1 and number>=4;
WHERE number BETWEEN 1 AND 4;//遵循左小右大
in,not in
in相当于多个or,表示在这个范围内,not in表示不在这个范围内
in后面跟的不是范围,而是具体值
SELECT *
FROM student
WHERE id IN(1,2,3,4);
查看表的结构
desc student;
DESCRIBE 显示了表中字段的详细信息
排序
如果我们需要对读取的数据进行排序,我们就可以使用 MySQL 的 ORDER BY 子句来设定你想按哪个字段哪种方式来进行排序,再返回搜索结果。
- 你可以使用 ASC 或 DESC 关键字来设置查询结果是按升序或降序排列。 默认情况下,它是按升序排列。
SELECT *
FROM friends
ORDER BY id;
#默认是升序
#指定降序
SELECT *
FROM friends
ORDER BY id desc;
#指定升序
SELECT *
FROM friends
ORDER BY id asc,salary asc;#id在前,起主导,只有id相同的时候,salary才起作用
语句执行的顺序:
- 第一步:FROM
- 第二步:WHERE
- 第三步:SELECT
- 第四步:ORDER BY(排序总是在最后一步)
算术运算符
算术运算符有:+ - / * %
伪表:是一个虚拟出来为了构成sql语句、只有一条记录和一列的数据库表,用DUAL表示
在SQL中,+没有连接的作用,就表示加法运算,字符串如果是数字转换为数字值,如果是字母则转换为0
SELECT 100+'1'//101
FROM DUAL;
SELECT 100+'a'//100
FROM DUAL;
比较运算符
比较情况为真返回1,为假返回0,其他情况返回null
= <=>(安全等于) <>不等于 != < <= > >=
只要有null参与判断就为null
<=>可以对null进行判断:
- 当两边操作数都为null的时候结果为1,当一个操作数为null时,结果返回0,不返回null
IS NULL/ IS NOT NULL / ISNULL
IS NULL 和 IS NOT NULL是关键字
ISNULL是函数
#查询表中不为null的值
SELECT last_name,salary,commission_pct
FROM employees
WHERE commission_pct IS NOT NULL;
ISNULL(expr) 如果expr的值为null则返回1,如果不为null则返回0
SELECT ISNULL(NULL); -- 输出结果:1
SELECT ISNULL('HELLO'); -- 输出结果:0
逻辑运算符
逻辑运算符 | 作用 |
NOT或! | 逻辑非 |
AND或&& | 逻辑与 |
OR或|| | 逻辑或 |
XOR | 逻辑异或 |
XOR 满足前面并且不满足后面,或者满足后面并并且不满足前面
AND的优先级高于OR
位运算符
位运算符都是在二进制的基础上进行操作
运算符 | 作用 |
& | 按位与 |
| | 按位或 |
^ | 按位异或 |
~ | 按位取反 |
>> | 按位右移 |
<< | 按位左移 |
数据处理函数/单行处理函数
单行处理函数的特点:一个输入对应一个输出
Lower:转换小写
SELECT LOWER(name) name
FROM student
upper 转换大写
select upper(name) as name
from student;
substr 取子串(substr(被截取的字符串,起始下标,截取的长度))
select substr(name,1,1,) as name
from student
#起始下标从1开始,没有0
length 取长度
select length(name) as namelength
from student;
trim 去空格
select *
from student
where name=trim('')
format 设置千分位
select ename,format(sal,$999,999) as sal from emp
round 四舍五入
select round(123456.78,0)
from student;
#这里的0表示保留小数点后0位
select round(1234567.89,-1)#保留到十位
from student;
rand() 生成随机数
select rand()
from student;
#生成100以内的随机数
SELECT ROUND(RAND()*100,0)
FROM student;
ifnull 可以将null转换成一个具体值
ifnull是空处理函数,专门处理空的
在所有数据库当中,只要有null参与的数学运算,结果都是null
select ename,(sal+ifnull(comm,0))*12 as year_salary
from friends;
case...when...then...when...then...else...end
SELECT name,salary as old_salary,job,
(CASE job
WHEN job=1 THEN
salary*2
WHEN job=2 THEN
salary*4
ELSE
salary
END) AS new_salary
FROM friends;
CONCAT 字符串拼接
SELECT CONCAT(name,number)
FROM student;
分组函数/多行处理函数
多行处理函数的特点:输入多行,最终输出一行
count 计数
SELECT COUNT(id)
FROM friends
sum 求和
SELECT SUM(salary)
FROM friends;
avg 平均值
SELECT AVG(salary)
FROM friends;
max 最大值
SELECT MAX(salary)
FROM friends;
min 最小值
SELECT MIN(salary)
FROM friends;
分组函数在使用前必须进行分组,然后才能使用,如果没分组,整张表看成一组
分组函数自动忽略null,不需要提前对null进行处理
分组函数中count(*)和count(具体字段):
- count(具体字段):表示统计该字段下不为null的字段数
- count(*):表示统计表的总行数,包括null的一行
分组函数不能够直接使用在where子句当中
所有分组函数可以组合起来一起用
开窗函数
在 SQL 中,开窗函数是一种强大的查询工具,它允许我们在查询中进行对分组数据进行计算、 同时保留原始行的详细信息 。
开窗函数可以与聚合函数(如 SUM、AVG、COUNT 等)结合使用,但与普通聚合函数不同,开窗函数不会导致结果集的行数减少。
sum over
SUM(计算字段名) OVER (PARTITION BY 分组字段名)
先按照字段名进行计算,然后再进行分组
sum over order by
sum over order by,可以实现同组内数据的 累加求和 。
SUM(计算字段名) OVER (PARTITION BY 分组字段名 ORDER BY 排序字段 排序规则)
先进行求和,然后按照字段进行分组,最后再进行排序
rank
Rank 开窗函数是 SQL 中一种用于对查询结果集中的行进行 排名 的开窗函数。它可以根据指定的列或表达式对结果集中的行进行排序,并为每一行分配一个排名。在排名过程中,相同的值将被赋予相同的排名,而不同的值将被赋予不同的排名。
当存在并列(相同排序值)时,Rank 会跳过后续排名,并保留相同的排名。
RANK() OVER (
PARTITION BY 列名1, 列名2, ... -- 可选,用于指定分组列
ORDER BY 列名3 [ASC|DESC], 列名4 [ASC|DESC], ... -- 用于指定排序列及排序方式
) AS rank_column
Row_number
Row_Number 开窗函数是 SQL 中的一种用于为查询结果集中的每一行 分配唯一连续排名 的开窗函数。
Row_Number 函数为每一行都分配一个唯一的整数值,不管是否存在并列(相同排序值)的情况。每一行都有一个唯一的行号,从 1 开始连续递增。
ROW_NUMBER() OVER (
PARTITION BY column1, column2, ... -- 可选,用于指定分组列
ORDER BY column3 [ASC|DESC], column4 [ASC|DESC], ... -- 用于指定排序列及排序方式
) AS row_number_column
lag/lead
开窗函数 Lag 和 Lead 的作用是获取在当前行之前或之后的行的值,这两个函数通常在需要比较相邻行数据或进行时间序列分析时非常有用。
LAG函数
Lag 函数用于获取 当前行之前 的某一列的值。它可以帮助我们查看上一行的数据。
LAG(column_name, offset, default_value) OVER (PARTITION BY partition_column ORDER BY sort_column)
- column_name:要获取值的列名。
- offset:表示要向上偏移的行数。例如,offset为1表示获取上一行的值,offset为2表示获取上两行的值,以此类推。
- default_value:可选参数,用于指定当没有前一行时的默认值。
- PARTITION BY和ORDER BY子句可选,用于分组和排序数据。
LEAD函数
Lead 函数用于获取 当前行之后 的某一列的值。它可以帮助我们查看下一行的数据。
LEAD(column_name, offset, default_value) OVER (PARTITION BY partition_column ORDER BY sort_column)
- column_name:要获取值的列名。
- offset:表示要向下偏移的行数。例如,offset为1表示获取下一行的值,offset为2表示获取下两行的值,以此类推。
- default_value:可选参数,用于指定当没有后一行时的默认值。
- PARTITION BY和ORDER BY子句可选,用于分组和排序数据。
分组查询
分组查询的执行顺序:
SELECT...
FROM...
WHERE...
GROUP BY
ORDER BY
- 先执行FROM
- 再执行WHERE
- 然后执行GROUP BY
- 然后执行SELECT
- 最后执行ORDER BY
WHERE子句后面不能跟分组函数,是因为GROUP BY在WHERE后面执行,WHERE执行的时候还没分组
GROUP BY
在一条SELECT语句当中,如果有GROUP BY语句的话,select后面只能跟参与分组的字段以及分组函数
#找出每个部门的最低工资
SELECT department,MIN(salary)
FROM friends
GROUP BY department;
要按多个情况进行分组时,将两个字段联合成一个字段来看
SELECT department,MIN(salary),job
FROM friends
GROUP BY department,job;
HAVING
使用having可以对分完组的数据进一步过滤,having不能单独使用,having必须和group by联合使用
#效率较低
SELECT department,MAX(salary)
FROM friends
GROUP BY department
HAVING
MAX(salary)>10000;
#效率较高
SELECT department,MAX(salary)
FROM friends
WHERE salary>10000
GROUP BY department;
where和having优先选择where,where完成不了的再选择having
where是先筛选再分组,having是先分组再筛选
连接查询
从一张表中单独查询,称为单表查询
从两张表中取字段多张表联合查询被称为连接查询
根据表的连接进行分类
- 内连接
-
- 等值连接
- 非等值连接
- 自连接
- 外连接
-
- 左外连接
- 右外连接
连接查询的原理:
一张表中的数据和另一张表的所有数据一一对应,直到找到对应的数据
笛卡尔积现象:
当两张表进行连接查询,没有任何条件限制的时候,最终查询条数,是两张表条数的乘积,这种现象被称为“笛卡尔积现象”
避免笛卡尔积现象:连接的时候加条件,满足这个条件的被筛选出来
通过笛卡尔积得知,表的连接次数越多,效率越低
#匹配次数没有减少,只不过进行了筛选
select emp.ename,dept.dname
from emp as e,dept as d
where e.deptno = d.deptno
内连接
等值连接
#查询每个员工所在部门名称,显示员工名和部门名
#SQL92语法 SQL92表的连接条件,和后期筛选的条件都放在了where后面
select e.ename,d.dname
from emp as e,dept as d
where e.deptno = d.deptno;
#SQL99语法 SQL99语法结构更清晰,如果需要进一步筛选可以再添加where
#inner join中inner可以省略,优点是一眼可以看出是内连接
select
e.ename,d.dname
from
emp e
inner join
dept d
on
e.deptno = d.deptno;
如果条件不满足条件,还可以用WHERE进行筛选
非等值连接
select
e.name,e.sal,sal.grade
from
emp e
join
salgrade sal
on
e.sal between sal.losal and sal.hisal;
自连接
select
a.ename as '员工名',b.ename as '领导名'
from
emp a
join
emp b
on
a.mgr=b.empno
外连接
左连接
select
e.ename,d.dname
from
dept d
left outer join
emp e
on
e.deptno = d.deptno;
left:表示将join关键字左边的看成主表,主要是将这个表中的数据全部查询出来,顺便查询关键字右边的表
LEFT JOIN 会读取左边数据表的全部数据,即使右边表无对应数据
右连接
RIGHT JOIN 会读取右边数据表的全部数据,即使左边边表无对应数据
#右外连接
select
e.ename,d.dname
from
emp e
right outer join #outer可以省略,带着可读性强
dept d
on
e.deptno = d.deptno;
right:表示将join关键字右边的表看成主表,主要是将这个表中的数据全部查询出来,顺便查询关键字左边的表
多张表怎么连接
select...
from
a
inner join
b
on
a和b的连接条件
inner join
c
on
a和c的连接条件
inner join
d
on
a和d的连接条件
子查询
SELECT的子查询
SELECT语句中嵌套select语句,被嵌套的select语句叫做子查询
#找到每个员工的部门名称
select e.ename,(select d.dname
from dept d
where e.deptno=d.deptno) as dname
from emp e
WHERE的子查询
在WHERE子句后面嵌套一个SELECT查询
#找出比最低工资高的员工姓名和工资
#先找出最低工资
select
min(sal)
from
emp
#再找出比最低工资高的员工姓名和工资
select ename,sal
from emp
where sal>800
#最后合并
select ename,sal
from emp
where sal>(select min(sal)from emp)
FROM的子查询
from后面的子查询,可以把查询出来的结果看成一张表,一定要改别名,不然会报错
#查询每个工作岗位的平均工资的薪资等级
#先查询每个工作岗位的平均工资
select job, avg(sal)
from emp
group by job
#克服心理障碍,把以上查询结果当作一张真实存在的表
select t.*,s.grade
from
(select job, avg(sal) as avgsal from emp group by job) as t
join
salgrade s
on t.avgsal between losal and hisal;
#这里临时表中一定要改别名,不然会报错
UNION合并查询结果集
union的效率高一些,对于表的连接来说,每连接一次新表,则满足笛卡尔积,匹配次数很多,但是union可以减少匹配次数,在减少匹配次数的情况下,还可以完成连个结果的拼接
UNION 操作符用于连接两个以上的 SELECT 语句的结果组合到一个结果集合中。多个 SELECT 语句会删除重复的数据。
union后面可以跟两个参数
- DISTINCT:默认是DISTINCT,去除重复记录
- ALL:返回所有结果集,将重复数据也进行返回
#查询两个部门的员工姓名
#普通写法
select ename,job
from emp
where job='MANAGER' or job ='SALESMAN'
#用union
select ename,job from emp where job='MANAGER'
union
select ename,job from emp where job='SALESMAN'
在使用union的时候要求两个结果集的列数相同,两个集的数据类型也要相同
LIMIT
limit是将结果集的一部分查询出来,一般是用在分页查询当中的
分页查询是为了用户的体验
limit startIndex,length
startIndex 是起始下标,length是长度
起始下标从0开始
#按照薪资降序,取出排名在前五名的员工
select ename,sal
from emp
order by sal desc
limit 5;
在Mysql当中limit是执行在order by后面的
通用分页公式:
每一页显示pageSize条数据
第pageNo页
limit (pageNo-1)*pageSize,pageSize
DQL语句的总结
select
...
from
...
where
...
group by
...
having
...
order by
...
limit
...
执行顺序:
- from——>where——>group by——>having——>select——>order by——>limit
DDL基本语句(对表结构的增删改)
表的创建
建表属于DDL语句,DDL语句包括:create,drop alter
create table 表名(
字段名1 数据类型,
字段名2 数据类型,
);
表名建议以t或者tbl开始,可读性强
字段名:见名知意
表名和字段名都属于标识符
表的快速创建
create table emp as select * from emp1
表的删除
drop table if exists t_student
如果表存在就删除该表
数据类型
数值类型
类型 | 大小 | 范围(有符号) | 范围(无符号) | 用途 |
tinyint | 1Bytes | (-128,127) | (0,255) | 小整数值 |
smallint | 2Bytes | (-32768,32767) | (0,65535) | 大整数值 |
mediumint | 3Bytes | (-8388608,8388607) | (0,16777215) | 大整数值 |
int或Integer | 4Bytes | (-2147483648,2147483647) | (0,4294967295) | 大整数值 |
BigInt | 8Bytes | (-9223372036854775808,9223372036854775807) | (0,18446744073709551615) | 极大整数值 |
Float | 4Bytes | (-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) | 0,(1.175 494 351 E-38,3.402 823 466 E+38) | 单精度,浮点数值 |
Double | 8Bytes | (-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 双精度,浮点数值 |
Decimal | 对DECIMAL(M,D) ,如果M>D,为M+2否则为D+2 | 依赖于M和D的值 | 依赖于M和D的值 | 小数值 |
日期和时间类型
类型 | 大小 | 范围 | 格式 | 用途 |
Date | 3Bytes | 1000-01-01/9999-12-31 | YYYY-MM-DD | 日期值 |
Time | 3Bytes | '-838:59:59'/'838:59:59 | HH:MM:SS | 时间值或持续时间 |
Year | 1Bytes | 1901/2155 | YYYY | 年份值 |
DateTime | 8Bytes | '1000-01-01 00:00:00' 到 '9999-12-31 23:59:59' | YYYY-MM-DD hh:mm:ss | 混合日期和时间值 |
TimeStamp | 4Bytes | 1970-01-01 00:00:01' UTC 到 '2038-01-19 03:14:07' UTC 结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07 | YYYY-MM-DD hh:mm ss | 混合日期和时间值,时间戳 |
字符串类型
类型 | 大小 | 用途 |
char | 0-255Bytes | 定长字符串 |
varchar | 0-65535Bytes | 变长字符串 |
tinyBlob | 0-255Bytes | 不超过255个字符的二进制字符串 |
tinyText | 0-255Bytes | 短文本字符串 |
Blob | 0-65535Bytes | 二进制形式的文本数据 |
Text | 0-65535Bytes | 长文本数据 |
mediumBlob | 0-16777215Bytes | 二进制形式的中等长度文本数据 |
mediumText | 0-16777215Bytes | 中等长度的文本数据 |
LongBlob | 0-4294967295Bytes | 二进制长度的极大文本数据 |
LongText | 0-4294967295Bytes | 极大文本数据 |
表的修改
当我们需要修改数据表名或者修改数据表字段时,就需要使用到 MySQL ALTER 命令。
MySQL 的 ALTER 命令用于修改数据库、表和索引等对象的结构。
ALTER 命令允许你添加、修改或删除数据库对象,并且可以用于更改表的列定义、添加约束、创建和删除索引等操作。
ALTER 命令非常强大,可以在数据库结构发生变化时进行灵活的修改和调整。
修改表结构
添加新列:
ALTER TABLE table_name
ADD column_name data_type;
修改列定义:
ALTER TABLE table_name
MODIFY column_name new_data_type;
修改列名称
ALTER TABLE table_name
CHANGE old_column_name new_column_name data_type
删除列:
ALTER TABLE table_name
DROP column_name;
添加约束
添加主键:
ALTER TABLE table_name
ADD PRIMARY KEY (column_name);
添加外键:
ALTER TABLE table_name
ADD FOREIGN KEY (column_name) REFERENCES referenced_table(ref_column_name);
添加唯一约束:
ALTER TABLE table_name
ADD CONSTRAINT constraint_name UNIQUE (column_name);
ADD CONSTRAINT是添加约束的关键字
创建索引
创建普通索引:
ALTER TABLE table_name
ADD INDEX index_name (column1 [ASC|DESC], column2 [ASC|DESC], ...);
创建唯一索引:
ALTER TABLE table_name
ADD UNIQUE INDEX index_name (column1 [ASC|DESC], column2 [ASC|DESC], ...);
删除索引:
ALTER TABLE table_name
DROP INDEX index_name;
重命名表:
ALTER TABLE old_table_name
RENAME TO new_table_name;
修改表存储引擎
ALTER TABLE table_name ENGINE = new_storage_engine;
注意:
但在使用 ALTER 命令时要格外小心,因为一些操作可能需要重建表或索引,这可能会影响数据库的性能和运行时间。
在进行重要的结构修改时,建议先备份数据,并在生产环境中谨慎操作。
删除,修改,添加表的字段
删除字段
删除了tableAlter表中的i字段
ALTER TABLE tableAlter_tbl DROP i;
如果数据库中只有一个字段不能用drop删除
添加字段
使用ALTER命令向tableAlter中添加了i字段并定义数据类型,i字段会自动添加到数据表字段的末尾
ALTER TABLE tableAlter _tbl ADD i INT;
指定添加字段位置
如果你需要指定新增字段的位置,可以使用MySQL提供的关键字 FIRST (设定位第一列), AFTER 字段名(设定位于某个字段之后)
ALTER TABLE testalter_tbl DROP i;
ALTER TABLE testalter_tbl ADD i INT FIRST;
ALTER TABLE testalter_tbl DROP i;
ALTER TABLE testalter_tbl ADD i INT AFTER c;
FIRST 和 AFTER 关键字可用于 ADD 与 MODIFY 子句,所以如果你想重置数据表字段的位置就需要先使用 DROP 删除字段然后使用 ADD 来添加字段并设置位置。
修改字段类型及名称
如果需要修改字段类型及名称, 你可以在ALTER命令中使用 MODIFY 或 CHANGE 子句
把字段c的类型从char(1)修改到char(10)
mysql> ALTER TABLE testalter_tbl MODIFY c CHAR(10);
使用 CHANGE 子句, 语法有很大的不同。 在 CHANGE 关键字之后,紧跟着的是你要修改的字段名,然后指定新字段名及类型
mysql> ALTER TABLE testalter_tbl CHANGE i j BIGINT;
mysql> ALTER TABLE testalter_tbl CHANGE j j INT;
ALTER TABLE 对NULL值和默认值的影响
当你修改字段时,你可以指定是否包含值或者是否设置默认值
mysql> ALTER TABLE testalter_tbl
-> MODIFY j BIGINT NOT NULL DEFAULT 100;
如果不设置默认值,Mysql会自动设置为NULL
修改字段的默认值:
mysql> ALTER TABLE testalter_tbl ALTER i SET DEFAULT 1000;
mysql> SHOW COLUMNS FROM testalter_tbl;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
| c | char(1) | YES | | NULL | |
| i | int(11) | YES | | 1000 | |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)
DML基本语句
insert——插入数据
insert into 表名(字段名,字段名2,字段名3...) values(值1,值2,值3)
#字段名和值要一一对应,即数量要对应,数据类型要对应
如果数据是字符型,必须使用单引号
insert插入日期
str_to_date:将字符串varchar类型转换成date日期类型
date_format:将date类型转换成具有一定格式的varchar类型
insert into t_student(id,name,birth)
values(1,'张三',str_to_date('01-10-1990','%d-%m-%Y'))
获取系统当前时间
insert into t_student(createTime)
values(now());
insert插入多条数据
insert into t_student(id,name,birth,createtime)
values(1,'zs','2005-04-20',now()),
(2,'ls','2005-04-20',now()),
(3,'ww','2005-04-20',now());
update——修改数据
update 表名 set 字段名1=值1,字段名2=值2..... where条件;
没有条件会导致所有数据都被更新
替换某个字段的某个字符
UPDATE table_name SET field=REPLACE(field, 'old-string', 'new-string')
[WHERE Clause]
UPDATE runoob_tbl SET runoob_title = REPLACE(runoob_title, 'C++', 'Python') where
runoob_id = 3;
delete——删除数据
delete from
表名
where 条件
没有条件,整张表中的数据都会被删除
delete删除表中数据,空间不会释放,这种删除缺点是:删除效率较低,优点是:支持回滚
快速删除表中的数据
truncate
这种删除效率高,表被一次截断,物理删除,这种删除不支持回滚,这种删除速度快
truncate table 表名
删除的只是表中的数据,表还在
约束
在创建表的时候,我们可以给字段加上一些约束,来保证这个表的数据的完整性,有效性
约束的作用:为了保证表中的数据有效
约束的种类:
- NOT NULL:指示某列不能存储NULL值
- UNIQUE:保证某列的每行必须有唯一值
- PRIMARY KEY:NOT NULL和UNIQUE的结合体,确保某列有唯一标识,有助于更容易快速地找到表中的特定记录
- FOREIGN KEY :保证一个表中的数据匹配另一个表中的值的参照完整性
- CHECK:保证列中的值符合指定的条件
- DEFAULT:规定没有给列赋值时的默认值
表级约束:需要给多个字段联合起来添加某一个约束的时候,需要使用表级约束
NOT NULL
NOT NULL 约束强制字段始终包含值。这意味着,如果不向字段添加值,就无法插入新记录或者更新记录
NOT NULL 约束强制列不接受 NULL 值。
drop table if exists t_vip;
create table t_vip(
id int,
name varchar(255) not null
);
insert into t_vip(id,name) value(1,'zhangsan')
insert into t_vip(id,name) value(2,'lisi')
UNIQUE
UNIQUE 约束唯一标识数据库表中的每条记录。
UNIQUE约束的字段不能重复,但可以为NULL
drop table if exists t_vip;
create table t_vip(
id int,
name varchar(255) unique
);
insert into t_vip(id,name) value(1,'zhangsan')
insert into t_vip(id,name) value(2,'lisi')
两个字段联合起来具有唯一性
drop table if exists t_vip;
create table t_vip(
id int,
name varchar(255),
unique(id,name)#这种约束方式叫做表级约束
#只有两个都重复的时候才会报错
);
PRIMARY KEY
PRIMARY KEY 约束唯一标识数据库表中的每条记录。
主键必须包含唯一的值。
主键列不能包含 NULL 值。
每个表都应该有一个主键,并且每个表只能有一个主键
drop table if exists t_vip(
id int primary key,
name varchar(255)
)
insert into t_vip values(1,'zhangsan')
insert into t_vip values(2,'lisi')
自增
drop table if exists t_vip;
create table t_vip(
id int primary key auto_increment, #auto_increment表示自增,从1开始自增
name varchar(255)
);
insert into t_vip(name) values('zhangsan')
insert into t_vip(name) values('zhangsan')
insert into t_vip(name) values('zhangsan')
insert into t_vip(name) values('zhangsan')
insert into t_vip(name) values('zhangsan')
FOREIGN KEY
一个表中的 FOREIGN KEY 指向另一个表中的 UNIQUE KEY(唯一约束的键)。
FOREIGN KEY 约束用于预防破坏表之间连接的行为。
FOREIGN KEY 约束也能防止非法数据插入外键列,因为它必须是它指向的那个表中的值之一。
使用FOREIGN的表叫做子表,被引用的叫做父表
如果不添加任何约束,如果子表中添加一个父表不存在的数据,则会报错
drop table if exists t_student;
drop table if exists t_class;
create table t_class(
classno int primary key,
classname varchar(255)
)
create tabel t_student(
number int primary key auto_increment,
name varchar(255),
cno int,
foreign key(cno) references t_class(classno)
)
子表中的外键引用父表中的某个字段,被引用的字段不一定是主键,但至少具有唯一性(unique)约束
外键值也可以为空
CHECK
CHECK 约束用于限制列中的值的范围。
如果对单个列定义 CHECK 约束,那么该列只允许特定的值。
如果对一个表定义 CHECK 约束,那么此约束会基于行中其他列的值在特定的列中对值进行限制。
CREATE TABLE Persons
(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
CHECK (P_Id>0)
)
//CHECK约束规定P_Id列必须大于0
DEFAULT
DEFAULT 约束用于向列中插入默认值。
如果没有规定其他的值,那么会将默认值添加到所有的新记录。
CREATE TABLE Persons
(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255) DEFAULT 'Sandnes'
)
存储引擎
存储引擎是MYSQL中的术语,在oracle中没有
存储引擎是一个表存储数据的方式
不同的存储引擎,存储数据的方式不同
CREATE TABLE IF NOT EXISTS `runoob_tbl`(
`runoob_id` INT UNSIGNED AUTO_INCREMENT,
`runoob_title` VARCHAR(100) NOT NULL,
`runoob_author` VARCHAR(40) NOT NULL,
`submission_date` DATE,
PRIMARY KEY ( `runoob_id` )
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
MYISAM引擎
myisam使用三个文件表示每个表:
- 格式文件:存储表结构的定义 .frm
- 数据文件:存储表行的内容 .MYD
- 索引文件:存储表上索引 .MYI :索引可以提高效率,减少扫描的范围
Myisam存储引擎特点:
- 可被转换为压缩,只读表来节省时间
- 对于一张表来说,只要是主键,或者加有unique约束的字段就会自动创建索引
- myisam不支持事务,安全性低
InnoDB存储引擎
这是mysql默认的存储引擎数据库
InnoDB支持事务,支持数据库崩溃后自动恢复机制
InnoDB存储引擎最重要的特点就是:非常安全,但效率较低
提供了一组用来记录事务性活动的日志文件
用commit(提交),savepoint,rollback(回滚)支持事务处理
MEMORY存储引擎
每个表以.frm格式的文件存储
使用MEMORY存储引擎的表,其数据存储在内存中,一断电就消失
MEMORY存储引擎优点:查询效率最高
MEMORY存储引擎缺点:不安全,关机之后数据消失
事务
MySQL 事务主要用于处理操作量大,复杂度高的数据
- 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。
- 事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。
- 事务用来管理 insert,update,delete 语句
- 一个事务其实就是多条DML同时成功,或者同时失败
- 在事务的执行过程中,每一条DML的操作都会记录到事务性活动的日志文件当中,
事务一般需要满足4个条件:
- 原子性:一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样。
- 一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
- 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交、读提交、可重复读和串行化。
- 持久化性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
在 MySQL 命令行的默认设置下,事务都是自动提交的,即执行 SQL 语句后就会马上执行 COMMIT 操作。因此要显式地开启一个事务务须使用命令 BEGIN 或 START TRANSACTION,或者执行命令 SET AUTOCOMMIT=0,用来禁止使用当前会话的自动提交。
事务控制语句
- BEGIN 或 START TRANSACTION 显式地开启一个事务;
- COMMIT 也可以使用 COMMIT WORK,不过二者是等价的。COMMIT 会提交事务,并使已对数据库进行的所有修改成为永久性的;
- ROLLBACK 也可以使用 ROLLBACK WORK,不过二者是等价的。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;
- SAVEPOINT identifier,SAVEPOINT 允许在事务中创建一个保存点,一个事务中可以有多个 SAVEPOINT;
- RELEASE SAVEPOINT identifier 删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常;
- ROLLBACK TO identifier 把事务回滚到标记点;
- SET TRANSACTION 用来设置事务的隔离级别。InnoDB 存储引擎提供事务的隔离级别有READ UNCOMMITTED(读未提交)、READ COMMITTED(读提交)、REPEATABLE READ(可重复度) 和 SERIALIZABLE(串行化)。
事务隔离性:
- 读未提交:read uncommitted(最低)
-
- 事务A读取到事务B未提交的数据
- 这种隔离级别存在”脏读“现象,但这种级别一般没人用
- 读已提交:read committed(oracle默认)
-
- 事务A只能读取到事务B提交到的数据
- 解决了脏读现象
- 不可重复读取数据,意思就是事务B在不断提交数据,但事务A每次独到的数据都不一样,不能读已经读过的数据
- 事务B的操作对事务A有影响
- 可重复读:repeatable read(mysql默认)
-
- 事务A开启之后,不管多久,事务A读取到的数据都是一致的,即使事务B将数据修改,并且提交,事务A读取到的数据还是没有发生改变
- 提交之后也读不到,永远读到的都是开启事务时的数据
- 事务B的操作对事务A没影响
- 序列化: serializable(最高)
-
- 效率最低
- 这种隔离级别表示事务排队,不可以并发
- 如果两个事务同时操作一个数据库,要等一个操作完,另一个才能进行操作
MYSQL 事务处理主要有两种方法:
1、用 BEGIN, ROLLBACK, COMMIT来实现
- BEGIN 开始一个事务
- ROLLBACK 事务回滚
- COMMIT 事务确认
2、直接用 SET 来改变 MySQL 的自动提交模式:
- SET AUTOCOMMIT=0 禁止自动提交
- SET AUTOCOMMIT=1 开启自动提交
索引
MySQL 索引是一种数据结构,用于加快数据库查询的速度和性能。
MySQL 索引的建立对于 MySQL 的高效运行是很重要的,索引可以大大提高 MySQL 的检索速度。
索引的分类:
- 单列索引:即一个索引只包含一个单列,一个表可以有多个单列索引
- 组合索引:一个索引包含多个列
实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录
索引虽然能够提高查询性能,但也需要注意以下几点:
- 索引需要占用额外的存储空间。
- 对表进行插入、更新和删除操作时,索引需要维护,可能会影响性能。
- 过多或不合理的索引可能会导致性能下降,因此需要谨慎选择和规划索引。
在mysql当中,索引是一个单独的对象,不同的存储引擎中以不同的形式存在,在MyISAM存储引擎当中,索引存储在MYI文件当中,在InnoDB存储引擎当中,索引存储在一个逻辑名称叫做tablespace当中,在MEMORY存储引擎,索引被存储在内存当中
在任何数据库当中主键上都会自动添加索引,在mysql当中,如果字段上有unique约束也会自动添加索引
索引在mysql当中以树的形式存在,需要按照左小右大的原则存放,采用中序遍历的方式遍历
普通索引
创建普通索引
CREATE INDEX index_name
ON table_name (column1 [ASC|DESC], column2 [ASC|DESC], ...);
CREATE INDEX: 用于创建普通索引的关键字。
index_name: 指定要创建的索引的名称。索引名称在表中必须是唯一的。
table_name: 指定要在哪个表上创建索引。
(column1, column2, ...): 指定要索引的表列名。你可以指定一个或多个列作为索引的组合。这些列的数据类型通常是数值、文本或日期。
ASC和DESC(可选): 用于指定索引的排序顺序。默认情况下,索引以升序(ASC)排序。
创建表的时候直接指定索引
CREATE TABLE students (
id INT PRIMARY KEY,
name VARCHAR(50),
age INT,
INDEX idx_age (age)
);
删除索引
DROP INDEX index_name ON table_name;
DROP INDEX: 用于删除索引的关键字。
index_name: 指定要删除的索引的名称。
ON table_name: 指定要在哪个表上删除索引
使用ALTER TABLE 删除索引
ALTER TABLE table_name
DROP INDEX index_name;
//table_name表示要删除的索引所在的表的名称
//index_name表示要删除的索引名称
唯一索引
创建唯一索引
CREATE UNIQUE INDEX index_name
ON table_name (column1 [ASC|DESC], column2 [ASC|DESC], ...);
//index_name表示索引的名称
//table_name表示创建索引到的哪个表的名称
//(column1, column2, ...)指定要的索引列
//ASC和DESC(可选): 用于指定索引的排序顺序。默认情况下,索引以升序(ASC)排序。
使用ALTER TABLE命令来创建唯一性索引
ALTER TABLE employees
ADD CONSTRAINT idx_email UNIQUE (email);
//ADD CONSTRAINT表示创建唯一性索引和约束的关键字
//idx_email 表示索引的名字
//UNIQUE(column1,column2...)表示唯一性索引包含的列名
创建表时直接指定
CREATE TABLE table_name (
column1 data_type,
column2 data_type,
...,
CONSTRAINT index_name UNIQUE (column1 [ASC|DESC], column2 [ASC|DESC], ...)
);
//CONSTRAINT: 用于添加约束的关键字。
//index_name: 指定要创建的唯一索引的名称。约束名称在表中必须是唯一的。
//UNIQUE (column1, column2, ...): 指定要索引的表列名。
索引失效
- 模糊查询的时候,索引会失效,因为以”%“开头,可以不以百分号开始,就可以用索引
- 使用or的时候会失效,如果使用or那么要求or两边的字段都要有索引,才会走索引,如果其中一边的一个没有索引,那么另一种索引也会实现
- 使用复合索引的时候,没有使用左侧的列查找,索引失效
视图
视图是由数据库中的一个表或多个表导出的虚拟表,其作用是方便用户对数据的操作。
视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据
数据库中只存放了视图的定义,而并没有存放视图中的数据,这些数据存放在原来的表中
使用视图查询数据时,数据库系统会从原来的表中取出对应的数据。因此,视图中的数据是依赖于原来的表中的数据的。一旦表中的数据发生改变,显示在视图中的数据也会发生改变。同样对视图的更新,会影响到原来表的数据。
创建视图
创建视图之前,先确定登录的数据库用户和密码是否有创建视图的权限
SELECT creat_view_priv,select_priv
from mysql.user
where user = 'root'
and
host = 'localhost'
查询结果中creat_view_priv的值为Y,表示当前用户拥有创建视图的权限
CREATE [OR REPLACE] [{FORCE|NOFORCE}] VIEW view_name
AS
SELECT查询
[WITH READ ONLY CONSTRAINT]
源代码在SQL的底层会进行补充
- OR REPLACE:如果视图已经存在,则替换旧视图。
- FORCE:即使基表不存在,也可以创建该视图,但是该视图不能正常使用,当基表创建成功后,视图才能正常使用。
- NOFORCE:如果基表不存在,无法创建视图,该项是默认选项。
- WITH READ ONLY:默认可以通过视图对基表执行增删改操作,但是有很多在基表上的限制(比如:基表中某列不能为空,但是该列没有出现在视图中,则不能通过视图执行insert操作),WITH READ ONLY说明视图是只读视图,不能通过该视图进行增删改操作。现实开发中,基本上不通过视图对表中的数据进行增删改操作。
create view 名称 as select * from
修改视图
ALTER VIEW VU_STUDENT AS SELECT * FROM STUDENT WHERE ID > 10;
删除视图
DROP VIEW IF EXISTS VU_STUDENT;
数据的导入
mysql命令导入
mysql -u用户名 -p密码 < 要导入的数据库数据(runoob.sql)
使用source命令导入
source 命令导入数据库需要先登录到数库终端:
mysql> create database abc; # 创建数据库
mysql> use abc; # 使用已创建的数据库
mysql> set names utf8; # 设置编码
mysql> source /home/abc/abc.sql # 导入备份数据库
使用LOAD DATA导入数据
MySQL 中提供了LOAD DATA INFILE语句来插入数据。 以下实例中将从当前目录中读取文件 dump.txt ,将该文件中的数据插入到当前数据库的 mytbl 表中。
mysql> LOAD DATA LOCAL INFILE 'dump.txt' INTO TABLE mytbl;
如果指定LOCAL关键词,则表明从客户主机上按路径读取文件。如果没有指定,则文件在服务器上按路径读取文件、
数据的导出
使用SELECT...INTO OUTFILE语句导出数据
SELECT a,b,a+b INTO OUTFILE '/tmp/result.text'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM test_table;
生成一个文件,各值用逗号隔开
导出SQL格式的数据
$ mysqldump -u root -p RUNOOB runoob_tbl > dump.txt
password ******
备份所有数据库
$ mysqldump -u root -p --all-databases > database_dump.txt
password ******
将数据表及数据库拷贝到其他主机
mysqldump 命令中指定数据库名及数据表。在源主机上执行以下命令,将数据备份至 dump.txt 文件中
$ mysqldump -u root -p database_name table_name > dump.txt
password *****
如果你需要将备份的数据库导入到MySQL服务器中,可以使用以下命令,使用以下命令你需要确认数据库已经创建
$ mysql -u root -p database_name > dump.txt
password *****
将指定主机的数据库拷贝到本地
如果你需要将远程服务器的数据拷贝到本地,你也可以在 mysqldump 命令中指定远程服务器的IP、端口及数据库名。
在源主机上执行以下命令,将数据备份到 dump.txt 文件中:
请确保两台服务器是相通的:
mysqldump -h other-host.com -P port -u root -p database_name > dump.txt
password ****