目录
第一章 了解数据库
1.数据库基础知识
(1).数据库的基本概念
什么是数据库?
数据库(Database)是指按照特定的数据模型组织、存储在计算机设备中并且能够支持数据的创建、修改、删除和查询的集合。简而言之,数据库是存储于磁盘或其他介质中的电子信息数据集合,它允许用户进行快速访问、维护和管理这些数据。
数据库的优点:
-
数据共享:在数据库中,数据是按照特定的数据模型组织和存储的,可以被多个应用程序或用户共享。这样可以避免数据的重复存储,提高了数据的利用效率和数据质量,同时,也可以保证数据的一致性。
-
数据独立性:在数据库中,数据的实现和物理存储是独立于应用程序的,这意味着如果数据的存储结构发生变化,应用程序的代码不需要修改。这提高了应用程序的可维护性和可扩展性。
-
数据安全性:数据库系统提供了严格的用户访问控制、密码保护、加密等安全措施,防止未经授权的用户随意访问和修改数据,保证了数据的完整性、一致性和可靠性。
-
数据一致性:在数据库中,对数据的插入、更新和删除操作都必须经过事务的管理,保证了数据的一致性。即使在发生系统故障时,也可以通过日志恢复机制来恢复数据的一致性。
-
数据易于维护:数据库提供了完善的备份和恢复机制,以及错误处理和异常处理机制,使得数据的管理和维护变得更加简单和可靠。
-
数据查询速度快:数据库采用高效的索引机制,可以快速定位和检索数据,提高了数据的检索和处理速度。
(2).数据模型介绍:
-
层次模型:层次模型是最早出现的数据库模型之一,它将数据组织成树形结构,每个节点表示一个实体,每条边表示数据之间的关系。层次模型要求每个实体只能有一个父节点,因此不适用于复杂的数据关系。
-
网状模型:网状模型是相对于层次模型的一种弥补,它允许一个实体有多个父节点,可以处理更复杂的数据关系。网状模型虽然增加了数据表示的灵活性和可扩展性,但其复杂性也大大增加。
-
关系模型:关系模型是目前最为广泛使用的数据库模型之一,它将数据组织成二维表格的形式,每个表格代表一种实体,每行记录表示一个具体的数据项,每列代表一个属性。关系模型采用SQL语言进行数据的查询和操作,具有简单易懂、易于扩展和重构的特点。
-
对象模型:对象模型是基于面向对象编程思想的数据库模型,它将数据组织成对象的形式,每个对象包含若干个属性和方法。对象模型可以更好地反映现实世界中各种事物之间的关系,支持继承、多态等面向对象特性。
-
XML模型:XML模型是一种基于XML文档的数据库模型,它将数据组织成树形结构,使用XML标记来描述各个实体之间的关系。XML模型适用于非结构化数据和半结构化数据的存储和查询,但在应对大量复杂的关系数据方面效率较低。
(3).mysql语言的简介:
MySQL是一种流行的关系型数据库管理系统,它是由瑞典MySQL AB公司开发,后被Sun公司收购,现在由Oracle公司所有和维护。MySQL支持多种操作系统,包括Windows、Linux、Unix等,同时也支持多种编程语言,包括C、C++、Java、PHP等
2.mysql常用数据类型
一.日期时间型:
-
DATE类型:DATE类型用于表示年、月、日的日期,格式为“YYYY-MM-DD”。例如,日期“2023年6月7日”可以表示为“2023-06-07”。
-
TIME类型:TIME类型用于表示小时、分钟、秒的时间,格式为“HH:MM:SS”。例如,时间“15:08:15”可以表示为“15:08:15”。
-
DATETIME类型:DATETIME类型用于表示日期和时间,格式为“YYYY-MM-DD HH:MM:SS”。例如,时间“2023年6月7日 15:08:15”可以表示为“2023-06-07 15:08:15”。
-
TIMESTAMP类型:TIMESTAMP类型也用于表示日期和时间,但格式与DATETIME类型不同。TIMESTAMP类型存储的是从1970年1月1日00:00:00到当前时间的秒数,格式为“YYYY-MM-DD HH:MM:SS”。
-
YEAR类型:YEAR类型用于表示年份,格式为“YYYY”。例如,年份“2023”可以表示为“2023”。
二.字符串型:
-
CHAR类型:CHAR类型用于存储固定长度的字符串,最长为255个字符。如果存储的字符串不足指定长度,则MySQL会使用空格补齐。例如,一个CHAR(10)类型的字段,如果存储“hello”,MySQL会把它变成“hello ”(注意后面有5个空格)。
-
VARCHAR类型:VARCHAR类型用于存储可变长度的字符串,最长为65535个字符。与CHAR类型不同,VARCHAR类型存储的实际字符串长度不会受限制,所以它可以节省存储空间。例如,一个VARCHAR(10)类型的字段,如果存储“hello”,MySQL会把它存储为“hello”。
-
TEXT类型:TEXT类型用于存储较长的文本数据,最长为4294967295个字符(约4GB)。TEXT类型比CHAR和VARCHAR类型更适合存储大量文本数据,如文章、评论等。但是,由于它的存储方式比较特殊,所以在查询和更新时需要注意性能问题。
-
BLOB类型:BLOB类型用于存储二进制数据,最长为65535个字节。BLOB类型适用于存储像图片、音频、视频等二进制文件。
-
ENUM类型:ENUM类型用于存储枚举值,它只能存储预定义的枚举值,类似于一个离散的、有限的集合。例如,一个ENUM('男', '女')类型的字段,只能存储“男”或“女”两种值。
三.整数型:
-
TINYINT类型:TINYINT类型用于存储小范围的整数数据,占用1个字节(8位),取值范围为-128到127。它通常用于存储布尔值(0或1)或状态码等。
-
SMALLINT类型:SMALLINT类型用于存储较小的整数数据,占用2个字节(16位),取值范围为-32768到32767。
-
MEDIUMINT类型:MEDIUMINT类型用于存储中等大小的整数数据,占用3个字节(24位),取值范围为-8388608到8388607。
-
INT类型:INT类型用于存储普通大小的整数数据,占用4个字节(32位),取值范围为-2147483648到2147483647。
-
BIGINT类型:BIGINT类型用于存储大范围的整数数据,占用8个字节(64位),取值范围为-9223372036854775808到9223372036854775807。
四.小数型
-
FLOAT类型:FLOAT类型用于存储单精度浮点数,占用4个字节(32位),可以精确到大约7位小数。FLOAT类型的取值范围为-3.4028235E38到3.4028235E38。
-
DOUBLE类型:DOUBLE类型用于存储双精度浮点数,占用8个字节(64位),可以精确到大约15位小数。DOUBLE类型的取值范围为-1.7976931348623157E+308到1.7976931348623157E+308。
第二章 数据库和数据表的基本操作
1.数据库的基本操作
一.mysql服务器、数据库、数据表的关系
一个MySQL服务器会包含多个数据库,每个数据库会包含多个数据表。在对MySQL进行操作时,需要先连接到指定的MySQL服务器,然后选择要使用的数据库,最后再对其中的数据表进行操作。在进行SQL查询时,需要指定数据表的名称以及要查询的列、条件等信息。
服务器:MySQL服务器是负责处理数据请求、执行SQL语句并返回结果的软件程序。一个MySQL服务器可以同时服务于多个客户端,并管理多个数据库。
数据库:MySQL数据库是一个逻辑容器,用于存储相关数据表和其他对象(如视图、存储过程等)。每个MySQL服务器可以创建多个数据库,不同的数据库之间相互独立,互不干扰。
数据表:MySQL数据表是一种二维表格结构,用于存储具有相同属性的数据记录。每个MySQL数据库可以包含多个数据表,不同的数据表之间可以建立关系,通过关联查询可以实现复杂的数据分析。
二.Mysql语句创建数据库
在MySQL中,可以使用CREATE DATABASE语句来创建一个新的数据库。该语句的基本格式为:
CREATE DATABASE XXXXXXX;
三.Mysql语句查看数据库
在MySQL中,可以使用SHOW DATABASES语句来查看当前MySQL服务器中存在的所有数据库。
SHOW DATABASES;
-- 执行该语句后,MySQL会返回一个类似下面的结果
+--------------------+
| Database |
+--------------------+
| information_schema |
| mydb |
| mysql |
| performance_schema |
| sys |
+--------------------+
四.Mysql语句选择数据库
在MySQL中,可以使用USE语句来选择当前要使用的数据库。
USE XXXname;
执行语句后,MySQL会将当前的工作环境切换到选择的数据库上,所有后续对数据表的操作都会针对该数据库进行。如果需要切换到其他数据库,只需要再次执行USE语句即可。需要注意的是,在执行USE语句之前必须先存在相应的数据库。如果不存在该数据库,则会返回一个错误提示。此时,需要先通过CREATE DATABASE语句来创建该数据库。
五.数据库的注释语句
- 单行注释:以“--”开头的语句表示单行注释。单行注释会忽略掉“--”后面的内容,并且只对当前行有效。
-- 查询ID为1的记录
- 多行注释:以“/”开头、以“/”结尾的语句表示多行注释。多行注释会忽略掉/和/之间的所有内容,并且可以跨越多个行。
/*
这是一个多行注释示例。
该注释会忽略掉
这里的所有内容
*/
2.数据表的基本操作
一.用Mysql语句创建数据表
在MySQL中,可以使用CREATE TABLE语句来创建一个新的数据表。
CREATE TABLE table_name (
column1 datatype,
column2 datatype,
...
);
其中,table_name是要创建的数据表名称,column1、column2等则表示要在数据表中创建的列名,datatype则表示每个列的数据类型。可以根据实际需求自定义列名和数据类型。
CREATE TABLE mytable (
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
firstname VARCHAR(30) NOT NULL,
lastname VARCHAR(30) NOT NULL,
email VARCHAR(50),
reg_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
在上面的示例中,我们创建了一个名为mytable的数据表,包含id、firstname、lastname、email和reg_date这几个列。其中,id列为自增长的主键,firstname和lastname列为必填字段,email列为可选字段,reg_date列为默认当前时间的日期类型字段。各个数据类型的含义可以参考MySQL文档。创建数据表时需要指定列名和数据类型,且列名不能重复。在实际开发中,可以根据实际业务需求来定义不同的数据表,并在其中创建不同的列。
二.用Mysql语句创建数据表
在MySQL中,可以使用SHOW TABLES语句来查看当前数据库中存在的所有数据表。
SHOW TABLES;
除了SHOW TABLES语句外,还可以使用DESCRIBE语句来查看指定数据表的结构信息。该语句的基本格式为:
DESCRIBE mytable;
可以使用通配符%来匹配任意字符,从而实现模糊匹配的功能。当使用了%通配符后,查询结果会包含所有满足条件的记录。
例如:查看所有包含字母“user”的数据表:
SHOW TABLES LIKE '%user%';
三.查看表结构、查看表创建语句
可以使用DESCRIBE语句或者SHOW COLUMNS语句来查看指定数据表的结构信息。这些语句可以用于了解数据表中包含哪些字段,每个字段的名称、数据类型、约束等信息。
- 使用DESCRIBE语句
DESCRIBE mytable;
- 使用SHOW COLUMNS语句
SHOW COLUMNS FROM mytable;
四.用Mysql语句删除数据表:
在MySQL中,可以使用DROP TABLE语句删除指定的数据表。该语句会永久删除指定数据表及其中包含的所有数据,因此在使用时需要谨慎。
DROP TABLE mytable;
五.用Mysql语句修改数据表结构:
在MySQL中,可以使用ALTER TABLE语句修改指定数据表的结构,包括添加、删除、修改列以及修改键等操作。
- 添加列
以下示例演示如何向名为mytable的数据表添加一个新列new_column
,数据类型为VARCHAR(50):
ALTER TABLE mytable ADD new_column VARCHAR(50);
执行该语句后,MySQL会向mytable数据表添加一个新列new_column
。
2.删除列
以下示例演示删除名为mytable的数据表的列old_column
:
ALTER TABLE mytable DROP COLUMN old_column;
执行该语句后,MySQL会从mytable数据表中删除列old_column
。
3.修改列名和数据类型
以下示例演示如何修改名为mytable的数据表的列column_name
的名称为new_column_name
,数据类型为INT:
ALTER TABLE mytable CHANGE column_name new_column_name INT;
执行该语句后,MySQL会将mytable数据表中的列column_name
的名称改为new_column_name
,数据类型改为INT。
第三章 数据的插入、更新与删除
1.使用Mysql语句实现数据的插入
在MySQL中,可以使用INSERT INTO语句向指定的数据表中插入新的数据。
INSERT INTO mytable (column1, column2, column3) VALUES ('value1', 'value2', 'value3');
执行该语句后,MySQL会向mytable数据表中插入一条新记录,该记录包含三个字段(column1、column2和column3),对应的值分别为'value1'、'value2'和'value3'。
在插入数据时,需要确保以下几点:
-
插入的数据必须符合该列的数据类型和约束;
-
如果未设置某一列的默认值,则必须为该列提供一个非NULL值;
-
如果未指定要插入数据的列,则必须为每个非NULL列提供一个值。
2.使用Mysql语句实现数据的删除
在MySQL中,可以使用DELETE语句删除指定数据表中的数据。
DELETE FROM mytable WHERE condition;
其中,condition为限制条件,用于指定要删除的记录。
在执行DELETE语句时,需要确保以下几点:
-
要谨慎使用DELETE语句,因为该操作是永久性的,会直接从数据表中删除记录;
-
如果未指定任何条件,则会删除数据表中的所有记录;
-
在删除数据时,建议先备份相关数据以防止误操作导致数据丢失。
3.使用Mysql语句实现数据的查找
在MySQL中,可以使用SELECT语句来实现数据的查找和筛选。
SELECT * FROM mytable ;
其中,mytable
为要查询的数据表名称,*
表示要查询的所有字段
在进行数据查找时,需要确保以下几点:
-
要根据实际业务需求来合理设置查询条件;
-
避免使用
SELECT *
这样的语句,因为它会查询所有字段,可能会影响性能; -
注意使用ORDER BY和LIMIT子句,以控制查询结果的数量和顺序。
4.使用Mysql语句实现数据的修改
在MySQL中,可以使用UPDATE语句来修改指定数据表中的记录。
UPDATE mytable SET column1='new value' WHERE condition;
其中,mytable
为要修改的数据表名称,column1
为要修改的字段名,'new value'
表示要更新的新值,WHERE condition
为限制条件,用于指定要修改的记录。
在进行数据修改时,需要确保以下几点:
-
要谨慎使用UPDATE语句,因为该操作会直接修改数据表中的记录;
-
如果未指定任何限制条件,则会修改数据表中的所有记录;
-
在修改数据时,应该先备份相关数据以防止误操作导致数据丢失。
第四章 单表查询
1.条件查询
一.比较条件的运算符
-
等于(=):用于判断字段的值是否等于给定值,例如
age = 30
。 -
不等于(<>):用于判断字段的值是否不等于给定值,例如
gender <> 'male'
。 -
大于(>):用于判断字段的值是否大于给定值,例如
salary > 5000
。 -
小于(<):用于判断字段的值是否小于给定值,例如
age < 20
。 -
大于等于(>=):用于判断字段的值是否大于等于给定值,例如
score >= 60
。 -
小于等于(<=):用于判断字段的值是否小于等于给定值,例如
height <= 1.8
。
二.比较条件的组合使用
-
AND:用于同时满足多个条件,例如
age > 30 AND gender = 'male'
将会返回年龄大于30岁且性别为男的记录。 -
OR:用于满足多个条件中的至少一个,例如
salary > 5000 OR age < 25
将会返回工资大于5000元或者年龄小于25岁的记录。 -
NOT:用于取反条件,例如
NOT gender = 'female'
将会返回非女性的记录。
三.BETWEEN关键字
在MySQL中,单表查询的条件查询可以使用BETWEEN关键字来匹配某个字段的值是否在给定的范围内。BETWEEN关键字跟AND运算符搭配使用,其语法如下:
SELECT column_name(s) FROM table_name WHERE column_name BETWEEN value1 AND value2;
其中,column_name
为要筛选的列名,table_name
为数据表名,value1
和value2
为区间的两个端点值。具体地说,如果一个字段的值大于或等于value1
并且小于或等于value2
,那么它就会被BETWEEN关键字筛选出来。
在使用BETWEEN关键字进行条件查询时,要确保给定的区间值是连续的。同时,BETWEEN关键字还支持日期型、时间型等其他数据类型的值范围查询,具体使用方式与数值型数据类似。
四.IN()关键字
在MySQL中,单表查询的条件查询可以使用IN关键字来筛选某个字段的值是否在给定的值集合中。IN关键字后面紧跟着一组由小括号包围的值,多个值之间用逗号隔开。
SELECT * FROM mytable WHERE age IN (20, 30);
IN关键字后面接收的是一个子查询时,应该将子查询写在圆括号中,并且保证子查询的结果是一列值,否则可能导致查询失败或结果不正确。
2.高级查询
一.DISTINCT关键字
在MySQL中,DISTINCT关键字用于返回唯一(不重复)的记录。它通常用在SELECT语句中,以便从数据表中获取唯一的行或列。
SELECT DISTINCT gender FROM mytable;
这个语句将只返回一个性别类型列表,并且每个类型只出现一次。如果不使用DISTINCT关键字,那么结果将会包含多次重复的性别类型。
二.ORDER BY语句
在MySQL中,ORDER BY语句用于对查询结果进行排序。它可以根据指定的一个或多个列对结果进行升序或降序排列。
SELECT name FROM mytable ORDER BY age DESC;
需要注意的是,ORDER BY语句应该写在SELECT语句的末尾,并且只适用于查询结果的列。同时,如果要对多个列进行排序,可以在ORDER BY语句后面列出多个列名,并使用逗号隔开。
三.LIMIT关键字
在MySQL中,LIMIT关键字用于限制SELECT语句返回结果的数量。它可以将查询结果分页,并指定从哪条记录开始、返回多少条记录。
如何从名为mytable
的数据表中获取前5条记录:
SELECT * FROM mytable LIMIT 5;
在实际应用中,可以将LIMIT关键字与ORDER BY语句一起使用,以便按照指定的顺序对查询结果进行排序并进行分页。
四.聚合函数
- SUM函数:用于计算某列的总和。例如,从名为
mytable
的数据表中获取age列的总和,可以这样写:SELECT SUM(age) FROM mytable;
- AVG函数:用于计算某列的平均值。例如,从名为
mytable
的数据表中获取age列的平均值,可以这样写:SELECT AVG(age) FROM mytable;
- COUNT函数:用于计算某列的行数。例如,从名为
mytable
的数据表中获取age列的行数,可以这样写:SELECT COUNT(age) FROM mytable;
- MAX函数:用于获取某列的最大值。例如,从名为
mytable
的数据表中获取age列的最大值,可以这样写:SELECT MAX(age) FROM mytable;
- MIN函数:用于获取某列的最小值。例如,从名为
mytable
的数据表中获取age列的最小值,可以这样写:SELECT MIN(age) FROM mytable;
需要注意的是,聚合函数只能用于SELECT语句中,并且通常与GROUP BY子句一起使用,以便对不同的数据分组进行统计和汇总。同时,如果要对NULL值进行统计,可以使用IFNULL函数将NULL值转换为0或其他默认值。
例如,如果要从名为mytable
的数据表中获取不同性别的人数和平均年龄,可以这样写:
SELECT gender, COUNT(*), AVG(age) FROM mytable GROUP BY gender;
这个语句将按照性别分组,并统计每个性别的人数和平均年龄。
3.分组查询
一.Group by语句的应用
在MySQL中,GROUP BY语句用于对查询结果进行分组,并对每个分组进行统计和汇总。通过GROUP BY语句,可以将数据按照不同的维度进行分组,从而实现更加灵活和精细的数据分析和处理。
以下是一个使用GROUP BY语句的示例,演示如何从名为mytable
的数据表中获取不同性别的人数和平均年龄:
SELECT gender, COUNT(*), AVG(age) FROM mytable GROUP BY gender;
这个语句将按照性别分组,并统计每个性别的人数和平均年龄。
注意:GROUP BY语句应该写在SELECT语句的末尾,并且只能跟在FROM、WHERE和HAVING语句之后。同时,GROUP BY语句中只能包含SELECT语句中的列名或聚合函数,不能包含其他表达式或常量。
GROUP BY语句通常与聚合函数一起使用,以便对不同的数据分组进行统计和汇总。如果省略GROUP BY子句,则会把整张表作为一个分组进行处理,而不是按照指定的列进行分组。
二.HAVING子句的应用
在MySQL中,HAVING语句用于对分组后的查询结果进行筛选和过滤。与WHERE语句不同的是,HAVING语句针对的是分组后的各个组,而WHERE语句针对的是原始数据表中的记录。这就意味着,只有当使用GROUP BY语句对查询结果进行分组时,才能使用HAVING语句对分组结果进行过滤。
如何从名为mytable
的数据表中获取年龄在30岁及以上的人数和平均年龄:
SELECT gender, COUNT(*), AVG(age) FROM mytable
GROUP BY gender
HAVING AVG(age) >= 30;
这个语句首先按照性别进行分组,并统计每个性别的人数和平均年龄。然后,使用HAVING语句筛选出平均年龄大于等于30岁的分组结果。
HAVING语句应该写在GROUP BY语句之后,并且只能包含聚合函数和分组列,不能包含其他表达式或常量。同时,HAVING语句的使用应该根据具体情况选择合适的条件和操作符,并考虑分组结果的大小和效率。
HAVING语句通常与GROUP BY语句一起使用,以便对不同的数据分组进行筛选和过滤。如果省略HAVING子句,则会返回所有分组结果,而不是只返回满足条件的分组结果。
Having语句与where子句的区别:
1.HAVING语句是在GROUP BY语句之后执行的,而WHERE语句是在GROUP BY语句之前执行的。
这意味着,HAVING语句是应用于分组后的结果,而WHERE语句是应用于原始数据表中的记录。因此,只有当使用GROUP BY语句对查询结果进行分组时,才能使用HAVING语句;而WHERE语句可以用于任何单表查询中。
2.HAVING语句只能用于聚合函数和分组列,而WHERE语句可以用于任何列。
这是因为HAVING语句是针对分组后的结果进行过滤的,而分组列和聚合函数是定义分组的关键元素。而WHERE语句则是针对原始数据表中的记录进行过滤的,因此可以用于任何列。
3.HAVING语句可以使用聚合函数,而WHERE语句不能使用聚合函数。
这意味着,HAVING语句可以对分组结果进行聚合计算和筛选,而WHERE语句只能使用普通的比较操作符对列进行过滤。
4.HAVING语句的执行顺序在WHERE语句之后。
这个顺序是非常重要的,因为它可以影响到查询的性能和结果。如果WHERE语句过滤掉了大量的记录,那么HAVING语句就只需要处理剩下的记录,从而提高查询效率。反之,如果HAVING语句先执行,那么就需要对所有的记录进行聚合计算和筛选,即使这些记录在WHERE语句中已经被排除了。
第五章 多表查询
1.连接查询
一.内查询
在MySQL中,连接查询是用来处理多个表之间的关联关系的常用方法之一。而内查询则是一种在查询语句中嵌套使用的子查询语句,通常用于检索符合特定条件的数据,并将其作为主查询的一部分来操作。在连接查询中使用内查询可以进一步过滤和筛选要返回的结果集,从而实现更精确的查询和分析。
如果要在连接查询中使用内查询,可以将子查询作为连接条件中的一个或者多个条件。
SELECT orders.order_id, customers.customer_name
FROM orders
INNER JOIN customers
ON orders.customer_id = customers.customer_id
AND customers.customer_state = 'CA';
这个查询语句中,使用了INNER JOIN语句将orders
表和customers
表连接起来,并且将customers
表中customer_state
列等于'CA'的行作为连接条件之一。这样就只会查询到位于加州的顾客所下的订单,而不会查询到其他州的订单。
二.外查询
在MySQL中,连接查询是用来处理多个表之间的关联关系的方法之一,将多个表中的数据联合起来进行查询和分析。连接查询通常包括内连接(INNER JOIN)、左连接(LEFT JOIN)、右连接(RIGHT JOIN)和全连接(FULL OUTER JOIN)等方式,其中外连接可以将外部表的所有记录返回给结果集,无论是否与内部表的数据匹配。
(1).左连接(LEFT JOIN)
左连接是一种连接操作,它可以返回左侧表的所有行及其匹配的右侧表的行。如果右侧表没有匹配的行,则返回NULL值。通过LEFT JOIN可以查询到符合特定条件的主表记录,并同时返回关联表中的数据。
SELECT orders.order_id, customers.customer_name
FROM orders
LEFT JOIN customers
ON orders.customer_id = customers.customer_id
WHERE orders.order_date >= '2022-01-01';
这个查询语句中,使用了LEFT JOIN语句将orders
表和customers
表连接起来,并过滤出order_date
大于等于'2022-01-01'的订单。即使有些订单没有匹配到任何客户信息,也会被包含在结果集中,并且customer_name
返回NULL值。
(2).右连接(RIGHT JOIN)
右连接是一种连接操作,与左连接相反。它可以返回右侧表的所有行及其匹配的左侧表的行。如果左侧表没有匹配的行,则返回NULL值。通过RIGHT JOIN可以查询到关联表中的所有数据,并同时返回符合特定条件的主表记录。
SELECT orders.order_id, customers.customer_name
FROM orders
RIGHT JOIN customers
ON orders.customer_id = customers.customer_id
WHERE customers.customer_state = 'CA';
这个查询语句中,使用了RIGHT JOIN语句将orders
表和customers
表连接起来,并过滤出位于加州的客户信息。即使有些客户没有下任何订单,也会被包含在结果集中,并且order_id
返回NULL值。
三.交叉连接
在MySQL中,连接查询是用来处理多个表之间的关联关系的常用方法之一,可以将多个表中的数据联合起来进行查询和分析。连接查询通常包括内连接(INNER JOIN)、左连接(LEFT JOIN)、右连接(RIGHT JOIN)和全连接(FULL OUTER JOIN)等方式,其中交叉查询也是一种较为特殊的连接查询方式。
交叉查询(CROSS JOIN)是指将两个或多个表中的每一行进行笛卡尔积操作,并返回所有可能的组合。这种查询方式没有连接条件,适用于需要生成所有可能组合的情况,它的结果不是一张表,而是一个虚拟的表格。
SELECT *
FROM categories
CROSS JOIN products;
这个查询语句中,使用了CROSS JOIN语句将categories
表和products
表连接起来,生成了一个包含所有可能组合的虚拟表格。如果categories
表中有5条记录,products
表中有10条记录,则结果集中将会有50条记录。
2.子查询
在MySQL中,子查询是指在一个查询语句中嵌套另一个查询语句。它可以根据一个查询的结果集进行另一个查询操作,或者将查询结果用作其他表达式的一部分。子查询可以用于多表查询中,以实现更复杂的数据处理和分析需求。
子查询通常包括标量子查询、行子查询和列子查询三种类型:
1.标量子查询
标量子查询是指返回单一值的子查询,它嵌套在SELECT语句的某个表达式中,并返回一个标量值。标量子查询经常用来作为WHERE子句中的条件。
示例:
SELECT *
FROM customers
WHERE customer_id IN (SELECT customer_id FROM orders WHERE order_date >= '2022-01-01');
这个查询语句中,使用了标量子查询将orders
表中所有在"2022-01-01"之后下过订单的客户ID获取,并用于WHERE子句中的IN运算符中,以筛选出这些客户对应的信息。
2.行子查询
行子查询是指返回多个行的子查询,它嵌套在SELECT语句的FROM子句中,并返回一张或多张表格。行子查询经常用来作为JOIN子句中的表。
示例:
SELECT *
FROM customers, (SELECT * FROM orders WHERE order_date >= '2022-01-01') AS new_orders
WHERE customers.customer_id = new_orders.customer_id;
这个查询语句中,使用了行子查询将orders
表中在"2022-01-01"之后下的订单筛选出来,并作为一个新的虚拟表格(new_orders
)加入到查询中,并与customers
表进行JOIN操作,最终返回符合条件的客户和订单信息。
3.列子查询
列子查询是指返回单列或多列值的子查询,它嵌套在SELECT语句的某个表达式中,并返回一列或多列值。列子查询经常用来作为SELECT语句中的列。
示例:
SELECT customer_name, (SELECT COUNT(*) FROM orders WHERE orders.customer_id = customers.customer_id) AS order_count
FROM customers;
这个查询语句中,使用了列子查询将每个客户对应的订单数目获取,并作为一个新的列(order_count
)加入到查询结果中。
子查询的效率通常比较低,且嵌套层数过多容易导致性能问题,因此在使用时要根据实际情况适度选择并慎重设计。同时也可以考虑使用连接查询等其他方式来代替子查询,以提高查询效率。
3.合并结果集(联合查询)
在MySQL中,合并多个查询结果集是一种常见的操作需求。通常情况下,我们可以通过UNION, UNION ALL, INTERSECT, EXCEPT等操作符实现多个查询结果集的合并。
1.UNION操作符
UNION操作符用于合并两个或多个SELECT语句的结果集,并去除重复数据,保留唯一性,其语法如下:
SELECT columns
FROM table1
UNION
SELECT columns
FROM table2
[UNION ...];
例如:
SELECT city FROM customers WHERE country = 'China'
UNION
SELECT city FROM suppliers WHERE country = 'China';
这个查询语句将从customers
表和suppliers
表中获取来自中国的城市名称,返回包含所有不重复城市名称的结果集。
2.UNION ALL操作符
与UNION操作符不同,UNION ALL操作符用于合并两个或多个SELECT语句的结果集,并不去除重复数据,保留所有数据,其语法如下:
SELECT columns
FROM table1
UNION ALL
SELECT columns
FROM table2
[UNION ALL ...];
例如:
SELECT city FROM customers WHERE country = 'China'
UNION ALL
SELECT city FROM suppliers WHERE country = 'China';
这个查询语句将从customers
表和suppliers
表中获取来自中国的城市名称,返回包含所有城市名称的结果集,可能存在重复数据。
3.INTERSECT操作符
INTERSECT操作符用于获取两个或多个SELECT语句返回的结果集的交集,其语法如下:
SELECT columns
FROM table1
INTERSECT
SELECT columns
FROM table2
[INTERSECT ...];
例如:
SELECT city FROM customers WHERE country = 'China'
INTERSECT
SELECT city FROM orders WHERE order_date >= '2022-01-01';
这个查询语句将查询出来自中国且在"2022-01-01"之后有订单的城市名称,返回包含所有这样的城市名称的结果集。
需要注意的是,INTERSECT操作符在MySQL中并不支持,可以通过其他方式模拟实现。
4.EXCEPT操作符
EXCEPT操作符用于获取两个或多个SELECT语句返回的结果集的差集,即第一个结果集与其他结果集的共有部分的补集,其语法如下:
SELECT columns
FROM table1
EXCEPT
SELECT columns
FROM table2
[EXCEPT ...];
例如:
SELECT city FROM customers WHERE country = 'China'
EXCEPT
SELECT city FROM suppliers WHERE supplier_state = 'Beijing';
这个查询语句将查询从中国来但不在北京供应商供货的城市名称,返回包含所有这样的城市名称的结果集。
第六章 视图与索引
1.视图
在MySQL中,视图(View)是一个虚拟的表格,是由 SELECT 查询语句创建出来的结果集,可以像普通的表格一样使用。视图并不实际存储数据,而是通过查询获取数据。
使用视图有以下几个优点:
-
简化复杂查询:如果存在多个表格并且需要进行复杂计算,可以使用视图将复杂查询简化,提高查询效率。
-
安全性控制:使用视图,可以控制用户只能访问部分列或部分行数据,提高数据的安全性。
-
数据抽象:使用视图,可以把复杂的查询条件或逻辑抽象出来,让用户更方便地使用和理解。
创建视图的语法如下:
CREATE VIEW view_name AS select_statement;
其中,view_name
是视图名称,select_statement
是SELECT语句,用于定义视图的结构。
例如,创建一个名为customer_order_view
的视图,包含客户姓名和其对应的订单编号:
CREATE VIEW customer_order_view AS
SELECT customers.customer_name, orders.order_id
FROM customers JOIN orders ON customers.customer_id = orders.customer_id;
视图创建后,可以像普通表格一样进行查询,例如:
SELECT * FROM customer_order_view WHERE customer_name = 'John Doe';
这个查询语句将返回所有名为"John Doe"的客户和其对应的订单编号。
虽然视图与普通表格类似,但是创建视图时需要考虑SELECT语句的复杂程度和效率问题,因为视图查询的效率并不一定比普通查询高,有时候甚至会造成性能问题。并且,对视图进行增删改操作时,实际上是对其所依赖的原表格进行操作,因此需要注意数据完整性和安全性问题。
2.索引
在 MySQL 中,索引(Index)是一种特殊的数据结构,用于提高查询效率和排序速度。索引可以在表格中创建,并且可以包含一个或多个列,以便快速搜索、排序和过滤数据。
使用索引有以下几个优点:
-
提高查询效率:创建索引后,查询语句可以直接定位到需要的数据行,大大加快了查询速度。
-
加速排序:如果查询语句需要按照某个列进行排序,创建索引可以快速完成排序操作。
-
减少磁盘 I/O 操作:创建索引可以将数据缓存到内存中,减少磁盘 I/O 操作,提高整体系统性能。
创建索引的语法如下:
CREATE [UNIQUE] INDEX index_name
ON table_name (column_name [, column_name, ...]);
其中,index_name
是索引名称,table_name
是需要创建索引的表格名称,column_name
是需要创建索引的列名。如果需要创建唯一索引,可以在CREATE
关键字后添加UNIQUE
。
例如,创建一个名为idx_customers_email
的索引,用于加速根据电子邮件地址查找客户记录的查询:
CREATE UNIQUE INDEX idx_customers_email ON customers (email);
第七章 数据完整性
1.域完整性
在 MySQL 数据库中,域完整性(Domain Integrity)是指对表格的某个列中的数据进行限制和验证,以确保它们符合特定的标准和要求。通常,域完整性是通过定义列的数据类型、大小和约束来实现的。
使用域完整性有以下几个优点:
-
数据的正确性:使用域完整性可以确保数据的正确性,防止无效或不正确的数据进入表格中。
-
数据一致性:使用域完整性可以确保数据的一致性,保证表格中所有数据都符合相同的标准和要求。
-
数据可靠性:使用域完整性可以提高数据的可靠性,防止数据损坏或丢失。
常见的域完整性约束包括:
-
非空约束:限制列中的数据不能是空值。
-
唯一约束:限制列中的数据必须是唯一的,不能重复。
-
主键约束:将列指定为表格的主键,并同时设置非空和唯一约束。
-
外键约束:将列指定为外键,并建立与另一个表格之间的关联,以实现数据的引用完整性。
-
默认约束:指定当添加新记录时,如果没有提供相应的值,则使用默认值填充该列。
创建表格时可以在列定义中添加这些约束,例如:
CREATE TABLE users (
id INT PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(50) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
在这个例子中,users
表格有一个自增的id
列作为主键,同时username
和email
列中的数据必须是唯一的、非空的;password
列不能为NULL
;created_at
列使用默认约束,如果不提供相应的值,则使用当前时间戳填充。
在设计数据库时需要仔细考虑域完整性约束的类型和数量,以便确保数据的正确性、一致性和完整性。同时,对于已有的表格,可以通过ALTER TABLE
语句添加或更改域完整性约束。
2.实体完整性
在 MySQL 数据库中,实体完整性(Entity Integrity)是指确保表格中的每一行都具有唯一的标识符,以及每个表格中所有相关列都包含有效的数据。通常情况下,实体完整性是通过定义主键和外键实现的。
使用实体完整性约束有以下几个优点:
-
数据的正确性:使用实体完整性可以确保每个表格中的数据都是唯一的,没有重复记录或行。
-
数据的一致性:使用实体完整性可以确保数据之间的关系正确、一致,保证表格中所有数据之间相互关联或引用,从而防止数据冲突或错误。
-
数据的可维护性:使用实体完整性可以提高数据的可维护性,便于对表格中的数据进行增删改查等操作。
常见的实体完整性约束包括:
-
主键约束:将列或列组指定为表格的主键,以确保每一行有唯一的标识符,并且不能为 NULL。
-
外键约束:将列或列组指定为外键,并建立与另一个表格之间的关联,以确保数据之间的关系正确、一致和有效。
创建表格时可以在列定义中添加这些约束,例如:
CREATE TABLE products (
id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
category_id INT NOT NULL,
FOREIGN KEY (category_id) REFERENCES categories(id)
);
CREATE TABLE categories (
id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL
);
在这个例子中,products
表格有一个自增的id
列作为主键,category_id
列作为外键,与categories
表格中的id
列建立关联。同时,name
和price
列中的数据不能为空。categories
表格也有一个自增的id
列作为主键,并且name
列中的数据不能为空。
3.参照完整性
在 MySQL 数据库中,参照完整性(Referential Integrity)是指通过建立表格之间的关联关系,确保任何时候进行的数据操作都不会破坏表格之间的一致性和完整性。通常情况下,参照完整性是通过定义主外键关系实现的。
使用参照完整性有以下几个优点:
-
数据的正确性:使用参照完整性可以确保数据之间的关系正确、一致,保证表格中所有数据之间相互关联或引用,从而防止数据冲突或错误。
-
数据的完整性:使用参照完整性可以确保数据的完整性,当尝试进行不合法操作时,例如删除被其他地方引用的数据,系统将拒绝该操作并给出错误提示,防止数据在不应该被破坏的情况下被删除。
-
数据的可维护性:使用参照完整性可以提高数据的可维护性,在修改或删除数据时,不需要手动维护数据之间的关系。
常见的参照完整性约束包括:
-
外键约束:将列或列组指定为外键,并建立与另一个表格之间的关联,以确保数据之间的关系正确、一致和有效。
-
级联更新:当主表格中的数据更新时,自动更新与之关联的从表格中的相关数据。
-
级联删除:当主表格中的数据被删除时,自动删除与之关联的从表格中的相关数据。
创建表格时可以在列定义中添加这些约束,例如:
CREATE TABLE products (
id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
category_id INT NOT NULL,
FOREIGN KEY (category_id) REFERENCES categories(id) ON UPDATE CASCADE ON DELETE RESTRICT
);
CREATE TABLE categories (
id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL
);
在这个例子中,products
表格有一个自增的id
列作为主键,category_id
列作为外键,与categories
表格中的id
列建立关联。同时,使用了级联更新和限制删除约束。categories
表格也有一个自增的id
列作为主键,并且name
列中的数据不能为空。
第八章 数据库编程
1.函数
一.内置函数
-
字符串函数:包括
CONCAT
、SUBSTR
、LENGTH
、TRIM
、LOWER
、UPPER
等,用于处理字符串类型的数据。 -
数值函数:包括
ABS
、ROUND
、CEILING
、FLOOR
、MOD
等,用于处理数值类型的数据。 -
日期函数:包括
NOW
、CURDATE
、YEAR
、MONTH
、DAY
、DATE_FORMAT
等,用于处理日期和时间类型的数据。 -
聚合函数:包括
SUM
、AVG
、COUNT
、MAX
、MIN
等,用于对一组数据进行聚合计算。 -
条件函数:包括
IF
、CASE
等,用于根据条件进行判断和操作。 -
其他函数:包括
RAND
、INET_ATON
、INET_NTOA
、USER
等,用于进行随机数生成、IP 地址转换、用户信息查询等操作。
二.自定义函数
创建自定义函数需要使用 CREATE FUNCTION
语句,语法如下所示:
CREATE [AGGREGATE] FUNCTION function_name ([parameter[, parameter]...])
RETURNS return_data_type
BEGIN
function_body
END;
其中,AGGREGATE
关键字可选,用于定义聚合函数;function_name
为自定义函数的名称;parameter
为输入参数列表,每个参数包含参数名和参数类型;RETURN
关键字后面为返回值的数据类型;function_body
为函数体,包含具体的计算逻辑。
下面是一个示例,演示如何创建一个简单的自定义函数,用于计算两个数的和:
CREATE FUNCTION add_nums(num1 INT, num2 INT)
RETURNS INT
BEGIN
DECLARE sum INT;
SET sum = num1 + num2;
RETURN sum;
END;
在上面的例子中,自定义函数名为 add_nums
,接受两个整型参数 num1
和 num2
,计算它们的和并返回整型结果。函数体使用 DECLARE
声明了一个变量 sum
,并使用 SET
进行赋值。最后使用 RETURN
返回计算结果。
创建好自定义函数之后,就可以像内置函数一样进行调用了,例如:
CREATE FUNCTION add_nums(num1 INT, num2 INT)
RETURNS INT
BEGIN
DECLARE sum INT;
SET sum = num1 + num2;
RETURN sum;
END;
自定义函数也需要遵循 MySQL 的函数编写规则,例如,函数名不能与系统函数重名,输入参数和返回值必须使用正确的数据类型,并且函数体中不能包含无效的 SQL 语句。
2.存储过程
MySQL 存储过程是一种预定义的 SQL 语句集合,可以接受参数并在数据库中存储。存储过程可以包含分支和循环结构,可以使用条件判断、循环、变量操作等多种编程技巧。
与自定义函数不同的是,存储过程可以执行多个 SQL 语句,因此更适用于需要进行复杂数据操作的场景。同时,存储过程也可以被其他程序或脚本调用,避免了重复编写相同代码的问题。
创建存储过程需要使用 CREATE PROCEDURE
语句,语法如下所示:
CREATE PROCEDURE procedure_name ([IN/OUT/INOUT] parameter[, IN/OUT/INOUT] parameter]...)
BEGIN
procedure_body
END;
其中,procedure_name
为存储过程的名称;parameter
为参数列表,可以包含输入参数 IN
、输出参数 OUT
和输入输出参数 INOUT
,每个参数包含参数名和参数类型;procedure_body
为存储过程的主体代码,包含多个 SQL 语句和程序流程控制语句,例如 IF、LOOP、WHILE 等。
下面是一个示例,演示如何创建一个简单的存储过程,用于查询订单数量:
CREATE PROCEDURE count_orders(IN start_date DATE, IN end_date DATE, OUT order_count INT)
BEGIN
SELECT COUNT(*) INTO order_count
FROM orders
WHERE order_date BETWEEN start_date AND end_date;
END;
在上面的例子中,存储过程名为 count_orders
,接受两个日期类型的输入参数 start_date
和 end_date
,并使用 OUT
参数 order_count
返回查询结果。存储过程主体中使用了 SQL 语句 SELECT COUNT(*) INTO order_count
计算订单数量,并将结果赋值给 order_count
输出参数。
创建好存储过程之后,就可以像调用函数一样进行调用了,例如:
CALL count_orders('2023-01-01', '2023-06-07', @count);
SELECT @count; -- 显示订单数量
在使用存储过程时需要理解存储过程的具体语法和用法,并且根据实际情况选择合适的存储过程来处理数据,以便获得更好的性能和结果。否则,存储过程可能会降低数据库的性能,甚至引起安全问题。
4.流程控制
1.IF...THEN...ELSE: 进行条件判断,根据条件执行不同的语句。语法如下:
IF condition THEN
statement1;
ELSE
statement2;
END IF;
2.CASE...WHEN...THEN...ELSE: 根据不同的条件执行不同的语句。语法如下:
CASE case_value
WHEN condition1 THEN statement1;
WHEN condition2 THEN statement2;
...
ELSE statementN;
END CASE;
其中,case_value
为待比较值,如果与某个条件相等则执行对应的 statement
,否则执行 ELSE
后的语句。
3.WHILE...DO: 只要条件满足就重复执行一组语句。语法如下:
WHILE condition DO
statement;
END WHILE;
其中,condition
为循环条件,只要满足条件就重复执行 statement
。
4.REPEAT...UNTIL: 类似于 WHILE...DO
,但是在判断循环条件之前始终执行一次 statement
。语法如下:
REPEAT
statement;
UNTIL condition;
其中,statement
为要执行的语句,condition
为循环条件,只有当条件满足时才退出循环。
5.LOOP: 无限循环一组语句,直到用 LEAVE
语句显式退出循环。语法如下:
LOOP
statement;
IF condition THEN
LEAVE loop_label;
END IF;
END LOOP;
其中,condition
为退出循环的条件,可以在 LOOP
前使用 label_name:
定义标签,并在 LEAVE
后引用该标签。
5.触发器
MySQL 触发器是一种特殊的存储过程,它会在指定的条件满足时自动执行,通常用于在数据库中处理一些重要的业务逻辑。MySQL 触发器可以在插入、更新或删除数据时调用,并且可以在执行之前或之后执行,可以对触发器执行的 SQL 语句进行更改。
MySQL 触发器有三个关键部分:触发时机(BEFORE 或 AFTER)、触发事件(INSERT、UPDATE 或 DELETE)和触发表。当符合触发条件时,就会跟据指定的触发事件自动执行触发器。
下面是 MySQL 中创建触发器的基本语法:
CREATE TRIGGER trigger_name
[BEFORE/AFTER] [INSERT/UPDATE/DELETE]
ON table_name
FOR EACH ROW
BEGIN
trigger_body
END;
其中,trigger_name
为触发器的名称;BEFORE
或 AFTER
表示在指定事件之前或之后触发;INSERT
、UPDATE
或 DELETE
为需要触发的事件类型;table_name
指定了触发器所属的表;FOR EACH ROW
表示对每行数据都将执行触发器;trigger_body
是触发器主体,包含触发器执行的 SQL 语句或存储过程。
以下是一个创建 'books' 表触发器的例子,当有新图书插入时会自动计算该作者的图书数量并更新 'authors' 表:
CREATE TRIGGER book_count_trigger AFTER INSERT ON books
FOR EACH ROW
UPDATE authors SET book_count = book_count + 1 WHERE id = NEW.author_id;
在上面的例子中,我们创建了一个名为 'book_count_trigger' 的触发器,它将在 'books' 表插入新数据时触发。在触发器中,我们使用 NEW
关键字引用了新插入的数据,并执行 SQL 语句 UPDATE authors SET book_count = book_count + 1 WHERE id = NEW.author_id;
,用于更新 'authors' 表中对应作者的图书数量。