MySQL基础
注意:本文的图片截图自尚硅谷MySQL笔记。
一:基本概述:
什么是数据库:
数据库是一种用来存储和管理数据的系统。它是一个组织化的数据集合,可以通过计算机系统进行访问、管理和更新。数据库可以存储各种类型的数据,包括文本、数字、图像、音频等。数据库的设计和使用可以帮助用户有效地组织和检索数据,提高数据的安全性和完整性,以及实现数据的共享和协作。数据库在各种领域都有广泛的应用,包括企业管理、科学研究、教育、医疗保健等。常见的数据库系统包括MySQL、Oracle、SQL Server等。
什么是SQL:
SQL(Structured Query Language,结构化查询语言)是用于管理关系数据库系统的标准化语言。它用于定义、查询和操作数据库中的数据。SQL包括各种语句和命令,如SELECT、INSERT、UPDATE、DELETE等,用于执行各种操作,如检索数据、插入新数据、更新数据、删除数据等。SQL是数据库管理系统(如MySQL、Oracle、SQL Server等)的核心语言,通过SQL语句,用户可以对数据库进行各种操作和管理。
二:基本的SELECT语句:
2.1.SQL的分类:
SQL语言在功能上主要分为如下3大类:
DDL(Data Definition Languages、数据定义语言),这些语句定义了不同的数据库、表、视图、索引等数据库对象,还可以用来创建、删除、修改数据库和数据表的结构。主要的语句关键字包括 CREATE 、 DROP 、 ALTER 等。
DML(Data Manipulation Language、数据操作语言),用于添加、删除、更新和查询数据库记
录,并检查数据完整性。主要的语句关键字包括 INSERT 、 DELETE 、 UPDATE 、 SELECT 等。
SELECT是SQL语言的基础,最为重要。
DCL(Data Control Language、数据控制语言),用于定义数据库、表、字段、用户的访问权限和
安全级别。主要的语句关键字包括 GRANT 、 REVOKE 、 COMMIT 、 ROLLBACK 、 SAVEPOINT 等。
因为查询语句使用的非常的频繁,所以很多人把查询语句单拎出来一类:DQL(数据查询语言)。
还有单独将 COMMIT 、 ROLLBACK 取出来称为TCL (Transaction Control Language,事务控语言)。
2.2.SQL语言的规则与规范:
基本规则:
- SQL 可以写在一行或者多行。为了提高可读性,各子句分行写,必要时使用缩进
- 每条命令以 ; 或 \g 或 \G 结束
- 关键字不能被缩写也不能分行
- 关于标点符号
- 必须保证所有的()、单引号、双引号是成对结束的
- 必须使用英文状态下的半角输入方式
- 字符串型和日期时间类型的数据可以使用单引号(’ ')表示
- 列的别名,尽量使用双引号(" "),而且不建议省略as
SQL大小写规范 (建议遵守):
- MySQL 在 Windows 环境下是大小写不敏感的
- MySQL 在 Linux 环境下是大小写敏感的
- 数据库名、表名、表的别名、变量名是严格区分大小写的
- 关键字、函数名、列名(或字段名)、列的别名(字段的别名) 是忽略大小写的。
推荐采用统一的书写规范:
- 数据库名、表名、表别名、字段名、字段别名等都小写
- SQL 关键字、函数名、绑定变量等都大写
注释
可以使用如下格式的注释结构
单行注释:#注释文字(MySQL特有的方式)
单行注释:-- 注释文字(--后面必须包含一个空格。)
多行注释:/* 注释文字 */
2.3.数据的导入:
mysql> source d:\mysqldb.sql
2.4.基本SELECT语句:
4.1.SELECT…:
SELECT 1; #没有任何子句
SELECT 9/2; #没有任何子句
4.2 SELECT … FROM
语法:
SELECT 标识选择哪些列
FROM 标识从哪个表中选择
选择全部列:
SELECT *
FROM departments;
选择特定列:
SELECT department_id, location_id
FROM departments;
2.5.列的别名:
-
重命名一个列
-
便于计算
-
紧跟列名,也可以在列名和别名之间加入关键字AS,别名使用双引号,以便在别名中包含空格特殊的字符并区分大小写。
-
AS 可以省略。
-
SELECT last_name AS name, commission_pct comm FROM employees; SELECT last_name "Name", salary*12 "Annual Salary" FROM employees;
2.6.列的去重:
在SELECT语句中使用关键字DISTINCT去除重复行
SELECT DISTINCT department_id
FROM employees;
2.7.空值参与运算:
所有运算符或列值遇到null值,运算的结果都为null
这里你一定要注意,在 MySQL 里面, 空值不等于空字符串。一个空字符串的长度是 0,而一个空值长度是空。而且,在 MySQL 里面,空值是占用空间的。
SELECT employee_id,salary,commission_pct,
12 * salary * (1 + commission_pct) "annual_sal"
FROM employees;
2.8.着重号:
``可以允许我们使用的字段与数据库的保留字,关键字相同。
2.9.查询常数:
SELECT 查询还可以对常数进行查询。对的,就是在 SELECT 查询结果中增加一列固定的常数列。这列的取值是我们指定的,而不是从数据表中动态取出的。
比如说,我们想对 employees 数据表中的员工姓名进行查询,同时增加一列字段 corporation ,这个字段固定值为“尚硅谷”,可以这样写:
SELECT '尚硅谷' as corporation, last_name FROM employees;
2.10.显示表结构:
使用DESCRIBE 或 DESC 命令,表示表结构。
DESCRIBE employees;
或
DESC employees;
2.11.过滤数据:
SELECT 字段1,字段2
FROM 表名
WHERE 过滤条件
SELECT employee_id, last_name, job_id, department_id
FROM employees
WHERE department_id = 90 ;
注意,SQL在windows系统不分大小写,但是字符串除外,不过,在部分工具中,有的也不区分。WHERE必须在FROM后面。
注意:在SQL语句的执行顺序中,WHERE子句是在SELECT子句之前执行的。因此,在WHERE子句中无法直接使用SELECT子句中定义的列别名,因为此时这个别名还没有被解析和识别。
三:运算符:
3.1.比较与算数运算符:
补充:FROM DUAL
:伪表。
-
一个整数类型的值对整数进行加法和减法操作,结果是一个整数;
-
一个整数类型的值对浮点数进行加法和减法操作,结果是一个浮点数;
-
加法和减法的优先级相同,进行先加后减操作与进行先减后加操作的结果是一样的;
-
在Java中,+的左右两边如果有字符串,那么表示字符串的拼接。但是在MySQL中+只表示数值相加。如果遇到非数值类型,先尝试转成数值,如果转失败,就按0计算。(补充:MySQL中字符串拼接要使用字符串函数CONCAT()实现)。null参与,结果还是null。
-
SELECT 100 + '1';#等于101
-
在sql中,可以用div,mod代替/,%。
-
整数除法仍然会带有小数点。
-
分母为0,结果为null。
-
在sql中,= 表示相等。
-
等号运算符(=)判断等号两边的值、字符串或表达式是否相等,如果相等则返回1,不相等则返回0。
-
如果等号两边的值、字符串或表达式都为字符串,则MySQL会按照字符串进行比较,其比较的是每个字符串中字符的ANSI编码是否相等。
-
如果等号两边的值都是整数,则MySQL会按照整数来比较两个值的大小。
-
如果等号两边的值一个是整数,另一个是字符串,则MySQL会将字符串转化为数字进行比较。
-
如果等号两边的值、字符串或表达式中有一个为NULL,则比较结果为NULL。
比如,有些属性为null,如果我们要过滤出为null的值,什么都不会得到,因为要返回0才会显示,但是null不管与谁比较结果都是null。
但是,我们可以用安全等于来判断。
注意,不等于运算符不能比较null。结果都是null。
非符号运算符:
注意:_ 表示不确定的字符。我们可以与LIKE一起使用,查询第几个字符为什么的字段,注意,如果我们就是想要查询_,我们可以使用转义字符。我们也可以用ESCAPE指定一个字符表示转义字符。
3.2.逻辑运算符:
注意:
1.异或用XOR表示,逻辑异或(XOR)运算符是当给定的值中任意一个值为NULL时,则返回NULL;如果两个非NULL的值都是0或者都不等于0时,则返回0;如果一个值为0,另一个值不为0时,则返回1。其他的也可以用英文表示。
2.AND优先级高于OR。
四:排序与分页:
排序:
无处理时,默认是添加顺序。
4.1 排序规则:
使用 ORDER BY 子句排序
ASC(ascend): 升序
DESC(descend):降序
ORDER BY 子句在SELECT语句的结尾,而去必须在WHERE后面。
4.2.单列排序:
SELECT last_name, job_id, department_id, hire_date
FROM employees
ORDER BY hire_date ;
注意,默认是升序。
4.3.多列排序:
SELECT last_name, department_id, salary
FROM employees
ORDER BY department_id, salary DESC;
分页:
背景1:查询返回的记录太多了,查看起来很不方便,怎么样能够实现分页查询呢?
背景2:表里有 4 条数据,我们只想要显示第 2、3 条数据怎么办呢?
4.4.实现规则:
分页原理:
所谓分页显示,就是将数据库中的结果集,一段一段显示出来需要的条件。
MySQL中使用 LIMIT 实现分页
LIMIT [位置偏移量,] 行数
第一个“位置偏移量”参数指示MySQL从哪一行开始显示,是一个可选参数,如果不指定“位置偏移量”,将会从表中的第一条记录开始(第一条记录的位置偏移量是0,第二条记录的位置偏移量是
1,以此类推);第二个参数“行数”指示返回的记录条数。
--前10条记录:
SELECT * FROM 表名 LIMIT 0,10;
或者
SELECT * FROM 表名 LIMIT 10;
--第11至20条记录:
SELECT * FROM 表名 LIMIT 10,10;
--第21至30条记录:
SELECT * FROM 表名 LIMIT 20,10;
分页显式公式:(当前页数-1)*每页条数,每页条数:
SELECT * FROM table
LIMIT(PageNo - 1)*PageSize,PageSize;
注意:LIMIT 子句必须放在整个SELECT语句的最后!
使用 LIMIT 的好处:
约束返回结果的数量可以 减少数据表的网络传输量 ,也可以 提升查询效率 。如果我们知道返回结果只有1 条,就可以使用 LIMIT 1 ,告诉 SELECT 语句只需要返回一条记录即可。这样的好处就是 SELECT 不需要扫描完整的表,只需要检索到一条符合条件的记录即可返回。
拓展:
在不同的 DBMS 中使用的关键字可能不同。
五:多表查询:
笛卡尔积的错误会在下面条件下产生:
-
省略多个表的连接条件(或关联条件)
-
连接条件(或关联条件)无效
-
所有表中的所有行互相连接
为了避免笛卡尔积, 可以在 WHERE 加入有效的连接条件。
加入连接条件后,查询语法:
SELECT table1.column, table2.column
FROM table1, table2
WHERE table1.column1 = table2.column2; #连接条件
在 WHERE子句中写入连接条件。
正确写法:
#案例:查询员工的姓名及其部门名称
SELECT last_name, department_name
FROM employees, departments
WHERE employees.department_id = departments.department_id;
在表中有相同列时,在列名之前加上表名前缀。只有列名只存在于一个表中,才可以省略。但是,建议都指明所在的表。
注意,可以给表起别名在WHERE中运用,不与前面的知识冲突,前面是列不能使用,但是,一旦起了别名,后面就必须使用别名,
多表查询分类讲解:
分类1:等值连接 vs 非等值连接:
-
等值连接:等值连接是指在连接两个表时,使用相等条件将两个表中的列进行匹配。例如,将两个表中的员工ID列进行等值连接,以获取员工的相关信息。
-
SELECT employees.employee_id, employees.last_name, employees.department_id, departments.department_id, departments.location_id FROM employees, departments WHERE employees.department_id = departments.department_id;
-
非等值连接:非等值连接是指在连接两个表时,使用非相等条件将两个表中的列进行匹配。这种连接通常涉及到范围或不等式条件,而不是简单的相等条件。
-
SELECT e.last_name, e.salary, j.grade_level FROM employees e, job_grades j WHERE e.salary BETWEEN j.lowest_sal AND j.highest_sal;
分类2:自连接 vs 非自连接:
-
自连接:自连接是指在同一表内进行连接操作,通常是通过将表与自身进行连接来获取相关信息。例如,可以通过自连接来查找同一表中不同行之间的关联。
-
非自连接:非自连接是指在不同表之间进行连接操作,通常是通过将不同的表进行连接来获取相关信息。
分类3:内连接 vs 外连接:
-
内连接:内连接是连接两个表并返回两个表中共有的行的操作。内连接基于连接条件匹配的行,只返回符合条件的行,其他不符合条件的行将被排除。合并具有同一列的两个以上的表的行, 结果集中不包含一个表与另一个表不匹配的行。
-
外连接:两个表在连接过程中除了返回满足连接条件的行以外还返回左(或右)表中不满足条件的行 ,这种连接称为左(或右) 外连接。没有匹配的行时, 结果表中相应的列为空(NULL)。
比如,对于内连接,有的员工没有部门,为null,所以部门相匹配时不会显示它的信息。
左外连接:左外连接是指查询两个表时,会返回左表中所有的记录,以及右表中符合条件的记录。如果右表中没有符合条件的记录,则会返回NULL值。左外连接的语法通常是在FROM子句中使用LEFT JOIN关键字。
右外连接:右外连接与左外连接相反,它会返回右表中所有的记录,以及左表中符合条件的记录。如果左表中没有符合条件的记录,则会返回NULL值。右外连接的语法通常是在FROM子句中使用RIGHT JOIN关键字。
满外连接:满外连接是左外连接和右外连接的结合,会返回两个表中所有的记录,无论是否符合条件。如果某个表中没有符合条件的记录,则会返回NULL值。满外连接的语法通常是在FROM子句中使用FULL JOIN关键字。满外连接通常在一些特殊情况下使用,比如需要同时获取两个表中的所有记录。
SQL92语法:
上面的内连接就是SQL92的内连接,外连接要使用+。但是,在MySQL,不支持SQL92外连接的写法。
#左外连接
SELECT last_name,department_name
FROM employees ,departments
WHERE employees.department_id = departments.department_id(+);
#右外连接
SELECT last_name,department_name
FROM employees ,departments
WHERE employees.department_id(+) = departments.department_id;
而且在SQL92中,没有满外连接。
SQL99中,用JOIN ON实现多表查询:
内连接:
SELECT *
FROM table1
INNER JOIN table2
ON table1.column = table2.column;
可以省略INNER。
外连接:
左右外连接:
SELECT *
FROM table1
LEFT OUTER JOIN table2
ON table1.column = table2.column
LEFT JOIN table3
ON table2.column = table3.column;SELECT *
FROM table1
RIGHT JOIN table2
ON table1.column = table2.column
RIGHT JOIN table3
ON table2.column = table3.column;
OUTER可以省略。
满外连接:
注意,MySQL不支持FULL JOIN,但是可以用 LEFT JOIN UNION RIGHT join代替。
UNION与UNION ALL的使用:
UNION ALL的效率更高,虽然会有重复的元素,但是我们可以用上图的左上和右中图UNION ALL。
七张图的代码实现:
#中图:内连接 A∩B
SELECT employee_id,last_name,department_name
FROM employees e JOIN departments d
ON e.`department_id` = d.`department_id`;
#左上图:左外连接
SELECT employee_id,last_name,department_name
FROM employees e LEFT JOIN departments d
ON e.`department_id` = d.`department_id`;
#右上图:右外连接
SELECT employee_id,last_name,department_name
FROM employees e RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`;
#左中图:A - A∩B
SELECT employee_id,last_name,department_name
FROM employees e LEFT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE d.`department_id` IS NULL
#右中图:B-A∩B
SELECT employee_id,last_name,department_name
FROM employees e RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE e.`department_id` IS NULL
# 左下图:满外连接
# 左中图 + 右上图 A∪B
SELECT employee_id,last_name,department_name
FROM employees e LEFT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE d.`department_id` IS NULL
UNION ALL #没有去重操作,效率高
SELECT employee_id,last_name,department_name
FROM employees e RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`;
#右下图
#左中图 + 右中图 A ∪B- A∩B 或者 (A - A∩B) ∪ (B - A∩B)
SELECT employee_id,last_name,department_name
FROM employees e LEFT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE d.`department_id` IS NULL
UNION ALL
SELECT employee_id,last_name,department_name
FROM employees e RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE e.`department_id` IS NULL
SQL99新特性:
(1):自然连接:
SQL99 在 SQL92 的基础上提供了一些特殊语法,比如 NATURAL JOIN 用来表示自然连接。我们可以把自然连接理解为 SQL92 中的等值连接。它会帮你自动查询两张连接表中 所有相同的字段 ,然后进行 等值连接 。
SELECT employee_id,last_name,department_name
FROM employees e NATURAL JOIN departments d;
(2):using连接:
六:函数:
6.1.单行函数:
数值函数:
字符串函数:
时间与日期函数:
SELECT DATE_ADD(NOW(), INTERVAL 1 DAY) AS col1,DATE_ADD('2021-10-21 23:32:12',INTERVAL
1 SECOND) AS col2,
ADDDATE('2021-10-21 23:32:12',INTERVAL 1 SECOND) AS col3,
DATE_ADD('2021-10-21 23:32:12',INTERVAL '1_1' MINUTE_SECOND) AS col4,
DATE_ADD(NOW(), INTERVAL -1 YEAR) AS col5, #可以是负数
DATE_ADD(NOW(), INTERVAL '1_1' YEAR_MONTH) AS col6 #需要单引号
FROM DUAL;
SELECT DATE_FORMAT(NOW(),GET_FORMAT(DATE,'USA')),
FROM DUAL;
流程控制函数:
在实际运用中,还可以用这种方法给它们进行分类赋值。
加密与解密函数:
注意,部分函数在8.0版本中不可用。
MySQL信息函数:
其他函数:
6.2.聚合函数:
聚合函数介绍:
聚合函数作用于一组数据,并对一组数据返回一个值。
常见聚合函数类型:
AVG()
SUM()
MAX()
MIN()
COUNT()
聚合函数不能嵌套调用。比如不能出现类似“AVG(SUM(字段名称))”形式的调用。
GROUP BY:
可以使用GROUP BY子句将表中的数据分成若干组:
当然,还可以使用多列分组:
SELECT department_id dept_id, job_id, SUM(salary)
FROM employees
GROUP BY department_id, job_id ;
可以使用WITH ROLLUP:
SELECT department_id,AVG(salary)
FROM employees
WHERE department_id > 80
GROUP BY department_id WITH ROLLUP;
此时不能进行排序操作。
HAVING:
过滤分组:HAVING子句:
-
行已经被分组。
-
使用了聚合函数。
-
满足HAVING 子句中条件的分组将被显示。
-
HAVING 不能单独使用,必须要跟 GROUP BY 一起使用。
如果在WHERE中使用了聚合函数,那么就必须用HAVING替代WHERE,并且,WHERE必须使用在GROUP BY前面,但是HAVING必须写在后面。
但是不在WHERE中使用聚合函数,还是可以用WHERE的。比如:
可以看到,WHERE先于HAVING,所以效率更高。同样,SELECT的别名,不能在它前面的执行步骤中使用。
七:子查询:
子查询指一个查询语句嵌套在另一个查询语句内部的查询,这个特性从MySQL 4.1开始引入。
SQL 中子查询的使用大大增强了 SELECT 查询的能力,因为很多时候查询需要从结果集中获取数据,或者需要从同一个表中先计算得出一个数据结果,然后与这个数据结果(可能是某个标量,也可能是某个集合)进行比较。
举例:查询谁的工资高于Abel:
#方式一:
SELECT salary
FROM employees
WHERE last_name = 'Abel';
SELECT last_name,salary
FROM employees
WHERE salary > 11000;
#方式二:自连接
SELECT e2.last_name,e2.salary
FROM employees e1,employees e2
WHERE e1.last_name = 'Abel'
AND e1.`salary` < e2.`salary`
#方式三:子查询
SELECT last_name,salary
FROM employees
WHERE salary > (
SELECT salary
FROM employees
WHERE last_name = 'Abel'
);
-
子查询要包含在括号内
-
将子查询放在比较条件的右侧
-
单行操作符对应单行子查询,多行操作符对应多行子查询
分类方式1:
我们按内查询的结果返回一条还是多条记录,将子查询分为单行子查询 、 多行子查询 。
分类方式2:
我们按内查询是否被执行多次,将子查询划分为 相关(或关联)子查询 和 不相关(或非关联)子查询 。子查询从数据表中查询了数据结果,如果这个数据结果只执行一次,然后这个数据结果作为主查询的条件进行执行,那么这样的子查询叫做不相关子查询。
同样,如果子查询需要执行多次,即采用循环的方式,先从外部查询开始,每次都传入子查询进行查
询,然后再将结果反馈给外部,这种嵌套的执行方式就称为相关子查询。
单行子查询:
SELECT last_name, job_id, salary
FROM employees
WHERE job_id =
(SELECT job_id
FROM employees
WHERE employee_id = 141)
AND salary >
(SELECT salary
FROM employees
WHERE employee_id = 143);
多行子查询:
题目:返回其它job_id中比job_id为‘IT_PROG’部门所有工资都低的员工的员工号、姓名、job_id以及salary:
/>
例题:查询平均工资最低的部门id:
方法一:
SELECT department_id
FROM employees
GROUP BY department_id
HAVING AVG(salary) <= ALL (SELECT AVG(salary) avg_salFROM employeesGROUP BY department_id
)
方法二:
SELECT department_id
FROM employees
GROUP BY department_id
HAVING AVG(salary) = (SELECT MIN(avg_sal)FROM (SELECT AVG(salary) avg_salFROM employeesGROUP BY department_id) dept_avg_sal
)
注意,在MySQL中,组函数是无法嵌套的,但我们可以把返回的一组值作为新的表,然后对它进行查询。
还可以把平均工资排序并且用LIMIT修饰得到一条信息,并且进行后序操作。
注意,在多行子查询时,要更加注意空值null的问题。
相关子查询:
例题:查询员工中工资大于本部门平均工资的员工的last_name,salary和其department_id:
题目:查询员工的id,salary,按照department_name 排序:
SELECT employee_id,salary
FROM employees e
ORDER BY (
SELECT department_name
FROM departments d
WHERE e.`department_id` = d.`department_id`
);
题目:若employees表中employee_id与job_history表中employee_id相同的数目不小于2,输出这些相同id的员工的employee_id,last_name和其job_id:
SELECT e.employee_id, last_name,e.job_id
FROM employees e
WHERE 2 <= (SELECT COUNT(*)
FROM job_history
WHERE employee_id = e.employee_id);
在SELECT中使用:
EXISTS与NOT EXISTS:
题目:查询公司管理者的employee_id,last_name,job_id,department_id信息:
方式一:
SELECT employee_id, last_name, job_id, department_id
FROM employees e1
WHERE EXISTS ( SELECT *FROM employees e2WHERE e2.manager_id = e1.employee_id);
方式二:自连接:
SELECT DISTINCT e1.employee_id, e1.last_name, e1.job_id, e1.department_id
FROM employees e1 JOIN employees e2
WHERE e1.employee_id = e2.manager_id;
方式三:
SELECT employee_id,last_name,job_id,department_id
FROM employees
WHERE employee_id IN (SELECT DISTINCT manager_idFROM employees
);
题目:查询departments表中,不存在于employees表中的部门的department_id和department_name:
SELECT department_id, department_name
FROM departments d
WHERE NOT EXISTS (SELECT 'X'FROM employees eWHERE e.department_id = d.department_id);
八:数据库的编辑:
8.1.创建数据库:
注意,方式三也可以指定字符集。
8.2.管理数据库:
8.3.修改与删除数据库:
8.4.表的创建:
方法一:
-- 创建表
CREATE TABLE emp (
-- int类型
emp_id INT,
-- 最多保存20个中英文字符
emp_name VARCHAR(20),
-- 总位数不超过15位
salary DOUBLE,
-- 日期类型
birthday DATE
);
方法二:
注意,相当于复制的第一个表的元素,而WHERE 1=2,可以让它SELECT不到第一个表的元素,这样就相当于没有赋值。
8.5.显示与修改表结构:
5.1.显示:
5.2.修改:
(1):追加:
ALTER TABLE 表名 ADD 【COLUMN】 字段名 字段类型 【FIRST|AFTER 字段名】;
ALTER TABLE dept80
ADD job_id varchar(15);
ALTER TABLE dept80
ADD job_year varchar(15) AFTER job_id;
(2):修改:
注意,default是默认值。
(3):重命名:
(4):删除:
8.6.表的重命名,删除与清空:
(1):重命名:
(2):删除表:
(3):清空:
在看看这些缩写的含义:
-
DDL(Data Definition Language):用于定义数据库结构、表、索引等对象的语言,包括CREATE、ALTER、DROP等命令。
-
DML(Data Manipulation Language):用于对数据库中的数据进行操作的语言,包括SELECT、INSERT、UPDATE、DELETE等命令。
-
DQL(Data Query Language):用于查询数据库中的数据的语言,主要包括SELECT命令。
-
DCL(Data Control Language):用于控制数据库用户的访问权限和安全性的语言,包括GRANT、REVOKE等命令。
-
DTL(Data Transaction Language):用于管理数据库事务的语言,包括COMMIT、ROLLBACK等命令。
注意:DML是可以回滚的,而且会回滚到最近一次的COMMIT操作,但是要SET autocommit = FALSE
,不过这句话对DDL是没有用的,因为DDL比如TRUNCATE操作后会默认进行一次提交,所以,就算回滚,也是回到删除之后了,这就是它与DELETE的区别。
8.7.MySQL8新特性—DDL的原子化:
在MySQL中,DDL(数据定义语言)的原子化是指在执行DDL语句时,要么全部执行成功,要么全部执行失败,不会出现部分执行成功部分执行失败的情况。原子化保证了数据库结构的一致性和完整性,避免了数据结构的不一致性和混乱。
例如,当执行一个创建表的DDL语句时,如果其中某个字段的数据类型设置错误导致创建表失败,整个DDL语句都会失败,数据库的结构不会发生变化。这种原子化的特性可以保证数据库的稳定性和可靠性,确保数据的完整性和一致性。
九:DML——增删改:
9.1.添加:
(1):values添加:
情况1:为表的所有字段按默认顺序插入数据:
INSERT INTO 表名
VALUES (value1,value2,....);
/*举例*/
INSERT INTO departments
VALUES (70, 'Pub', 100, 1700);
值列表中需要为表的每一个字段指定值,并且值的顺序必须和数据表中字段定义时的顺序相同。
情况2:为表的指定字段插入数据:
NSERT INTO 表名(column1 [, column2, ..., columnn])
VALUES (value1 [,value2, ..., valuen]);
/*举例*/
INSERT INTO departments(department_id, department_name)
VALUES (80, 'IT');
为表的指定字段插入数据,就是在INSERT语句中只向部分字段中插入值,而其他字段的值为表定义时的默认值。
在INSERT子句中随意列出列名,但是一旦列出,VALUES中要插入的value1,.valuen需要与column1,…columnn列一一对应。如果类型不同,将无法插入,并且MySQL会产生错误。
情况3:同时插入多条记录
INSERT语句可以同时向数据表中插入多条记录,插入时指定多个值列表,每个值列表之间用逗号分隔开,基本语法格式如下:
INSERT INTO table_name
VALUES
(value1 [,value2, ..., valuen]),
(value1 [,value2, ..., valuen]),
......
(value1 [,value2, ..., valuen]);/*举例*/INSERT INTO emp(emp_id,emp_name)VALUES (1001,'shkstart'),(1002,'atguigu'),(1003,'Tom');
(2):将查询结果插入到表中:
INSERT INTO 目标表名
(tar_column1 [, tar_column2, ..., tar_columnn])
SELECT
(src_column1 [, src_column2, ..., src_columnn])
FROM 源表名
[WHERE condition]
/*举例*/
INSERT INTO sales_reps(id, name, salary, commission_pct)
SELECT employee_id, last_name, salary, commission_pct
FROM employees
WHERE job_id LIKE '%REP%';
要注意一一对应的关系。而且不能超过原来的表规定的长度。
9.2.修改:
使用 UPDATE 语句更新数据。语法如下:
UPDATE table_name
SET column1=value1, column2=value2, ... , column=valuen
[WHERE condition]
可以更改一条或者多条数据,如果要回滚,记得设置为FALSE。
举例:
UPDATE employees
SET department_id = 70
WHERE employee_id = 113;
9.3.删除:
DELETE FROM table_name [WHERE <condition>];
举例:
DELETE FROM departments
WHERE department_name = 'Finance';
9.4.计算列:
什么叫计算列呢?简单来说就是某一列的值是通过别的列计算得来的。例如,a列值为1、b列值为2,c列不需要手动插入,定义a+b的结果为c的值,那么c就是计算列,是通过别的列计算得来的。
在MySQL 8.0中,CREATE TABLE 和 ALTER TABLE 中都支持增加计算列。下面以CREATE TABLE为例进行讲解。
举例:定义数据表tb1,然后定义字段id、字段a、字段b和字段c,其中字段c为计算列,用于计算a+b的值。 首先创建测试表tb1,语句如下:
CREATE TABLE tb1(
id INT,
a INT,
b INT,
c INT GENERATED ALWAYS AS (a + b) VIRTUAL
);
十:MySQL数据类型:
1.整数类型:
可选属性:
2.浮点类型:
-
MySQL允许使用非标准语法 (其他数据库未必支持,因此如果涉及到数据迁移,则最好不要用): FLOAT(M,D) 或 DOUBLE(M,D) 。这里,M称为 精度 ,D称为 标度 。(M,D)中 M=整数位+小数位,D=小数位。 D<=M<=255,0<=D<=30。
例如,定义为FLOAT(5,2)的一个列可以显示为-999.99-999.99。如果超过这个范围会报错。
-
FLOAT和DOUBLE类型在不指定(M,D)时,默认会按照实际的精度(由实际的硬件和操作系统决定)来显示。
-
说明:浮点类型,也可以加 UNSIGNED ,但是不会改变数据范围,例如:FLOAT(3,2) UNSIGNED仍然只能表示0-9.99的范围。
不管是否显式设置了精度(M,D),这里MySQL的处理方案如下:
-
如果存储时,整数部分超出了范围,MySQL就会报错,不允许存这样的值。
如果存储时,小数点部分若超出范围,就分以下情况:
-
若四舍五入后,整数部分没有超出范围,则只警告,但能成功操作并四舍五入删除多余的小数位后保存。例如在FLOAT(5,2)列内插入999.009,近似结果是999.01。
-
若四舍五入后,整数部分超出范围,则MySQL报错,并拒绝处理。如FLOAT(5,2)列内插入999.995和-999.995都会报错。
-
从MySQL 8.0.17开始,FLOAT(M,D) 和DOUBLE(M,D)用法在官方文档中已经明确不推荐使用,将来可能被移除。另外,关于浮点型FLOAT和DOUBLE的UNSIGNED也不推荐使用了,将来也可能被移除。
在编程中,如果用到浮点数,要特别注意误差问题,因为浮点数是不准确的,所以我们要避免使用“=”来判断两个数是否相等。同时,在一些对精确度要求较高的项目中,千万不要使用浮点数,不然会导致结果错误,甚至是造成不可挽回的损失。那么,MySQL 有没有精准的数据类型呢?当然有,这就是定点数
类型: DECIMAL 。
3.定点数类型:
注意,浮点数的表述范围大,但是精度不够。定点数刚好与其相反。
4.位类型:
CREATE TABLE test_bit1(
f1 BIT,
f2 BIT(5),
f3 BIT(64)
);
INSERT INTO test_bit1(f1)
VALUES(1);
#Data too long for column 'f1' at row 1
INSERT INTO test_bit1(f1)
VALUES(2);
INSERT INTO test_bit1(f2)
VALUES(23);
使用SELECT命令查询位字段时,可以用 BIN() 或 HEX() 函数进行读取。
bin函数用于将整数转换为二进制字符串表示,而hex函数用于将整数转换为十六进制字符串表示。这两个函数都是用来将整数转换为不同进制的字符串表示形式。当然,我们可以用(字段名)+ 0
,来输出十进制的数。
5.日期与时间:
-
YEAR 类型通常用来表示年
-
DATE 类型通常用来表示年、月、日
-
TIME 类型通常用来表示时、分、秒
-
DATETIME 类型通常用来表示年、月、日、时、分、秒
-
TIMESTAMP 类型通常用来表示带时区的年、月、日、时、分、秒
(1):YEAR:
在MySQL中,YEAR有以下几种存储格式:
-
以4位字符串或数字格式表示YEAR类型,其格式为YYYY,最小值为1901,最大值为2155。
-
以2位字符串格式表示YEAR类型,最小值为00,最大值为99。
-
当取值为01到69时,表示2001到2069;
-
当取值为70到99时,表示1970到1999;
-
当取值整数的0或00添加的话,那么是0000年;
-
当取值是日期/字符串的’0’添加的话,是2000年。
-
从MySQL5.5.27开始,2位格式的YEAR已经不推荐使用。YEAR默认格式就是“YYYY”,没必要写成YEAR(4),从MySQL 8.0.19开始,不推荐使用指定显示宽度的YEAR(4)数据类型。
CREATE TABLE test_year(
f1 YEAR,
f2 YEAR(4)
);
NSERT INTO test_year
VALUES('2020','2021');
(2):DATE:
DATE类型表示日期,没有时间部分,格式为 YYYY-MM-DD ,其中,YYYY表示年份,MM表示月份,DD表示日期。需要 3个字节 的存储空间。在向DATE类型的字段插入数据时,同样需要满足一定的格式条件。
-
以 YYYY-MM-DD 格式或者 YYYYMMDD 格式表示的字符串日期,其最小取值为1000-01-01,最大取值为9999-12-03。YYYYMMDD格式会被转化为YYYY-MM-DD格式。
-
以 YY-MM-DD 格式或者 YYMMDD 格式表示的字符串日期,此格式中,年份为两位数值或字符串满足YEAR类型的格式条件为:当年份取值为00到69时,会被转化为2000到2069;当年份取值为70到99时,会被转化为1970到1999。
-
使用 CURRENT_DATE() 或者 NOW() 函数,会插入当前系统的日期。
CREATE TABLE test_date1(
f1 DATE
);
Query OK, 0 rows affected (0.13 sec)
INSERT INTO test_date1
VALUES ('2020-10-01'), ('20201001'),(20201001);
INSERT INTO test_date1
VALUES ('00-01-01'), ('000101'), ('69-10-01'), ('691001'), ('70-01-01'), ('700101'),('99-01-01'), ('990101');
INSERT INTO test_date1
VALUES (000301), (690301), (700301), (990301);
INSERT INTO test_date1
VALUES (CURRENT_DATE()), (NOW());
SELECT *
FROM test_date1;
(3):TIME:
INSERT INTO test_time1
VALUES('2 12:30:29'), ('12:35:29'), ('12:40'), ('2 12:40'),('1 05'), ('45');
INSERT INTO test_time1
VALUES ('123520'), (124011),(1210);
INSERT INTO test_time1
VALUES (NOW()), (CURRENT_TIME());
(4):DATETIME:
INSERT INTO test_datetime1
VALUES ('2021-01-01 06:50:30'), ('20210101065030');INSERT INTO test_datetime1
VALUES ('99-01-01 00:00:00'), ('990101000000'), ('20-01-01 00:00:00'),
('200101000000');INSERT INTO test_datetime1
VALUES (20200101000000), (200101000000), (19990101000000), (990101000000);INSERT INTO test_datetime1
VALUES (CURRENT_TIMESTAMP()), (NOW());
(5)TIMESTAMP:
INSERT INTO test_timestamp1
VALUES ('1999-01-01 03:04:50'), ('19990101030405'), ('99-01-01 03:04:05'),
('990101030405');INSERT INTO test_timestamp1
VALUES ('2020@01@01@00@00@00'), ('20@01@01@00@00@00');INSERT INTO test_timestamp1
VALUES (CURRENT_TIMESTAMP()), (NOW());#Incorrect datetime value
INSERT INTO test_timestamp1
VALUES ('2038-01-20 03:14:07');
6.文本字符串类型:
注意,char不计算空格,即使是(ab ),它计算的长度是2。
注意,VARCHAR会保留空格。在不同的版本,有不同的指向,有的是字符,有的是byte。
7.TEXT:
TEXT文本类型,可以存比较大的文本段,搜索速度稍慢,因此如果不是特别大的内容,建议使用CHAR,VARCHAR来代替。还有TEXT类型不用加默认值,加了也没用。而且text和blob类型的数据删除后容易导致“空洞”,使得文件碎片比较多,所以频繁使用的表不建议包含TEXT类型字段,建议单独分出去,单独用一个表。
8.ENUM类型:
CREATE TABLE test_enum(
season ENUM('春','夏','秋','冬','unknow')
);
INSERT INTO test_enum
VALUES('春'),('秋');
# 忽略大小写
INSERT INTO test_enum
VALUES('UNKNOW');
# 允许按照角标的方式获取指定索引位置的枚举值
INSERT INTO test_enum
VALUES('1'),(3);
# Data truncated for column 'season' at row 1
INSERT INTO test_enum
VALUES('ab');
# 当ENUM类型的字段没有声明为NOT NULL时,插入NULL也是有效的
INSERT INTO test_enum
VALUES(NULL);
9.SET类型:
CREATE TABLE test_set(
s SET ('A', 'B', 'C')
);
INSERT INTO test_set (s) VALUES ('A'), ('A,B');
#插入重复的SET类型成员时,MySQL会自动删除重复的成员
INSERT INTO test_set (s) VALUES ('A,B,C,A');
#向SET类型的字段插入SET成员中不存在的值时,MySQL会抛出错误。
INSERT INTO test_set (s) VALUES ('A,B,C,D');
SELECT *
FROM test_set;
10.二进制字符串类型:
CREATE TABLE test_binary1(
f1 BINARY,
f2 BINARY(3),
# f3 VARBINARY,
f4 VARBINARY(10)
);
INSERT INTO test_binary1(f1,f2)
VALUES('a','a');
INSERT INTO test_binary1(f1,f2)
VALUES('尚','尚');#失败
注意,这里是byte。
11.JSON类型:
CREATE TABLE test_json(
js json
);
插入数据与查询:
INSERT INTO test_json (js)
VALUES ('{"name":"songhk", "age":18, "address":{"province":"beijing",
"city":"beijing"}}');
mysql> SELECT *
-> FROM test_json;
十一:约束:
什么是约束:
约束是表级的强制规定。
可以在创建表时规定约束(通过 CREATE TABLE 语句),或者在表创建之后通过 ALTER TABLE 语句规定约束。
查看约束:
#information_schema数据库名(系统库)
#table_constraints表名称(专门存储各个表的约束)
SELECT * FROM information_schema.table_constraints
WHERE table_name = '表名称';
(1):非空约束:
-
默认,所有的类型的值都可以是NULL,包括INT、FLOAT等数据类型
-
非空约束只能出现在表对象的列上,只能某个列单独限定非空,不能组合非空
-
一个表可以有很多列都分别限定了非空
-
空字符串’'不等于NULL,0也不等于NULL
添加非空约束:
CREATE TABLE 表名称(
字段名 数据类型,
字段名 数据类型 NOT NULL,
字段名 数据类型 NOT NULL
);
这是建表前的约束。
alter table 表名称 modify 字段名 数据类型 not null;
ALTER TABLE emp
MODIFY sex VARCHAR(30) NOT NULL;
这是建表后的约束。
删除非空约束:
alter table 表名称 modify 字段名 数据类型 NULL;#去掉not null,相当于修改某个非注解字段,该字段允许为空
或
alter table 表名称 modify 字段名 数据类型;#去掉not null,相当于修改某个非注解字段,该字段允许为空
(2)唯一性约束:
- 同一个表可以有多个唯一约束。
- 唯一约束可以是某一个列的值唯一,也可以多个列组合的值唯一。
- 唯一性约束允许列值为空。
- 在创建唯一约束的时候,如果不给唯一约束命名,就默认和列名相同。
- MySQL会给唯一约束的列上默认创建一个唯一索引。
建表时:
create table 表名称(字段名 数据类型,字段名 数据类型 unique,字段名 数据类型 unique key,字段名 数据类型
);/*列级约束*/
create table 表名称(字段名 数据类型,字段名 数据类型,字段名 数据类型,[constraint 约束名] unique key(字段名)
);/*表级约束*/
建表后:
#字段列表中如果是一个字段,表示该列的值唯一。如果是两个或更多个字段,那么复合唯一,即多个字段的组合是唯一的
#方式1:
alter table 表名称 add unique key(字段列表);
#方式2:
alter table 表名称 modify 字段名 字段类型 unique;
复合唯一约束:
create table 表名称(
字段名 数据类型,
字段名 数据类型,
字段名 数据类型,
unique key(字段列表) #字段列表中写的是多个字段名,多个字段名用逗号分隔,表示那么是复合唯一,即多
个字段的组合是唯一的
);
删除唯一约束:
(3):主键约束:
主键约束相当于唯一约束+非空约束的组合,主键约束列不允许重复,也不允许出现空值。
-
一个表最多只能有一个主键约束,建立主键约束可以在列级别创建,也可以在表级别上创建。
-
主键约束对应着表中的一列或者多列(复合主键)
-
如果是多列组合的复合主键约束,那么这些列都不允许为空值,并且组合的值不允许重复。
-
MySQL的主键名总是PRIMARY,就算自己命名了主键约束名也没用。
-
当创建主键约束时,系统默认会在所在的列或列组合上建立对应的主键索引(能够根据主键查询的,就根据主键查询,效率更高)。如果删除主键约束了,主键约束对应的索引就自动删除了。
-
需要注意的一点是,不要修改主键字段的值。因为主键是数据记录的唯一标识,如果修改了主键的值,就有可能会破坏数据的完整性。
建表时添加:
create table 表名称(
字段名 数据类型 primary key, #列级模式
字段名 数据类型,
字段名 数据类型
);
create table 表名称(
字段名 数据类型,
字段名 数据类型,
字段名 数据类型,
[constraint 约束名] primary key(字段名) #表级模式
);
MySQL的主键名总是PRIMARY,就算自己命名了主键约束名也没用。
建表后添加:
ALTER TABLE 表名称 ADD PRIMARY KEY(字段列表); #字段列表可以是一个字段,也可以是多个字段,如果是多个字段的话,是复合主键
删除主键约束:
alter table 表名称 drop primary key;
注意,一个表只能有一个主键约束,而且在实际开发中,我们根本不会删除主键约束。
(4)AUTO_INCREMENT:
- 一个表最多只能有一个自增长列
- 当需要产生唯一标识符或顺序值时,可设置自增长
- 自增长列约束的列必须是键列(主键列,唯一键列)
- 自增约束的列的数据类型必须是整数类型
- 如果自增列指定了 0 和 null,会在当前最大值的基础上自增;如果自增列手动指定了具体值,直接赋值为具体值。
自增的持久化:
在MySQL 8.0之前,自增主键AUTO_INCREMENT的值如果大于max(primary key)+1,在MySQL重启后,会重置AUTO_INCREMENT=max(primary key)+1,这种现象在某些情况下会导致业务主键冲突或者其他难以发现的问题。
(5):外键约束:
限定某个表的某个字段的引用完整性。
比如:员工表的员工所在部门的选择,必须在部门表能找到对应的部分。
建表时添加约束:
create table 主表名称(
字段1 数据类型 primary key,
字段2 数据类型
);
create table 从表名称(
字段1 数据类型 primary key,
字段2 数据类型,
[CONSTRAINT <外键约束名称>] FOREIGN KEY(从表的某个字段) references 主表名(被参考字段)
);
#(从表的某个字段)的数据类型必须与主表名(被参考字段)的数据类型一致,逻辑意义也一样
#(从表的某个字段)的字段名可以与主表名(被参考字段)的字段名一样,也可以不一样
-- FOREIGN KEY: 在表级指定子表中的列
-- REFERENCES: 标示在父表中的列
举例:
create table dept( #主表did int primary key, #部门编号dname varchar(50) #部门名称
);
create table emp(#从表eid int primary key, #员工编号ename varchar(5), #员工姓名deptid int, #员工所在的部门foreign key (deptid) references dept(did) #在从表中指定外键约束
#emp表的deptid和和dept表的did的数据类型一致,意义都是表示部门的编号
);
说明:
(1)主表dept必须先创建成功,然后才能创建emp表,指定外键成功。
(2)删除表时,先删除从表emp,再删除主表dept
建表后:
ALTER TABLE 从表名 ADD [CONSTRAINT 约束名] FOREIGN KEY (从表的字段) REFERENCES 主表名(被引用字段) [on update xx][on delete xx];ALTER TABLE emp1
ADD [CONSTRAINT emp_dept_id_fk] FOREIGN KEY(dept_id) REFERENCES dept(dept_id);
举例:
create table dept(did int primary key, #部门编号dname varchar(50) #部门名称
);
create table emp(eid int primary key, #员工编号ename varchar(5), #员工姓名deptid int #员工所在的部门
);
#这两个表创建时,没有指定外键的话,那么创建顺序是随意
alter table emp add foreign key (deptid) references dept(did);
举例:
create table dept(
did int primary key, #部门编号
dname varchar(50) #部门名称
);
create table emp(
eid int primary key, #员工编号
ename varchar(5), #员工姓名
deptid int, #员工所在的部门
foreign key (deptid) references dept(did) on update cascade on delete set null
#把修改操作设置为级联修改等级,把删除操作设置为set null等级
);
注意,在实际运用中,一般不使用外键。
(6):检查约束与默认值约束:
1.CHECK约束:
检查某个字段的值是否符号xx要求,一般指的是值的范围。
create table employee(
eid int primary key,
ename varchar(5),
gender char check ('男' or '女')
);
2.DEFAULT约束:
给某个字段/某列指定默认值,一旦设置默认值,在插入数据时,如果此字段没有显式赋值,则赋值默认值。
建表时:
create table 表名称(字段名 数据类型 primary key,字段名 数据类型 unique key not null,字段名 数据类型 unique key,字段名 数据类型 not null default 默认值,
);
create table 表名称(字段名 数据类型 default 默认值 ,字段名 数据类型 not null default 默认值,字段名 数据类型 not null default 默认值,primary key(字段名),unique key(字段名)
);
说明:默认值约束一般不在唯一键和主键列上加
举例:
create table employee(
eid int primary key,
ename varchar(20) not null,
gender char default '男',
tel char(11) not null default '' #默认是空字符串
);
建表后:
alter table 表名称 modify 字段名 数据类型 default 默认值;
#如果这个字段原来有非空约束,你还保留非空约束,那么在加默认值约束时,还得保留非空约束,否则非空束就被删除了
#同理,在给某个字段加非空约束也一样,如果这个字段原来有默认值约束,你想保留,也要在modify语句中保留默认值约束,否则就删除了
alter table 表名称 modify 字段名 数据类型 default 默认值 not null;
删除约束:
alter table 表名称 modify 字段名 数据类型 ;#删除默认值约束,也不保留非空约束
alter table 表名称 modify 字段名 数据类型 not null; #删除默认值约束,保留非空约束
十二:视图:
视图一方面可以帮我们使用表的一部分而不是所有的表,另一方面也可以针对不同的用户制定不同的查询视图。比如,针对一个公司的销售人员,我们只想给他看部分数据,而某些特殊的数据,比如采购的价格,则不会提供给他。再比如,人员薪酬是个敏感的字段,那么只给某个级别以上的人员开放,其他人的查询视图中则不提供这个字段。
-
视图的创建和删除只影响视图本身,不影响对应的基表。但是当对视图中的数据进行增加、删除和修改操作时,数据表中的数据会相应地发生变化,反之亦然。
-
向视图提供数据内容的语句为 SELECT 语句, 可以将视图理解为存储起来的 SELECT 语句
-
在数据库中,视图不会保存数据,数据真正保存在数据表中。当对视图中的数据进行增加、删除和修改操作时,数据表中的数据会相应地发生变化;反之亦然。
-
视图,是向用户提供基表数据的另一种表现形式。通常情况下,小型项目的数据库可以不使用视图,但是在大型项目中,以及数据表比较复杂的情况下,视图的价值就凸显出来了,它可以帮助我们把经常查询的结果集放到虚拟表中,提升使用效率。理解和使用起来都非常方便。
创建视图:
针对单表:
CREATE VIEW 视图名称
AS 查询语句
举例:
CREATE VIEW empvu80
AS
SELECT employee_id, last_name, salary
FROM employees
WHERE department_id = 80;
CREATE VIEW emp_year_salary (ename,year_salary)
AS
SELECT ename,salary*12*(1+IFNULL(commission_pct,0))
FROM t_employee;
CREATE VIEW salvu50
AS
SELECT employee_id ID_NUMBER, last_name NAME,salary*12 ANN_SALARY
FROM employees
WHERE department_id = 50;
多表创建:
CREATE VIEW empview
AS
SELECT employee_id emp_id,last_name NAME,department_name
FROM employees e,departments d
WHERE e.department_id = d.department_id;
我们经常需要输出某个格式的内容,比如我们想输出员工姓名和对应的部门名,对应格式为emp_name(department_name),就可以使用视图来完成数据格式化的操作:
CREATE VIEW emp_depart
AS
SELECT CONCAT(last_name,'(',department_name,')') AS emp_dept
FROM employees e JOIN departments d
WHERE e.department_id = d.department_id
这段SQL代码创建了一个名为emp_depart的视图(VIEW),该视图将员工的姓氏(last_name)和所在部门的名称(department_name)合并为一个新的列emp_dept。视图的内容是从employees表(简称为e)和departments表(简称为d)中获取的,通过department_id字段进行连接。具体来说,通过JOIN关键字将employees表和departments表连接起来,然后通过WHERE子句筛选出department_id相等的记录。最后,使用CONCAT函数将员工的姓氏和所在部门的名称合并为一个新的列emp_dept。这个视图可以方便地查询员工和他们所在部门的信息。
当我们创建好一张视图之后,还可以在它的基础上继续创建视图。
举例:联合“emp_dept”视图和“emp_year_salary”视图查询员工姓名、部门名称、年薪信息创建“emp_dept_ysalary”视图。
CREATE VIEW emp_dept_ysalary
AS
SELECT emp_dept.ename,dname,year_salary
FROM emp_dept INNER JOIN emp_year_salary
ON emp_dept.ename = emp_year_salary.ename;
更新视图:
MySQL支持使用INSERT、UPDATE和DELETE语句对视图中的数据进行插入、更新和删除操作。当视图中的数据发生变化时,数据表中的数据也会发生变化,反之亦然。
更新操作与一般表的更新一般相同。
但是,并不是都可以更改:
修改视图:
方式1:使用CREATE OR REPLACE VIEW 子句修改视图:
CREATE OR REPLACE VIEW empvu80
(id_number, name, sal, department_id)
AS
SELECT employee_id, first_name || ' ' || last_name, salary, department_id
FROM employees
WHERE department_id = 80;
方式2:ALTER VIEW:
ALTER VIEW 视图名称
AS
查询语句