> 技术文档 > 【MySQL学习】:关系数据库标准语言SQL_mysql支持关系数据库标准语言么

【MySQL学习】:关系数据库标准语言SQL_mysql支持关系数据库标准语言么

📃个人主页:island1314

🔥个人专栏:MySQL学习

⛺️  欢迎关注:👍点赞 👂🏽留言 😍收藏  💞 💞 💞


引言

下面的操作都是在windows 的操作,此时MySQL在Windows下不区分大小写,但在Linux下默认是区分大小写的。
SQL通用语法:

  1. SQL 语句可以单行 或 多行书写,以分号结尾
  2. SQL 语句可以使用 空格 / 缩进来增强语句可读性
  3. MySQL 数据库的SQL语句不区分大小写,关键字一般建议使用大写
  4. 注释:  单行注释: -- 注释内容 或 # 注释内容 (MySQL 特有) 多行注释:/* 注释内容 */

SQL分类

分类 全称 说明 DDL Data Defintion Language 数据定义语言,用来定义数据库对象(数据库,表,字段) DML Data Manipulation Language 数据操纵语言,用来对数据库表中的数据进行增删改 DQL Data Query Language 数据定义语言,用来查询数据库表的记录 DCL Data Control Language 数据定义语言,用来创建数据库用户,控制数据库的访问权限。

1. 数据库操作(DDL)

输入密码 进入MySql数据库

1.1 建立数据库

create database  [IF NOT EXIST] 数据库名字 [DEFAULT CHARSET 字符集] [COLIATE 排序规则];

注:分号记得打,单词与单词之间至少有一个空格。

由于数据库创建的时候,要求不能重复,此时则可以在创建的时候,加上上面第一个[ ]内 的命令

1.2 查看数据库

  1. 查看所有数据库
    SHOW DATABASES;  -- 注意:databases 后面带 \'s\'
  2. 查看当前数据库
    SELECT DATABASES(数据库名)

1.3 选中数据库

  • use 数据库名; 

1.4 删除数据库

DROP DATABASE 数据库名;

2. 常用数据类型

2.1 数值类型

分为整型和浮点型

数据类型 大小(字节) 说明 对应java类型 对应C类型 BIT[ (M) ] M指定位数,默认为1 M指定位数,默认为1 常用Boolean对应BIT,此时默认是1位,即只能存0和1 char[] TINYINT 1 Byte signed char SMALLINT 2 Short short int INT 4 Integer int BIGINT 8 Long long long int FLOAT(M, D) 4 单精度,M指定长度,D指定
小数位数。会发生精度丢失 Float float DOUBLE(M,
D)
8 Double double DECIMAL(M,
D)
M/D最大值+2

双精度,M指定长度,D表示小数点位数。精确数值

BigDecimal char[] NUMERIC(M,
D)
M/D最大值+2 和DECIMAL一样  BigDecimal char[]

扩展资料

数值类型可以指定为无符号(unsigned),表示不取负数。

1字节(bytes)= 8bit。
对于整型类型的范围:

  1. 有符号范围:-2^(类型字节数*8-1)到2^(类型字节数*8-1)-1,如int是4字节,就是-2^31到2^31-1
  2. 无符号范围:0到2^(类型字节数*8)-1,如int就是2^32-1

尽量不使用unsigned,对于int类型可能存放不下的数据,int unsigned同样可能存放不下,与其
如此,还不如设计时,将int类型提升为bigint类型。

2.2 字符类型

数据类型 大小(字节) 说明 对应java类型 对应C类型

VARCHAR

(SIZE)

0-65,535 可变长度字符串 String char[] TEXT 0-65,535 中等长度文本数据 String char[] MEDIUMTEXT  0-16 777 215 中等长度文本数据 String char[] BLOB 0-65,535 二进制形式的长文本数据 byte[] char[]

注:上面的size表示该类型最多存储几个字符(不是字节)比如:当写了 size = 10 时,不是说当前就立即分配10 个字符的存储空间......,而是先会分配一个比较小的空间,如果不够,再自动扩展,最大的空间不超过10

2.3 时间类型

数据类型 大小(字节) 说明 对应java类型 对应C类型 DATETIME 8 范围从1000到9999年,不会进行时区的检索及转换。 java.util.Date、
java.sql.Timestamp MYSQL、TIME TIMESTAMP 4 范围从1970到2038年,自动检索当前时区并进行转换。 java.util.Date、
java.sql.Timestamp MYSQL、TIME

一般常用:

  • 整数:int,long
  • 小数:double,decimal
  • 字符串:varchar
  • 时间日期:datetime

3. 数据表操作(DDL)

针对数据表的操作,前提是选中数据库(use 数据库)

3.1 创建表

CREATE TABLE ( [列级完整性约束],   [列级完整性约束],  ...  [, ]);

🔥 建表的同时,通常还可以定义与该表有关的完整性约束,这些完整性约束被存入系统的数据字典。

  • 当用户操作表中数据时,由关系数据库管理系统自动检查该操作是否违背这些完整性约束。
  • 如果完整性约束涉及该表的多个属性列,则必须定义在表级上,否则既可以定义在列级也可以定义在表级。

注:若确实想让表名/列名 和关键字一样,可以使用 反引号 ` (键盘左上角,ESC下面,tab上面的那个按键)来吧表名 列名引起来,此处列名 在前面,类型 在后面。但是也不是所有语言都类型在前的,有些语言类型可以在后面!!!比如C++,Go,Python。

3.2 查看该数据库中的所有表

  • show tables;  (查看当前数据库下有那些表,比如我们刚刚使用了use来去使用数据库,则就在当前数据库进行查找)

3.3 查看指定表的结果

desc 表名; 

  •  查看表中的列
SHOW COLUMNS FROM 表名;  (查看表中有那些列,更便捷的方式是:describe 表名;) 

案例: 

其中:

  • field: 表示字段名字
  • Type:表示字段类型,注:此处的(11)表示的是显示的宽度,显示这个int类型时,最多占据 11 个字符的宽度(和存储时候的容量无关)
  • Null: 表示是否为空,注:此处写成 YES允许这一列为NULL,也可以写成null、Null
  • Key:索引类型
  • Default:默认值,是NULL可以通过 default 约束来修改
  • Extra:扩充(额外信息)
show create table 表名 \\G; -- 查看创建表的sql语句, \\G 是格式化显示的意思

案例:

3.4 删除表

drop tables [IF EXISTS]  [restrict | cascade] 
  1. 若选择RESTRICT,则该表的删除有限制条件,即该表不能被其他表的约束所引用(如CHECK、FOREIGN KEY等约束),不能有视图,不能有触发器(trigger),不能有存储过程或函数等。如果存在这些依赖该表的对象,则此表不能被删除
  2. 若选择CASCADE,则该表的删除没有限制条件。在删除基本表的同时,相关的依赖对象.都可能被一起删除
  3. 该语句的默认选项是 RESTRICT

  • 删除指定表,并且重新创建该表
TRUNCATE TABLE 列名

3.5 修改表

  1. 添加字段
    alter table  [add[column]   [完整性约束]] [add ] [drop [column]  [cascade | restrict]] [drop constraint  [cascade | restrict]] [rename column  to ] [alter column  type ]分析:① :要修改的基本表② add 子句用于增加新列、新的列级完整性约束和新的表级完整性约束。③ drop column 子句用于删除表中的列,如果指定了CASCADE 短语,则自动删除引用了该列的其他对象,比如视图;如果指定了RESTRICT 短语,则如果该列被其他对象引用,关系数据库管理系统将拒绝删除该列。④ drop constraint 子句用于删除指定的完整性约束。⑤ rename column 子句用于修改列名。⑥ alter column 子句用于修改列的数据类型。

  2. 修改数据类型

    ALTER TABLE 表名 MODIFY 字段名 新数据类型(长度);
  3. 修改字段名 和 字段类型

    ALTER TABLE 表名 CHANFGE 旧字段名 新字段名 类型(长度)[comment 注释] [约束]

注意:无论 基本表中是否 已有数据,新增加的一列均为空值

4. MySQL 增删改查(DML & DQL)

4.1 数据更新(DML)

4.1.1 插入数据
insert into  values(, ...);
  • 指定列插入:insert into 表名(列名, 列名...)values(值,值...); 

 此时我们只插入 name,id 这一列就会被填充为默认值(此处默认值为null)

  • 我们还可以一次插入多行记录~~  insert into 表名 values(值, 值...), (值, 值...);

注:上面使用到的 \' \',可以用来表示字符串,或者用 \" \",SQL没有 “字符” 这个类型。

  • 小知识:(datetime 类型的插入)

若我们插入时间要是当前时刻

insert into student2 select * from student1;

  • 插入查询结果

这个用到了下面我们会讲到的查询,查询搭配插入使用,把查询语句的查询结果,作为插入的数值。如将 student1 的查询结果插入到 student2 中。

insert into student2 select * from student1;

注:此处要求查询出来的结果集合, 列数/类型 要和插入的这个表 匹配

4.1.2 修改数据
update  set  =  where ];

案例:

注:修改NULL数据时,如下:

明明我们有英语成绩为NULL的情况,但是仍然没有匹配到,原因是为什么呢?

在修改列允许Null时,可能会涉及到已存在的数据。如果列属性从不允许Null变为允许Null,可能需要处理现有数据以确保数据的一致性和完整性。

以下是常见的处理的方法:

4.1.3 删除数据
delete from 表名 where 条件 / order by /limit;

4.2 数据库约束

4.2.1 约束类型
  • NOT NULL - 指示某列不能存储 NULL 值。
  • UNIQUE - 保证某列的每行必须有唯一的值。
  • DEFAULT - 规定没有给列赋值时的默认值。
  • PRIMARY KEY - NOT NULL 和 UNIQUE 的结合。确保某列(或两个列多个列的结合)有唯一标识,有助于更容易更快速地找到表中的一个特定的记录。
    注:一张表里只能有一个 primary key.
  • FOREIGN KEY - 保证一个表中的数据匹配另一个表中的值的参照完整性。
  • CHECK - 保证列中的值符合指定的条件。对于MySQL数据库,对CHECK子句进行分析,但是忽略CHECK子句。
4.2.2 NULL 约束

创建表时,可以指定某列不为空:

4.2.3 UNIQUE:唯一约束

指定id列为唯一的、不重复的:

4.2.4 DEFAULT:默认值约束

指定插入数据时,name列为空,默认值为未命名:

4.2.5 PRIMARY KEY:主键约束
  • 主键,是表中一列或者多列的组合
  • 主键约束( Primary Key Constraint )要求主键列的数据唯一,并且不允许为空。
  • 主键能够唯一的标识表中的每一条记录,可以结合外键,来定义与不同数据表之间的关系。

怎么理解主键呢?我们知道数据库中的表可以存放很多数据,如果把表中的每一条数据比作一个人的话,那么表的主键就可以看做是人的身份证。

有两种方式可以添加主键约束:

  1. 在定义列的同时指定主键
  2. 在定义完字段之后,再指定主键

注:一张表只能有且仅有一个主键

小知识:主键自动生成索引

4.2.6 FOREIGN KEY:外键约束

外部关键字
在以后,我们统一将外部关键字叫做外键,外键就是另一张表中的主键。

问:外键有啥用啊?
答:外键的主要作用就是保持数据的一致性,完整性。

如图有两张表,classId 是 T_Student 的外键,同时是 T_class 表的主键。如果我们要删除 T_class 表中 classId 为 1 的字段,程序是会报错的。因为 T_Student 表中有数据和 classId 为 1 的字段关联了,是不能删除的,这样子就保证了数据的一致性和完整性。

问:那怎么才能删除呢?
答:需要先删除 T_Student 表中 classId 为 1 的两个字段。

外键用于关联其他表的主键或唯一键

 案例:

对学生表进行数据插入:

注:当我们想删除父表时,则需要先删除 子表,再删除 父表。

  • 指定外界约束时,要求父表这一列,得是主键或者 unique,范例:

4.3 查询(DQL)

  1. SELECT 字段列表
  2. FROM 表名列表
  3. WHERE 条件列表
  4. GROUP  BY 分组字段列表
  5. HAVIJNG 分组后条件列表
  6. ORDER BY 排序字段列表
  7. LIMIT 分页参数

执行顺序:②③④⑤①⑥⑦

select[all | distinct] [别名][, [别名]] ...from [别名][, [别名]] ... | (语句) [as][where ][group by [having 条件表达式>]][order by [asc | desc]][limit [offset ]]

在查询前,我们先创建一个表。

mysql > --创建学生成绩表mysql > create table student(id int, name varchar(20), math decimal(3, 1), english decimal(3, 1);mysql > --插入测试数据insert into student(id, name, math, english) values(1, \'张三\', 78, 90),(2, \'李四\', 78, 45),(3, \'王五\', 67.9, 45.6),(4, \'赵六\', NULL, 67.7),(5, \'孙行者\', 76.8, 90.0),(6, \'者行孙\', 80.4, 67.3);

 4.2.1 基本查询:SELECT
  • 全列查询
 select * from 表名; // 把表中所有行所有列都查询出来

注:其中上面的 * 是通配符,可以代指所有列

  • 指定列查询  select 列名, 列名... from 表名;

  • 查询字段为表达式 (一边查询,一边计算)

在查询的时候,写作由列名构成的表达式,把这一列的所有行都带入到表达式中

注:但是原始数据不变,这个只是产生的临时数据。因此我们可以发现,查询的时候,是把服务器这里的数据读出来,返回给客户端,并且以临时表的形式进行展示。

SQL 查询的时候可以进行一些简单的统计操作,表达式查询吗,是列和列之间的运算,把每一行都带入到这样的运算中。

  • 查询时指定别名

查询的时候给 列 / 表达式 指定别名(给表也能指定别名)

select 表达式 as 别名 from 表名;

  • 去重查询

distinct 修饰某个列 / 多个列,值相同的行只保留一个。

 注: 其中 单独的distinct只能放在开头,否则报错,语法错误

4.2.2 排序查询:ORDER BY

查询的时候进行排序,把行进行排序

注:需要明确排序规则~~

  1. 针对哪个列作为比较规则
  2. 排序的时候式升序还是降序
SELECT 列名 FROM 表名 ORDER BY 列名 ASC/DESC; // asc 升序,desc 降序

如果一个 sql 不加 order by 此时查询的结果数据的顺序是: “不确定的” / “无序”

注:其可以按照表达式进行排序,还可以多个列进行排序。比如数学成绩相同时,再按照语文顺序排序。

4.2.3 条件查询:WHERE

会指定具体的条件,按照条件针对数据进行筛选

SELECT 列名 FROM 表名 WHERE 条件

原理如下:遍历这个表每一行记录,把每一行的数据分别带入到条件中,如果条件成立,这个记录就会被放入结果集合中,不成立,这个记录就 pass

比较运算符:

运算符 说明

>, >=, <, <=

大于,大于等于,小于,小于等于 = 等于,NULL 不安全,例如 NULL = NULL 的结果是 NULL 等于,NULL 安全,例如 NULL NULL 的结果是 TRUE(1) !=, 不等于 between a0 and a1 范围匹配,[a0, a1],如果a0 <= value <= a1,返回true in(option, ...) 如果是 option 中的任意一个,返回 TRUE(1) Is NULL 是NULL Is  Not NULL 不是NULL LIKE

模糊匹配。 

% 表示任意多个(包括 0 个)任意字符

_ 表示任意一个字符

逻辑运算符:

运算符 说明 AND 多个条件必须都为 TRUE(1),结果才是 TRUE(1) OR 任意一个条件为 TRUE(1), 结果为 TRUE(1) NOT 条件为 TRUE(1),结果为 FALSE(0)

注:

  1. WHERE条件可以使用表达式,但不能使用别名。
  2. AND的优先级高于OR,在同时使用时,需要使用小括号()包裹优先执行的部分

案例:

Like 模糊匹配

在模糊匹配前,为了让数据显示更加明显,我们加入几行数据。

insert into student(id, name, math, english) values(7, \'行孙者\',67, 90),(8, \'孙明\', 83, 45),(9, \'孙\', NULL, NULL);

显示结果:

4.2.4 分页查询:LIMIT

由于使用select * 这种方式查询,比较危险,需要保证一次查询,不要查出来的东西太多~~

因此 MYSQL 就使用limit 来限制这次查询最多查出来多少个结果。

select 查询列 from 表名 limit N offset M // N 表示这次最多查出几条记录// M 表示这次查询的 N 条记录, 从第几个下标开始(默认下标从 0 开始)

4.2.5 聚合查询
① 聚合函数

🍅常见的统计总数、计算平局值等操作,可以使用聚合函数来实现,常见的聚合函数有:

函数 说明 COUNT([DISTINCT] expr) 返回查询到的数据的 数量 SUM([DISTINCT] expr) 返回查询到的数据的 总和,不是数字没有意义 AVG([DISTINCT] expr) 返回查询到的数据的 平均值,不是数字没有意义 MAX([DISTINCT] expr) 返回查询到的数据的 最大值,不是数字没有意义 MIN([DISTINCT] expr) 返回查询到的数据的 最小值,不是数字没有意义

案例:(下面是使用的 count)

注:如果当前列 存在 NULL数据,则查询特定列时就不会计算 NULL数据,而直接 select(*) 就会计算所有行。

② 分组 GROUP BY 子句

🍅SELECT 中使用 GROUP BY 子句可以对指定列进行分组查询。需要满足:使用 GROUP BY 进行分组查询时,SELECT 指定的字段必须是“分组依据字段”,其他字段若想出现在SELECT 中则必须包含在聚合函数中。

select column1, sum(column2), .. from table group by column1,column3;

案例:

③ HAVING

🍅GROUP BY 子句进行分组以后,需要对分组结果再进行条件过滤时,不能使用 WHERE 语句,而需要用HAVING

4.2.6 联合查询
① 内连接

📒内连接是最常用的联接类型,它返回两个表中匹配的记录。若表中某些记录在另一个表中没有匹配的记录,这些记录将不会出现在结果集中。

SELECT columns FROM table1 INNER JOIN table2 ON table1.column = table2.column;

上面的意思就是查找 表1中 位于 表2 相同的列

 示例:

假设有两个表 employeesdepartments,分别存储员工和部门的信息:

-- employees 表+----+---------+-------------+| id | name | department_id |+----+---------+-------------+| 1 | Alice | 1  || 2 | Bob | 2  || 3 | Charlie | NULL |+----+---------+-------------+-- departments 表+----+-----------+| id | department|+----+-----------+| 1 | HR || 2 | IT |+----+-----------+

使用内连接查询所有员工及其对应的部门名称:

select employees.name, departments.department from employees inner join departments on employees.department_id = departments.id;结果:+---------+-------------+| name | department |+---------+-------------+| Alice | HR || Bob | IT |+---------+-------------+
② 外连接

左外连接 (LEFT JOIN)

📙左连接返回左表中的所有记录以及右表中匹配的记录。如果右表中没有匹配的记录,则结果集中的右表列将包含 NULL

SELECT columns FROM table1 LEFT JOIN table2 ON table1.column = table2.column;

案例:

使用左连接查询所有员工及其部门(即使某些员工没有部门):

select employees.name, departments.department from employees left join departments on employees.department_id = departments.id;结果显示:+---------+-------------+| name | department |+---------+-------------+| Alice | HR || Bob | IT || NULL | Sales |+---------+-------------+

 右外连接 (RIGHT JOIN)

📕右连接与左连接相反,它返回右表中的所有记录以及左表中匹配的记录。如果左表中没有匹配的记录,则结果集中的左表列将包含 NULL。

SELECT columns FROM table1 LEFT JOIN table2 ON table1.column = table2.column;

案例:

select employees.name, departments.department from employees right join departments on employees.department_id = departments.id;结果显示:+---------+-------------+| name | department |+---------+-------------+| Alice | HR || Bob | IT || NULL | Sales |+---------+-------------+

全外连接(FULL OUTER JOIN)

📜MySQL 5.7 及更早版本不支持全外连接(FULL OUTER JOIN)。要实现全外连接的效果,可以通过结合使用左连接和右连接并排除重复记录来模拟。

(select employees.name, departments.departmentfrom employeesleft join departments on employees.department_id = departments.id)UNION -- 用到了下面的合并查询内容(select employees.name, departments.departmentfrom employeesright join departments on employees.department_id = departments.id);-- 结果显示+---------+------------+| name | department |+---------+------------+| Alice | HR || Bob | IT || Charlie | NULL |+---------+------------+
③ 自连接

自连接是将表与其自身进行联接,通常用于查找表中某个记录与其他记录的关系。

SELECT a.columns, b.columns FROM table a JOIN table b ON a.column = b.column;

 注:不能直接自连接,一般采取取别名的方式。

案例:

select * from employees as e1, employees as e2 where e1.id = e2.department_id;+------+-------+---------------+------+-------+---------------+| id | name | department_id | id | name | department_id |+------+-------+---------------+------+-------+---------------+| 1 | Alice | 1 | 1 | Alice | 1 || 2 | Bob | 2 | 2 | Bob | 2 |+------+-------+---------------+------+-------+---------------+
④ 子查询

子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询

  1. 单行子查询:返回一行记录的子查询
  2. 多行子查询:返回多行记录的子查询
-- 错误范例select name from employeeswhere department_id = (select department_id from employees where id = department_id);ERROR 1242 (21000) : Subquery returns more than 1 row-- 正确范例-- 单行子查询select name from employeeswhere department_id = (select department_id from employees where id = 1);+------ - +| name |+------ - +| Alice |+------ - +-- 多行子查询select employees.id, employees.name, departments.department from employees, departmentswhere employees.id = departments.id;+------+-------+------------+| id | name | department |+------+-------+------------+| 1 | Alice | HR || 2 | Bob | IT |+------+-------+------------+
⑤ 合并查询
-- 错误范例select id, name from employees where id < 3union select department from departments;ERROR 1222 (21000) : The used SELECT statements have a different number of columns -- 由上可知:合并的两个sql 的结果集的列,需要匹配,列的个数和类型也需要一致,类名不用一致-- 正确范例select name from employees where id < 3union select department from departments;-- 结果显示:+-------+| name |+-------+| Alice || Bob || HR || IT |+-------+
4.2.7 嵌套查询

🐸 在 SQL 中,一个 select -from - where 语句称为一个查询块,将一个查询块嵌套在另一个查询块的 where 子句 或 having 短句的条件中的查询称为 嵌套查询(nested query)

假设有以下三张表

// student 表+-------+-------+------+------+-------+| sno | sname | ssex | sage | sdept |+-------+-------+------+------+-------+| 95001 | 李勇 | 男 | 20 | CS || 95002 | 刘晨 | 女 | 19 | IS || 95003 | 王敏 | 女 | 18 | MA || 95004 | 张立 | 男 | 19 | IS || 95005 | 刘云 | 女 | 18 | CS |+-------+-------+------+------+-------+
① 带有 IN 谓词的子查询

比如:要查询与 \'刘晨\' 同一个性别的学生学号、姓名和主修专业 

// 方法一:分布完成select ssex from student where sname = \'刘晨\'; //结果为女select * from student where ssex = \'女\';// 方法二:嵌套查询select * from student where ssex in(select ssex from student where sname =\'刘晨\');
② 带有比较运算符的子查询

🦌 带有比较运算符的子查询是指 父查询和子查询之间用比较运算符之间进行连接。当用户能确切知道内层查询返回的是单个值时候,可以用 >、 =、<=、!=、等

比如在之前,由于一个学生只有一个性别,也就是说 内查询是一个值,因此可以用 \'=\' 代替 \'in\'

select * from student where ssex =(select ssex from student where sname =\'刘晨\');
③ 带有 ANY(SOME) 或 ALL 谓词的子查询

子查询返回单值的时候可以用比较运算符,但返回多值的时候要用 ANY(有的系统用 SOME)或 ALL 谓词修饰符,但是使用 ANY 或 ALL 谓词时候必须同时使用比较运算符。语义如下:

语句 作用 > ANY 大于子查询结果中的某个值 > ALL 大于子查询结果中的所有值 < ANY 小于子查询结果中的某个值

< ALL

小于子查询结果中的所有值 >= ANY 大于或等于子查询结果中的某个值 >= ALL 大于或等于子查询结果中的所有值 <= ANY 小于或等于子查询结果中的某个值 <= ALL 小于或等于子查询结果中的所有值 =ANY 等于子查询结果中的某个值 =ALL 等于子查询结果中的所有值(通常没啥意义,用 in 代替) != (或 )ANY 不等于子查询结果中的某个值 != (或 )ALL 不等于子查询结果中的任何一个值

查询男生中比女生中任意一个年龄大的学生所有信息

select * from student where sage>any(select sage from student where ssex=\'女\')and ssex  \'女\'; # 注意这是父查询块条件# 结果如下:+-------+-------+------+------+-------+| sno | sname | ssex | sage | sdept |+-------+-------+------+------+-------+| 95001 | 李勇 | 男 | 20 | CS || 95004 | 张立 | 男 | 19 | IS |+-------+-------+------+------+-------+# 如果不加那句话,则是select * from student where sage>any(select sage from student where ssex=\'女\');+-------+-------+------+------+-------+| sno | sname | ssex | sage | sdept |+-------+-------+------+------+-------+| 95001 | 李勇 | 男 | 20 | CS || 95002 | 刘晨 | 女 | 19 | IS || 95004 | 张立 | 男 | 19 | IS |+-------+-------+------+------+-------+
④ 带有 EXISTS 谓词的子查询

 带有 EXISTS 谓词的子查询不返回任何数据,只产生逻辑真/假值

select sname from student where exists (select * from student where ssex=\'女\');+-------+| sname |+-------+| 李勇 || 刘晨 || 王敏 || 张立 || 刘云 |+-------+// 上面的有问题,需要用别名select sname from student s1 where exists(select * from student s2 where s2.ssex=\'女\' and s1.ssex=s2.ssex);+-------+| sname |+-------+| 刘晨 || 王敏 || 刘云 |+-------+

注意:由 EXISTS 引出的子查询,其目标列表表达式通常都用 *,因为带有 EXISTS 的子查询只返回真值/假值,给出列名无实际意义

4.2.8 集合查询

select 语句的查询结果是元组的集合,所以对多个 SELECT 语句的结果可进行集合操作,集合操作主要包括 并操作(UNION)、交操作(INTERSECT)和 差操作(EXCEPT)

演示如下:

# student 表+-------+-------+------+------+-------+| sno | sname | ssex | sage | sdept |+-------+-------+------+------+-------+| 95001 | 李勇 | 男 | 20 | CS || 95002 | 刘晨 | 女 | 19 | IS || 95003 | 王敏 | 女 | 18 | MA || 95004 | 张立 | 男 | 19 | IS || 95005 | 刘云 | 女 | 18 | CS |+-------+-------+------+------+-------+5 rows in set (0.01 sec)# course 表+-----+-------------+--------+------+| cno | cname | credit | pcno |+-----+-------------+--------+------+| 1 | 数据库 | 4 | 5 || 2 | 数学 | 6 | NULL || 3 | 信息系统 | 3 | 1 || 4 | 操作系统 | 4 | 6 || 5 | 数据结构 | 4 | 7 || 6 | 数据处理 | 3 | NULL || 7 | PASCAL 语言 | 4 | 6 |+-----+-------------+--------+------+

操作如下:

# 查询性别为女生以及年龄小于19岁的学生select * from student where ssex=\'女\' UNIONselect * from student where sage<19;+-------+-------+------+------+-------+| sno | sname | ssex | sage | sdept |+-------+-------+------+------+-------+| 95002 | 刘晨 | 女 | 19 | IS || 95003 | 王敏 | 女 | 18 | MA || 95005 | 刘云 | 女 | 18 | CS |+-------+-------+------+------+-------+# 查询性别为女生与年龄小于19岁的学生的交集select * from student where ssex=\'女\' INTERSECTselect * from student where sage<19;+-------+-------+------+------+-------+| sno | sname | ssex | sage | sdept |+-------+-------+------+------+-------+| 95003 | 王敏 | 女 | 18 | MA || 95005 | 刘云 | 女 | 18 | CS |+-------+-------+------+------+-------+# 查询性别为女生与年龄小于19岁的学生的差集select * from student where ssex=\'女\' EXCEPTselect * from student where sage<19;+-------+-------+------+------+-------+| sno | sname | ssex | sage | sdept |+-------+-------+------+------+-------+| 95002 | 刘晨 | 女 | 19 | IS |+-------+-------+------+------+-------+

6. 数据库用户(DCL)

6.1 用户操作

(1)登录MySQL 主机

mysql -u root -p

(2)查询已存在用户

SELECT USER, HOST FROM MYSQL.user;

(3)创建用户

CREATE USER \'用户名\'@\'主机名\' IDENTIFIED BY \'密码\';

(4)修改用户

ALTER USER \'用户名\'@\'主机名\' IDENTIFIED WITH mysql_native_password BY \'新密码\';

(5)删除用户

DROP USER \'用户名\'@\'主机名\';

 案例:

-- 登录 MySQL 服务器mysql - u 用户名 - p-- 查看已存在用户select user, host from mysql.user;+------------------+-----------+| user | host |+------------------+-----------+| mysql.infoschema | localhost || mysql.session | localhost || mysql.sys | localhost || root | localhost |+------------------+-----------+-- 创建用户 s1, 只能在当前主机 比如我当前主机是 localhost 下访问,密码123456;create user \'s1\'@\'localhost\' identified by \'123456\';-- 创建用户 s2,可以在任意主机访问数据库,密码123456create user \'s2\'@\'%\' identified by \'123456\';-- 修改用户 s2 的访问密码为1234alter user \'s2\'@\'localhost\' identified by mysql_native_password by \'1234\';-- 删除用户drop user \'s1\'@\'localhost\';-- 退出 MySQL 服务器exit;-- 注:主机名可以使用 % 进行通配-- 获取当前MySQL的主机名select @@hostname;

 6.2 用户权限

(1)查询权限

SHOW GRANTS FOR \'用户名\'@\'主机名\';

(2)授予权限

GRANT 权限列表 ON 数据库名.表名 TO \'用户名\'@\'主机名\';

(3)撤销权限

REVOKE 权限列表 ON 数据库名.表名 FROM \'用户名\'@\'主机名\';

案例:

-- 查询 s2 的权限show grants for \'s2\'@\'%\';-- 查询显示+--------------------------------+| Grants for s2@% |+--------------------------------+| GRANT USAGE ON *.* TO `s2`@`%` |+--------------------------------+-- 授予 s2 权限数据库 student 上表的所有权限grant all on student.* to \'s2\'@\'%\';-- 查询显示+-------------------------------------------------+| Grants for s2@%  |+-------------------------------------------------+| GRANT USAGE ON *.* TO `s2`@`%`  || GRANT ALL PRIVILEGES ON `student`.* TO `s2`@`%` |+-------------------------------------------------+-- 撤销 s2 权限数据库 student 上表的所有权限revoke all on student.* from \'s2\'@\'%\';-- 查询显示+--------------------------------+| Grants for s2@% |+--------------------------------+| GRANT USAGE ON *.* TO `s2`@`%` |+--------------------------------+

7. 索引

7.1 概念

索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引,并指定索引的类型,各类索引有各自的数据结构实现

7.2 作用

1. 加速数据查询

索引可以显著提高数据检索的速度。没有索引的表需要扫描整个表来找到匹配的记录,这在表数据量大时会非常慢。而有索引的表可以通过索引快速定位到相关记录,从而减少了需要扫描的数据量。

2. 加速排序和过滤操作

索引不仅可以加速数据的检索,还可以优化排序操作(例如,ORDER BY)和过滤操作(例如,WHERE 子句)。当查询包含排序或过滤条件时,索引可以帮助 MySQL 更高效地处理这些操作。

3. 提高查询性能

对于频繁使用的查询条件或连接条件,创建索引可以极大地提高这些查询的性能。例如,基于外键的索引可以加速表之间的联接操作。

4. 避免全表扫描

使用索引后,MySQL 可以避免对整个表进行全表扫描,这可以显著减少查询的时间,尤其是在数据量非常大的情况下。

5. 唯一性约束

索引可以强制唯一性约束。通过创建唯一索引,数据库可以确保索引列中的所有值都是唯一的,这有助于保证数据的完整性。

6. 提高数据完整性

在某些情况下,索引还可以提高数据的完整性。例如,主键索引可以确保表中的每一行都具有唯一的标识符,从而避免重复数据的插入

7.3 如何使用

主要的索引类型

  1. 主键索引(PRIMARY KEY): 主键索引是一种特殊的唯一索引,用于唯一标识表中的每一行。一个表只能有一个主键索引,主键字段的值必须唯一且不能为空。

  2. 唯一索引(UNIQUE): 唯一索引确保索引列中的每个值都是唯一的,可以有多个唯一索引。与主键索引不同,唯一索引的列可以允许空值(NULL)。

  3. 普通索引(INDEX): 普通索引是最常用的索引类型,用于加速数据检索,不强制列值的唯一性。

  4. 全文索引(FULLTEXT): 全文索引用于加速对文本字段的全文检索,如查找包含特定单词的记录。它适用于大量文本数据的搜索。

  5. 复合索引(COMPOSITE): 复合索引是一个索引包含多个列,用于加速基于多个列的查询操作。

注:主键,unique ,外键都会自动生成索引.

(1)查看索引
show index from 表名
(2)创建索引

对于非主键、非唯一约束、非外键的字段,可以创建普通索引

create [unique] [cluster] index  on  ( [][, ][]]...);

 示例:(下述table_name 指表名,column_name指列名)

-- 创建一个普通索引CREATE INDEX idx_name ON table_name (column_name);-- 创建一个唯一索引CREATE UNIQUE INDEX idx_unique_name ON table_name (column_name);-- 创建一个复合索引CREATE INDEX idx_composite ON table_name (column1, column2);-- 创建一个全文索引CREATE FULLTEXT INDEX idx_fulltext ON table_name (text_column);
(3)删除索引
drop index  on 

注:手动创建的索引可以手动删除,但如果是自动创建的索引(主键/外键,unique),无法被删除!!!

(4)修改索引
alter index  rename to 

7.4 使用场景及注意事项

要考虑对数据库表的某列或某几列创建索引,需要考虑以下几点:

  • 数据量较大,且经常对这些列进行条件查询。
  • 该数据库表的插入操作,及对这些列的修改操作频率较低。
  • 索引会占用额外的磁盘空间。

满足以上条件时,考虑对表中的这些字段创建索引,以提高查询效率。
反之,如果非条件查询列,或经常做插入、修改操作,或磁盘空间不足时,不考虑创建索引。

注意事项

  • 索引会占用空间:索引会占用额外的磁盘空间,尤其是在大型表中,索引的空间开销可能会很大。
  • 更新性能:虽然索引能提高查询速度,但插入、更新和删除操作可能会变得较慢,因为每次数据修改时,索引也需要被更新。
  • 选择性:索引对于具有高选择性的列(即列中唯一值较多)效果更好。例如,性别字段的选择性低(仅有“男”和“女”),而身份证号的选择性高(每个身份证号唯一)。

8. 函数类型(扩展)

8.1 字符串函数

函数 功能 COUNCAT(S1,S2..Sn) 字符串拼接,将S1,S2,...Sn 拼接成一个字符串 LOWER(str) 将字符串 str 全部转为小写 UPPER(str) 将字符串 str 全部转为大写 LPAD(str, n, pad) 左填充,用字符串pad 对 str 的左边进行填充,达到 n 个字符串长度。 RPAD(str, n, pad) 右填充,用字符串pad 对 str 的左边进行填充,达到 n 个字符串长度。 TRIM(str) 去掉字符串头部 和 尾部的空格 SUBSTRING(str, start, len) 返回从字符串 str 从 start 位置起的 len 个长度的字符串。

案例:

-- 输入select concat(upper(\'i\'), lpad(\'Never\',6,\'-\'), trim(\' -Love \'), substring(\'--You\',2,5));-- 输出+----------------------------------------------------------------------------------+| concat(upper(\'i\'), lpad(\'Never\',6,\'-\'), trim(\' -Love \'), substring(\'--You\',1,5)) |+----------------------------------------------------------------------------------+| I-Never-Love-You  |+----------------------------------------------------------------------------------+1 row in set (0.00 sec)

下面函数的使用也和上面使用类似,我们就不一一举例了。

8.2 数值函数

函数 功能 CEIL(x) 向上取整 FLOOR(x) 向下取整 MOD(x)

返回 x / y 的模

RAND() 返回 0 ~ 1 内的随机数 ROUND(x, y) 求参数 x 的四舍五入的值,保留 y 位小数

8.3 日期函数

函数 功能 CURDATE() 返回当前日期 CURTIME() 返回当前时间 NOW() 返回当前日期和时间 YEAR(date) 获取指定 date 的年份 MONTH(date) 获取指定 date 的月份 DAY(date) 获取指定 date 的日期 DATE_ADD(date, INTERVAL expr type) 返回一个日期/时间值 加上一个时间间隔 expr 后的时间值  DATEDIFF(date1, date2) 返回起始时间 date1 和 结束时间 date2 之间的天数

8.4 流程函数

函数 功能 IF(value, t, f)

如果 value 为 true,则返回 t,否则返回 f

IFNULL(value1, value2) 如果 value1 不为空,返回 value1,否则返回 value2 CASE WHEN [val1] THEN [res1] .. ELSE [default] END 如果 val1 为 true,返回 res1,.. 否则返回 default 默认值 CASE  [expr] WHEN [val1] THEN [res1] .. ELSE [default] END 如果 expr 的值等于 val1,返回 res1,..否则返回 default 的默认值

9. 补充

9.1 模式定义与删除

  • 定义模式
create schema [] Authorization 

如果没有指定,那么 就隐含为

注意:要创建新模式,调用该命令的用户必须拥有数据库管理员(DBA) 权限,或者获得了 DBA 授予的 CREATE SCHEMA  权限

案例如下:

// 1. 为用户 Wang 定义一个 ‘学生选课模式’ S-C-SCcreate schema \'S-C-SC\' authorization Wang;// 2. 未指定模式名的模式示例create schema authorization Wang;

🦌 定义模式实际上定义了一个命名空间,再这个空间中可以进一步命名该模式包含的数据对象,如 基本表、视图、索引 等

目前,在 Create schema 中可以接收 CREATE table,Create view 和 Grant 子句,也就是说,用户可以在创建模式的同时在该模式定义中进一步创建 基本表、视图、定义授权

  • 删除模式
drop schema   

注意: Cascade  和 Restrict 两个必须其一删除

  • Cascade(级联):表示把该模式以及该模式下的所有库对象全部删除
  • RESTRICT(限制): 表示该模式中已经定义了数据库对象,该模式拒绝语句指向,只有当该模式没有任何数据库对象时 才能执行 DROP SCHEMA 语句

9.2 视图

💢 视图是关系数据库系统提供给用户以多种角度观察数据库中数据的重要机制。

  • 视图是从一个或几个基本表(或视图)导出的表
  • 它与基本表不同,是一个虚表
  • 数据库中只存放视图的定义,而不存放视图对应的数据,这些数据仍存放在原来的基本表中
  • 一旦基本表中的数据发生变化,从视图中查询出的数据也就随之改变了
  • 从这个意义上讲,视图就像一个窗口,透过它可以看到数据库中自己感兴趣的数据及其变化

视图一经定义,就可以和基本表一样被查询、被删除。也可以在一个视图之上再定义新的
视图,但对视图的更新(增、删、改)操作则有一定的限制

9.2.1 定义视图
(1)建立视图
create view  [([, ]...)]AS [WITH CHECK OPTION]
  • 其中,子查询可以是任意的SELECT语句,是否包含ORDER BY子句和 DISTINCT短语取决于具体系统的实现
  • WITH CHECK OPTION:表示对视图进行UPDATE INSERTDELETE 操作时,要保证更新、插入或删除的行满足视图定义中的谓词条件(即子查询中的条件表达式)
  • 组成视图的属性列名或者全部省略,或者全部指定,没有第三种选择。如果省略了视图的各个属性列名,则隐含该视图由子查询中 SELECT 子句目标列中的诸字段组成。

注意:在下列三种情况下必须明确指定组成视图的所有列名

  • ① 某个目标列不是单纯的属性名,而是聚集函数或列表达式
  • ② 多表连接时选出了几个同名列作为视图的字段
  • ③ 需要在视图中为某个列启用新的更合适的名字

比如:有这样一张学生表

+-------+-------+------+------+-------+| sno | sname | ssex | sage | sdept |+-------+-------+------+------+-------+| 95001 | 李勇 | 男 | 20 | CS || 95002 | 刘晨 | 女 | 19 | IS || 95003 | 王敏 | 女 | 18 | MA || 95004 | 张立 | 男 | 19 | IS || 95005 | 刘云 | 女 | 18 | CS |+-------+-------+------+------+-------+
  • 建立性别为女生的视图
# 这里指定了列名,如果省略,就隐含为 子查询中 select 子句的列名create view F_Student(Fno, Fname, Fsex, Fage, Fdept) as select * from student where ssex=\'女\'with check option;
  • 由于在定义上面视图时,加上了 WITH CHECK OPTION 子句,以后对该视图进行插入、删除、修改操作时,会自动检查 ssex=\'女\' 的条件,比如:
# 插入性别为男 -- 失败insert into F_Student values(\'95006\', \'千\', \'男\', 23, \'IS\');ERROR 1369 (HY000): CHECK OPTION failed \'xsgl.f_student\'# 插入性别为女 -- 成功insert into F_Student values(\'95006\', \'千\', \'女\', 23, \'IS\');Query OK, 1 row affected (0.01 sec)

注意:这里 视图 是由 子查询 SELECT * 建立的,F_Student 视图的属性列和 Student 表的属性列意义对应,如果以后修改了基本表 Student 的结构,则Student 表与F_Student 视图的映像关系可能会被破坏,该视图就不能正常工作了。

  • 因此为避免出现这类问题,最好在修改基本表之后删除由该基本表导出的视图,然后重建这个视图。

补充:

  1. 视图可以建立在单个基本表上,还可以建立在多个基本表上
  2. 视图可以建立在一个或多个已经定义好的视图上
  3. 视图可以建立在基本表和视图上
(2)删除视图
DROP VIEW[CASCADE];

视图删除后视图的定义将从数据字典中删除。如果该视图上还导出了其他视图,则使用CASCADE 级联删除语句把该视图和由它导出的所有视图一起删除。

# 假如有三个视图,F, S1, S2, 且 S2 是从 S1 视图导出的drop view F; # 删除成功drop view S1; # 删除失败# 因为 S1 上还导出来 S2 视图,如果要删除需要drop view S1 cascade; # 删除成功

注意:(基本表删除不代表视图没了)

  • 基本表删除后,由该基本表导出的所有视图均无法使用了,但是视图的定义没有从字典中清除。
  • 删除这些视图定义需要显式地使用DROP VIEW语句
9.2.2 查询视图 
# 查看视图 select * from F_Student;+-------+-------+------+------+-------+| Fno | Fname | Fsex | Fage | Fdept |+-------+-------+------+------+-------+| 95002 | 刘晨 | 女 | 19 | IS || 95003 | 王敏 | 女 | 18 | MA || 95005 | 刘云 | 女 | 18 | CS || 95006 | 千 | 女 | 23 | IS |+-------+-------+------+------+-------+# 查看表,发现表和视图数据是同步的select * from Student;+-------+-------+------+------+-------+| sno | sname | ssex | sage | sdept |+-------+-------+------+------+-------+| 95001 | 李勇 | 男 | 20 | CS || 95002 | 刘晨 | 女 | 19 | IS || 95003 | 王敏 | 女 | 18 | MA || 95004 | 张立 | 男 | 19 | IS || 95005 | 刘云 | 女 | 18 | CS || 95006 | 千 | 女 | 23 | IS |+-------+-------+------+------+-------+

视图消解(view resolution)

  • 关系数据库管理系统执行对视图的查询时,首先进行有效性检查,检查查询中涉及的表、视图等是否存在。
  • 如果存在,则从数据字典中取出视图的定义,把定义中的子查询和用户的查询结合起来,转换成等价的对基本表的查询,然后再执行修正了的查询。这一转换过程就称为视图消解

比如上面 F_Student 的学生信息查询,进行视图消解后的语句如下:

select * from Student where ssex = \'女\';

注意:定义视图后对视图进行查询与基于派生表的查询是有区别的。

  1. 视图一旦定义,该定义将保存在数据字典中,之后的所有查询都可以直接引用该视图
  2. 而派生表只是在语句执行时临时定义,语句执行后该派生表定义即被删除
9.2.3 更新视图

🐍 更新视图是指通过视图来插入、删除和修改数据。由于视图是不实际存储数据的虚表,因此对视图的更新最终要转换为对基本表的更新。像查询视图那样,对视图的更新操作也是通过视图消解,转换为对基本表的更新操作。

为防止用户通过视图对数据进行更新操作时,有意无意地对不属于视图范围内的基本表数据进行操作,可在定义视图时加上【WITH CHECK OPTION子句

  • 这样在视图上更新数据时,关系数据库管理系统会检查视图定义中的条件,若不满足条件则拒绝执行该操作。
insert into F_Student values(\'95006\', \'千\', \'女\', 23, \'IS\');-- 视图消解insert into Student(Sno, Sname, Ssex, Sage, Sdept)values(\'95006\', \'千\', \'女\', 23, \'IS\');

注意:一般的,行列子集视图是可更新的。除行列子集视图时,有些视图理论上是可更新的,有些视图理论上不可以更新

9.2.4 视图作用

🔥 视图最终是定义在基本表之上的,对视图的一切操作最终也要转换为对基本表的操作,而且对于非行列子集视图进行查询或更新时还有可能出现问题。既然如此,为什么还要定义视图呢?

  • 这是因为合理使用视图能够带来许多好处,所以在实际应用开发中经常使用视图。

(1)视图能够对机密数据提供安全保护

  • 有了视图机制,就可以在设计数据库应用系统时对不同的用户定义不同的视图,使机密数据不出现在不应看到这些数据的用户视图上。这样视图机制就自动提供了对机密数据的安全保护功能

例如:Student表涉及全校30个院系的学生数据,可以在其上定义30个视图,每个视图只包含一个院系的学生数据,并只允许每个院系的主任查询和修改本院系的学生视图

(2)视图对重构数据库提供了一定程度的逻辑独立性

数据的物理独立性与逻辑独立性的概念

  1. 数据的物理独立性是指用户的应用程序不依赖于数据库的物理结构。
  2. 数据的逻辑独立性是指当数据库重构时,如增加新的关系或对原有关系增加新的字段等,用户的应用程序不会受影响。
  3. 层次数据库和网状数据库一般能较好地支持数据的物理独立性,而对于逻辑独立性则不能完全地支持。

在关系数据库中,数据库的重构往往是不可避免的。重构数据库最常见的是将一个基本表“垂直”地分成多个基本表。

例如:将学生关系Student(Sno, Sname, Ssex, Smajor) 分为 SX(Sno, Sname, Ssex) 和 SY(Sno, Smajor) 两个基本表。这扇原来的表 Student 就变为 SX 表和 SY 表自然连接的结果,如果建立一个视图  Student:

create view Student(Sno, Sname, Ssex, Smajor) as select SX.Sno, SX.Sname, SX.Ssex, SY.Smajor from SX, SY where SX.Sno = SY.Sno; 

🌈 这样尽管数据库的逻辑结构改变了,变为SX和SY两个基本表,但不必修改应用程因为我们可以建立视图 Student,它和用户原来创建的 Student 表一模一样。视图使用户的外模式保持不变,同时无须修改用户的应用程序就能和原来一样进行数据操作

当然,视图只能在一定程度上提供数据的逻辑独立性,比如上面讲到,对视图的更新是有操作。条件的,因此应用程序中修改数据的语句可能仍会因基本表结构的改变而需要做相应修改

(3)视图能够简化用户的操作 

  • 视图机制使用户可以将注意力集中在所关心的数据上。通过定义视图使数据库看起来结村更加简单、清晰,并且可以简化用户的数据查询操作。

例如:那些定义了若干张表连接的视图就将表与表之间的连接操作对用户隐蔽起来了,换句话说,用户所做的只是对一个虚表的简单查询。适当利用视图可以更清晰地表达查询

(4)视图使用户能以多种角度看待同一数据

  • 视图机制能使不同的用户以不同的方式看待同一数据,当许多不同类型的用户共享同一数据库时,这种灵活性是非常重要的。

例如:有的教师希望了解学生的平均成绩,有的教师希望了解学生的最高成绩和最低成绩,他们都可以在基本表SC上定义自己感兴趣的视图,直接对这些视图查询。

由于以上诸多优点,视图被广泛用于 实际应用开发中


 📖 总结

上面这些也是属于比较基础的内容,大家多敲多练习就会使用了。通过掌握上面的这些指令,我们就可以进行数据库的创建、管理、数据操作和查询等多种操作。

💞 💞 💞那么本篇到此就结束,希望我的这篇博客可以给你提供有益的参考和启示,感谢大家支持!!!祝大家天天开心