数据库学习笔记

先赞后看,养成习惯!!!❤️ ❤️ ❤️
码字不易,如果喜欢可以关注我哦!
如果本篇学习笔记对你有所启发,欢迎访问我的个人博客了解更多内容:链接地址

数据库

MySQL 是一种开源的关系型数据库管理系统(RDBMS),它是目前最流行的数据库之一,被广泛应用于各种应用和网站开发领域。

一、SQL语言

  • 关键字不缺分大小写
  • 好的书写习惯:关键字全大写,非关键字全小写:SELECT name,age,gender FROM user
  • 字符串内容是区分大小写的

1.1SQL语言的分类:

  • DDL:数据定义语言,用于进行数据库对象的操作.数据库对象指:库,表,视图,索引,序列等
  • DML:数据操作语言,对表中数据进行操作的语言.包含:增(INSERT)删(DELETE)改(UPDATE)
  • DQL:数据查询语言,对表中数据进行查询的语言,SELECT语句
  • DCL:数据控制语言,是对数据库进行管理的,通常比如创建用户,分配权限等.(DBA重点学习)
  • TCL:事务控制语言.包含:COMMIT(提交),ROLLBACK(回滚)

1.2数据类型

在数据库中设计一张表时,要为表中每个字段(列)单独指定数据类型以确保可以保存正确的数据
注意:数据类型本身是方言,不同的数据库数据类型不完全一样

1.2.1整数类型

INT类型
int类型占用4个字节,保存数字的范围±21

  • INT(m):m表示整数的长度(位数),类型后面通常要指定长度,不指定时默认为11位.
    BIGINT类型
    bigint类型占用8个字节
1.2.2浮点类型

DOUBLE类型
DOUBLE(M,N):定义DOUBLE类型时,要指明数字的长度和精度

  • M:表述数字的长度(位数)
  • N:表示小数点后的精度
  • M包含N.
  • DOUBLE(7,2):可以保存一个7位数字,其中2位数小数.最大值可以保存:99999.99

二、DDl语言

对数据库对象进行操作的语言:CREATE,ALTER,DROP

表操作

  • 查看表结构:DESC 表名
  • 查看创建表时的信息:SHOW CREATE TABLE 表名
  • 查看当前数据库创建的表:SHOW TABLES
  • 修改表名:RENAME TABLE 原表名 TO 新表名
  • 删除表:DROP TABLE 表名
  • 修改表
  • 添加新字段:ALTER TABLE 表名 ADD 字段名 类型[(长度)] [DEFAULT默认值] [约束]
  • 在表最开始插入字段:ALTER TABLE 表名 ADD 字段名 类型 FIRST
  • 在表中插入一个新字段,将新字段添加到表中指定字段的后面:ALTER TABLE 表名 ADD 字段名 类型 AFTER 表中某字段
  • 删除表中字段:ALTER TABLE 表名 DROP 字段名
  • 修改表中字段:ALTER TABLE 表名 CHANGE 原字段名 新字段名 类型[长度 默认值 约束]

三、DML语言

对表中数据进行操作的语言,涉及到的关键字:INSERT,UPDATE,DELETE

  • INSERT:用来向表中插入新数据
  • UPDATE:用来修改表中现有数据
  • DELETE:删除表中数据

3.1 INSERT语句

**INSERT INTO 表名 (字段1,字段2,字段3,...) VALUES(1,2,3)**

注意事项:

  • 数据库中字符串的字面量使用单引号
  • INSERT语句中VALUE子句中指定的值的顺序,个数,类型必须与前面指定的字段完全一致
  • INSERT语句指定的字段的顺序,个数可以与该表不完全一样
    补充
    查看表中数据,需要使用DQL语句(数据查询语言)
    查看指定表中的所有记录:
    SELECT * FROM 表名
3.1.1插入默认值

INSERT语句中没有被指明的字段都是插入默认值。如果该字段没有明确指定默认值时,默认值为NULL

3.2.2全列插入

INSERT语句中不指定任何字段时,则为全列插入,此时要求VALUES子句中指定的值的顺序,个数,类型必须与表结构定义完全一致
补充说明
在SQL语句中每个关键字可以构成一个子句
语法

**INSERT INTO 表名 VALUES(1,2,...)**
3.3.3插入NULL值与默认值
  • 可以在VALUES子句中显示的使用NULL来向字段插入一个NULL值
  • 可以在VALUES子句中显示的使用DEFAULT来向字段插入对应的默认值

字段插入默认值
INSERT INTO person VALUES(DEFAULT,22); name使用默认值

字段插入NULL值
INSERT INTO person VALUES(NULL,33); name插入了NULL值

3.3.4批量插入

语法:

**INSERT INTO 表名[(字段1,字段2,字段3..)] VALUES(1,2,3),(第二组值),(第三组值),...**

3.2 UPDATE语句

修改表数据
  • 语法
**(UPDATE 表名 SET 字段1=新值1,字段2=新值2...[WHERE 过滤条件])**         

添加WHERE子句目的是仅修改表中满足该条件的记录

  • WHERE子句在UPDATE语句中的作用
    通常UPDATE语句都会添加WHERE子句,用来指定筛选条件,只有满足条件的记录才会被修改
  • WHERE子句的基础条件
    WHERE子句会在后面DQL语句中详细介绍
    WHERE子句中可以使用的基础条件判断:>, >=, <, <=, =, <>(判断不等于使用"<>“,有些数据库支持”!=")

3.3 DELETE

删除表中数据

DELETE FROM 表名
[WHERE 过滤条件]

注意:通常DELETE语句不会忽略WHERE子句,否则是清空表操作

总结:

  • INSERT语句,向表中插入记录

    • INSERT后面指定的字段名可以与表结构不一致,但是要求VALUES子句中指定的值个数,顺序,类型必须与指定的字段一致
    • INSERT语句可以忽略某些字段,此时被忽略的字段会插入默认值
    • INSERT语句可以显示的插入默认值,此时VALUES子句中对应字段的值使用关键字DEFAULT
    • INSERT语句可以显示的插入NULL值,此时VALUES子句中对应字段的值使用关键字NULL
    • INSERT语句可以不指定任何字段,此时为全列插入,要求VALUES子句中指定的值的顺序,个数,类型必须与表表结构完全一致
  • UPDATE语句,用来修改表中的记录

    • 通常UPDATE语句不会忽略WHERE子句,因为修改表中记录是修改满足WHERE子句要求的记录。
    • 如果忽略了WHERE子句则是表中所有记录进行修改
  • DELETE语句,用来删除表中的记录

    • 通常DELETE语句不应当忽略WHERE子句,否则为清空表操作

四、DQL语言

数据查询语言
DQL是用于检索表中数据的语言

执行顺序
SELECT 子句----------------6
FROM 子句-------------------1
WHERE 子句-----------------2
JOIN … ON …子句---------3
GROUP BY 子句------------4
HAVING 子句-----------------5
ORDER BY 子句------------7
LIMIT 子句--------------------8

基础语法

SELECT 字段1,字段2,... FROM1,2...        检索指定字段的值      
SELECT * FROM1,2...                     检索所有字段的值
  • SELECT 子句用于指定需要检索表中那些字段的值
  • FROM子句用于指定从哪些表中检索数据

4.1WHERE子句(对全部数据进行过滤)

WHERE子句用来添加过滤条件,在DQL语句中用于筛选需要检索的数据,只有满足过滤条件的记录才会被查询出来
1.连接多个条件

  • AND:“与”,都为真时才为真
  • OR:“或”,都为假时才为假

2.AND的优先级高于OR
为了提高OR的优先级,可以使用"()"括起来

  • 查看班级编号在6(含)以下的所有大队长和中队长的名字,年龄,性别,班级编号和职位

3.IN(列表)
IN(列表):字段的值在列表当中,即:等于列表其中之一。

4.NOT IN(列表)
NOT IN(列表):字段值不在列表中,即:不能等于列表中的任何一项

5.ETWEEN…AND…
BETWEEN n AND m:在一个区间范围内。即:值要>=n并且<=m

6.DISTINCT
DISTINCT:去重,将结果集中指定字段值重复的记录去除
DISTINCT关键字必须紧跟在SELECT关键字之后

7.LIKE模糊查询
LIKE是用于进行模糊查询的,使用两个常用的通配符:

  • _:下划线表示一个字符(1个字符)
  • %:百分号表示任意个字符(0-任意次)

常见格式

LIKE '%X%'          表示字符串中含有X(X之前或之后可以有任意个字符)
LIKE '_X%'          表示字符串第二个字符是X
LIKE 'X%'           表示字符串是以X开头的
LIKE '%X'           表示字符串是以X结尾的
LIKE '%X_Y'         表示字符串倒数第三个字符是X并且最后一个字符是Y

8.NULL值判断
判断一个字段是否为NULL:

  • IS NULL:判断一个字段的值是否为空
  • IS NOT NULL:判断一个字段的值是否不为空
  • 不能使用"=“或者”<>"判断NULL和非NULL

4.2ORDER BY 子句

ORDER BY子句可以对查询结果集按照指定的字段进行升序或降序的排序

  • 升序:ORDER BY 字段(可以多字段) ASC。按照ORDER BY后面指定的字段按照值从小到大的顺序排序
  • 降序:ORDER BY 字段 DESC。按照指定字段值的从大到小顺序排序
  • 不指定排序方式时,默认为升序,因此实际开发中通常不会写ASC。
  • ORDER BY 子句是DQL中最后一个子句(MySQL和MariaDB中ORDER BY后面还会跟一个子句LIMIT,用于分页查询,但是分页查询属于方言)

排序可以按照多字段进行,规则:

  • 首先按照第一个字段的值进行对应的排序
  • 当第一个字段值相同的记录再按照第二个字段的值进行对应的排序
  • 优先级:ORDER BY后面第一个字段最优先,以此类推

4.3分页查询

分页查询:将一个DQL的查询结果集分段查询出来。
使用场景
当一个DQL语句执行的查询结果记录数非常庞大时,我们应当分段将数据检索出来。

例如:淘宝
当我们在淘宝上搜索一件商品时,通常会查询出数量庞大的商品列表,需要分批查询出来,比如我们常见的分页,一页仅显示30件商品,不断的换页数再查看其它部分的数据。

分批检索数据的优势:减小不必要的系统开销,降低网络传输的数据量,提高传输效率。
方言
分页查询是方言,SQL92标准中没有对分页的语法定义,因此不同的数据库分页写完完全不一样。
MySQL或MariaDB中的分页
语法

SELECT ...
FROM ...
WHERE ...
ORDER BY 字段
LIMIT M,N           用于分页查询
  • M:跳过结果集中多少条记录
  • N:从跳过的记录后开始检索出多少条记录
  • 分页中常见的参数:
  • 当前页数
  • 每页显示的条目数

分页公式

  • M:跳过的记录数,计算:(当前页数-1)*每页显示的条目数
  • N:每页显示的条目数

4.4在DQL语句中可以使用函数或表达式

在SELECT子句中使用表达式
  1. 数学函数,如ABS、CEIL、FLOOR、MOD、POWER等,对数据进行数学运算,计算平方、平均值及其它数学统计量等。

  2. 字符串函数,如CONCAT、UPPER、LOWER、LEFT、RIGHT、SUBSTRING等,对文本数据进行格式化、裁剪、拼接、转换等操作。

  3. 日期和时间函数,如DATE、DATEDIFF、DATETIME、NOW、TIME等,对日期和时间进行处理和计算。

  4. 逻辑函数,如IF、CASE、COALESCE等,对数据进行逻辑运算,处理多重条件和异常值。

  5. 聚合函数,如SUM、COUNT、AVG、MAX、MIN等,对数据进行聚合和汇总,计算数据的总和、平均值、最大值、最小值等。

使用函数和表达式时,需要考虑数据类型和精度的匹配,避免出现数据转换错误和计算误差。同时,也要注意查询性能和效率,避免使用过于复杂的函数和表达式,导致查询时间过长或影响系统性能。

在数据库中存在一些内置函数,不同的数据库函数名和作用不完全一样。

IF NULL函数
定义
IF NULL(arg1,arg2)

作用:

  • 如果arg1不为NULL,函数就返回arg1的值
  • 如果arg1为NULL,函数返回arg2的值
  • 该函数的作用是将一个NULL值替换为一个非NULL值
  • 内部逻辑
  • NULL值不仅不可以进行等值和非等值判断,同时"<“,”<=“,”>“,”>="都不可以
在WHERE子句中使用表达式

WHERE子句是用于指定条件的子句,它可以基于表达式过滤数据。
表达式可以是数学运算、逻辑运算或条件表达式,用于比较列和值以决定哪些行符合指定的条件。

常见的表达式包括

比较运算符(如=,<>,>,<,>=,<=),
逻辑运算符(如AND,OR,NOT),
函数表达式(如SUM,MAX,AVG)。

在WHERE子句中使用表达式可以让查询更灵活,可以根据不同的业务需求进行定制化查询,从而实现更精准的结果。

4.5别名

别名通常使用在SELECT子句和FROM子句中

  • 在SELECT子句中可以为字段取别名
  • 通常SELECT子句中我们会将一个表达式或函数取别名,这样查询结果集中该函数或表达式对应的字段名就会使用这个别名
  • 在SELECT子句中使用子查询时,会为该子查询去别名
  • 在FROM子句中可以为表取别名,降低SQL语句代码冗余(关联查询中经常使用,减少重复的表名书写)

语法:
字段名<空格>别名

查看老师的年薪
SELECT name,salary,salary*12
FROM teacher

4.6聚合函数

概念
聚合函数又称为多行函数,分组函数。对记录按照指定的字段进行统计并得出一行记录结果的
聚合函数分类

  • MIN:统计指定字段的最小值
  • MAX:统计指定字段的最大值
  • SUM:统计指定字段的总和
  • AVG:统计指定字段的平均值
  • COUNT:不是对字段值的统计,而是对记录数进行的统计,统计共有多少条记录

注意事项

  • 聚合函数忽略NULL值,AVG,COUNT最为明显
  • MIN,MAX,SUM,AVG是对值的统计,COUNT是对记录数的统计

4.7GROUP BY 分组

GROUP BY子句的作用是在DQL中将结果集按照指定的字段值相同的记录分组,并配合聚合函数进行分组统计使用

  • 在SELECT子句中出现了聚合函数时,那么不在聚合函数中的字段都应当出现在GROUP BY子句中
  • GROUP BY子句通常是配合聚合函数的,因此如果SELECT子句中没有聚合函数,通常不会用GROUP BY子句
4.7.1按照单字段分组

例如

  • 查看每种职位的老师平均工资是多少?
SELECT AVG(salary),title        因为title出现在GOURP BY子句中,因此可以在SELECT中单独出现
FROM teacher
GROUP BY title                  将结果集按照title字段值相同的记录分组
4.7.2按照多字段分组

GOURP BY子句后面可以指定多个字段,只有结果集中这些字段值都相同的记录才会看作一组
例如

- 查看同班级同性别的学生分别多少人?
SELECT COUNT(*),class_id,gender
FROM student
GROUP BY class_id,gender            只有class_id和gender都相同的记录才会被划分为一组
ORDER BY class_id,gender     

4.6HAVING子句(筛选分组之后的数据)

HAVING子句是紧跟在GROUP BY子句之后的,用于添加过滤条件来筛选分组的。

  • 问题:
查看每个科目老师的平均工资?但是仅查看平局工资高于6000的那些.
SELECT AVG(salary),subject_id
FROM teacher
WHERE AVG(salar)>6000               聚合函数不能出现在WHERE子句中
GROUP BY subject_id
  • 错误
    聚合函数不能出现在WHERE子句中
  • 原因

因为过滤时机不对,WHERE的过滤时机:

  • WHERE是在检索表时,逐行进行过滤的,意味着数据库会将满足WHERE条件的记录查询出来并包含在查询结果集中。因此WHERE是在查询过程中进行过滤的。
  • 聚合函数作为过滤条件,前提:
  • 聚合函数是用来统计结果集的,这意味着聚合函数使用至少要有结果集后才能进行
  • 而WHERE是在查询结果集时发挥作用的
  • 所以聚合函数作为过滤条件应当是在WHERE之后进行的
  • 解决办法
    使用HAVING子句
    HAVING与WHER的区别
  • 相同点在于:都可以添加过滤条件
  • HAVING子句可以使用聚合函数作为过滤条件
  • HAVING子句是用来过滤GOURP BY对结果集进行的分组
  • WHERE是先对全部数据进行过滤,产生结果集后并根据GOURP BY分组后HAVING才参与进来对分许进行过滤

4.7子查询(SubQuery)

是一条查询语句,嵌套在其他sql语句中

  • DQL中使用
  • 在SELECT子句中使用
  • 在WHERE子句中使用
  • 在DML中使用
  • 在增删改表中数据时可以依靠子查询结构进行
  • 在DDL中使用
  • 可以在创建表时,将一个查询结果集当作表创建出来
  • 可以将一个查询结果集当作视图创建

子查询分类:

  • 单行单列子查询:该查询结果集仅有一行一列,就是只有一个值。用于DML,DQL中
  • 多行单列子查询:查询结果集只有一列,但是可以有多行。用于DML,DQL中
  • 多行多列子查询:查询结果集是一张表(无论是多行还是一行,只要是多列)。用于DDL语句
4.7.1在DQL中使用子查询

单行单列子查询
例如
多行单列子查询
多行单列子查询,查询结果是由多个值构成的,因此作为过滤条件使用时:

  • 如果进行等值判断:要配合IN,NOT IN使用
  • 当子查询返回多行单列情况时,不能使用=来判断,应当使用IN
  • 如果进行关系运算(>,>=,<,<=):
  • >ANY(列表):大于列表其中之一,判断标准:大于最小的
  • <ANY(列表):小于列表其中之一,小于最大的
  • >ALL(列表):大于列表最大值
  • <ALL(列表):小于列表最小值
4.7.2在DML中使用子查询

在增删改操作中可以嵌套子查询

使用子查询作为查询语句的一部分,增强查询的灵活性和复杂性。

子查询是一个嵌套在主查询中的 SELECT语句,用于获取一个中间结果集,然后将这个结果作为主查询的条件,完成数据查询、插入、更新或删除。

三种常用子查询:

  1. WHERE子查询:使用WHERE子查询时,子查询位于主查询的WHERE子句中,作为一个条件来筛选行。例如,查询销售额大于市场平均水平的部门:

    SELECT department_name, sales_amount
    FROM department
    WHERE sales_amount > (SELECT AVG(sales_amount) FROM department)
    
  2. INSERT子查询:使用INSERT子查询是为了插入从另一个表派生的值。例如,使用INSERT INTO语句将从表employee中获取数据,然后将其插入到department表中:

    INSERT INTO department(department_name, manager_id, location)
    SELECT department_name, manager_id, location FROM employee WHERE department_id = '101'
    
  3. UPDATE子查询:使用UPDATE子查询是为了更新基于另一个表的条件的特定行。例如,将位于department表的市场部门的员工的工资提高10%:

    UPDATE employee SET salary = salary * 1.10 
    WHERE department_id = (SELECT department_id FROM department WHERE department_name = '市场')
    
4.7.3在DDL语句中使用子查询

将一个查询结果集当作一张表创建出来

使用子查询来动态生成DDL语句,从而满足不同的业务需求。

常见的DDL语句包括创建表、修改表、删除表、创建索引等。

三种常用子查询:

  1. CREATE TABLE AS SELECT:CREATE TABLE AS SELECT语句将查询的结果插入到新创建的表中。例如,创建一个新表employee_ctas,其中包含所有department_id为10的员工:

    CREATE TABLE employee_ctas AS
    SELECT * FROM employee
    WHERE department_id = 10
    
  2. CREATE TABLE LIKE:CREATE TABLE LIKE语句将从源表中创建一个新表,并复制表结构,包括列名、列的数据类型等。例如,创建一个具有与employee表相同结构的新表employee_new:

    CREATE TABLE employee_new LIKE employee
    
  3. CREATE INDEX ON (SELECT):CREATE INDEX ON (SELECT)语句使用子查询作为索引的基础数据。例如,创建一个基于department表部门名称的索引:

    CREATE INDEX department_name_idx ON department (department_name(30));
    

注意在使用子查询的DDL语句中,需要谨慎处理DDL语句的执行结果和影响范围,确保DDL语句符合业务需求和数据安全要求。同时,也要关注DDL语句的性能和效率,避免影响整体的系统性能。

4.8多表关联查询

定义
联合多张表查询数据,意味着查询结果集中的字段来自于多张表
关联关系
表与表中的数据会产生对应关系,这样的关系被称为关联关系

4.8.1关联关系分类

两张表就可以产生对应的关联关系

  • 一对一:A表的1条记录仅对应B表中的1条记录。此时A和B表就是一对一关联关系
  • 一对多:A表的1条记录可以对应B表的多条记录,此时A和B表就是一对多关系
  • 多对多:A表和B表双向都是一对多关系,就是多对多关系。
    • 多对多关系
      多对多关系:两张表双向看待都是"一对多"时,两张表就是多对多关系。
      多对多关系的设计方式:
    • 专门创建一张关联关系表,这张表上有两个字段,分别保存两张多对多关系表中主键字段的值
    • 关联关系表两个字段就是两个外键
4.8.2连接条件

连接条件是用来在关联查询时,让数据库可以理解表中记录的对应关系。从而将产生对应关系的记录从不同表中查询出来并体现到查询结果集中

  • 连接条件的指定个数:N张表关联查询要有至少N-1个连接条件
  • 比如:2张表关联查询就要有至少1个
  • 在关联查询中通常一定要指定连接条件,不指定连接条件时,则会产生笛卡尔积,通常是一个无意义的结果集,开销大,除了必要情况外要避免。
SELECT t.name,s.name
FROM teacher t,subject s

此时数据库查询的结果集中会包含两张表记录总数的乘积条结果。

  • 数据库会用teacher表的一条记录与subject表中的每条记录进行一次连接并生成一条记录
  • 通常这个结果集是无意义的,开销大。
  • 1个连接条件

语法

SELECT 表中字段
FROM A表,B表,C表...
WHERE 连接条件(多个连接条件之间必须使用AND保证同时成立)
AND 过滤条件(过滤条件也要与连接条件同时成立)
4.9.3主外键关联

通常在设计两张表时,如果两张表中的记录存在关联关系时,那么就会在表中以主外键关联形式设计表。

  • 什么是主键:主键通常是一张表中的第一个字段,名字一般用"id",使用该值为一表示一张表上的一条记录
  • 什么是外键:外键是用来记录另一张表上主键字段值的一个字段。设计有外键字段的表会与该字段保存的主键字段值对应的表产生关联关系,并且关联方式就是:存在外键字段的表是一对多中多的一方
  • 例如:class表与student表
  • class表设计了id字段作为主键(PK)
  • student表中设计了外键字段class_id,该字段记录了class表中某条记录的主键值。class_id就是外键(FK)
  • 因此class与student表就存在关联关系,并且在一对多中class是"一",student是"多"
  • 在关联查询中,连接条件通常就是等值连接,一般就是使用主键=外键进行关联的
4.9.4关联查询中使用聚合函数

关联查询中使用聚合函数,可以对多个表中的数据进行聚合统计,并返回一个结果集。

假设有两个表A和B:

A:
id   name
1    Alice
2    Bob
3    Carol

B:
id   a_id  score
1    1     95
2    1     85
3    2     90
4    3     80

现在需要查询每个人的平均分数,可以使用关联查询和聚合函数的结合:

SELECT A.id, A.name, AVG(B.score) as avg_score
FROM A
JOIN B ON A.id = B.a_id
GROUP BY A.id, A.name;

上面的查询中,通过连接A表和B表,可以得到每个人的分数,然后使用AVG函数对每个人的分数进行平均值计算,并使用GROUP BY子句对每个人进行分组。

查询结果:

id   name   avg_score
1    Alice  90.0
2    Bob    90.0
3    Carol  80.0

在使用关联查询和聚合函数时,需要确保各项间正确匹配,保证聚合函数的正确计算,同时也要关注查询的效率和性能,避免数据量大时查询效率过低影响系统性能。

4.9查询方式

4.9.1内连接

内连接是关联查询的另一种写法
关联查询语法:

SELECT 子句
FROM A表,B表,C表
WHERE A与B的连接条件 AND A与C的连接条件
AND 过滤条件

内连接语法:

SELECT 子句
FROM A表
JOIN B表 ON 连接条件
JOIN C表 ON 连接条件
WHERE 过滤条件
4.9.2外连接

外连接也是关联查询,特点:可以将不满足连接条件的记录也查询出来

  • 左外连接:以JOIN左侧表作为驱动表,该表中的所有数据都要查询出来(满足过滤条件),来自右侧表中不满足连接条件的记录对应的字段全部补NULL
  • 右外连接:以JOIN右侧表作为驱动表。
4.9.3UNION并集

UNION可以将不同的SQL查询结果集并在同一个结果集中显示

  • SELECT子句中的字段:顺序,个数,类型必须要一致
  • 重复的记录仅会保留一次
4.9.4自连接

定义
当一张表中的一条记录可以对应它自己的多条记录时,就是自连接。
自连接发生在同一张表中
场景
当数据具有相同属性,并且有存在上下级关系时(树状类型数据),可以设计为自连接。

主键和外键在同一张表中。

4.11外键约束

在关联关系中:通常两张表建立关系是靠主键与外键的等值连接作为连接条件。
外键约束要求

  • 当为一张表中某个字段添加外键约束时,该约束要求必须参照对应的主键字段值。
  • 具有外键约束的字段要求它的值可以是:
  • NULL值,外键字段可以不指定任何值
  • 主键字段的值,外键字段必须保存它参照的主键字段中包含的值。如果向外键字段插入一个主键字段没有的值时会报错,违背外键约束
    外键约束带来的问题
  • 外键约束不能保存主键字段没有的值
  • 主键字段的记录不能轻易被删除,因为如果该记录被删除,会导致外键字段保存该值时,这个值变成主键字段没有的值了,会违背外键约束
  • 如果需要删除主键字段对应记录,需要先将具有外键的表中对应该值的记录全部更新为NULL,才可以删除主键字段的记录。但是该操作会导致大量的DML操作。

结论:
实际开发中,通常我们不会为外键添加外键约束

五、约束条件

5.1主键约束

5.1.1什么是主键

主键是用来唯一表示表中每一条记录的一个值
可以作为主键的值要同时满足的要求:

  • 非空:每条记录都必须有该值
  • 唯一:每条记录该字段的值都不可以重复
5.1.2PRIMARY KEY
  • 当表中某个字段添加了主键约束后,数据库会检查向该字段插入数据时是否非空且唯一
  • 一张表中只有能一个字段添加主键约束
  • 作为主键的字段通常字段名命名为"id",一般也是表中的第一个字段
5.1.3自增

具有主键约束的字段对于主键值应当由系统生成,而自增就是主键值生成的方式之一 AUTO_INCREMENT

5.2非空约束(NOT NULL)

非空约束可以要求表中字段的值不允许为NULL。插入数据时必须指定该字段的值,修改数据时也不可以将NULL值修改到该字段上。

5.3唯一性约束(UNIQUE)

唯一性约束要求对应字段的值在整张表中不能有重复的值,NULL除外。

  • NULL值可以插入到具有唯一性约束的字段中,且可以重复多次
INSERT INTO user4(name,age) VALUES(NULL,33);        成功
INSERT INTO user4(name,age) VALUES(NULL,38);        成功

注:NULL是没有的意思,不算是一个值,因此不存在值重复。

  • 更新数据也不可以将重复的值更新到具有唯一性约束的字段中

5.4检查约束(CHECK)

检查约束允许我们为指定字段设定约束条件,只有满足条件的操作才被允许

5.5外键约束

外键约束在实际开发中几乎不会使用

六、预编译SQL

执行预编译SQL
预编译SQL:先将SQL语义定死,然后体现可变的值时先用 “?” 代替.此时先将预编译SQL语句发送给数据库
那么该SQL语义就不会因为拼接内容导致改变.
之后我们再讲可变的值单独传递给数据库,让其理解 “?” 的值是什么进行执行.

预编译SQL的优点:
1:不会出现SQL注入式工具
2:当语义不变,但是值会改变的多条SQL执行时,效率高,开销小

public class JDBCDemo8 {
    public static void main(String[] args) {
        UserInfo userInfo = InputUtil.getInputObject(new UserInfo(),"欢迎登录","登录");

        try(
                Connection connection = DBUtil.getConnection();
        ) {
            //将可变化的值先用"?"代替.值是不影响SQL语义的.
            String sql = "SELECT id,username,password,nickname,age " +
                    "FROM userinfo " +
                    "WHERE username=? AND password=?";
            /*
                在创建执行对象时先将预编译SQL发送给了数据库
                此时数据库接收到预编译SQL后会理解该SQL语义并生成执行计划,但是该计划还不能
                被真正的执行,因为还缺少数据.
             */
            PreparedStatement ps = connection.prepareStatement(sql);
            //为预编译SQL中的"?"指定实际的值.参数1是第几个"?"(规则:从上往下,从左往右)
            ps.setString(1, userInfo.getUsername());//调用setXXX()方法,取决于该字段的类型
            //就算密码输入:' OR '1'='1  数据库也仅把它当做密码的值看待,去数据库查询有没有这个密码
            ps.setString(2, userInfo.getPassword());
            ResultSet rs = ps.executeQuery();//此时会将两个?对应的值发送给数据库来执行该预编译SQL
            if(rs.next()){
                System.out.println("登录成功");
            }else {
                System.out.println("登录失败");
            }


        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
}

七、拓展

数据库中的锁是一种机制,用于控制并发访问时对数据的访问和操作。在多用户同时对同一数据进行并发操作时,由于并发操作的执行顺序不确定性,会出现一些问题,如丢失修改、脏读等情况。为避免这些问题,数据库提供了锁机制,以保证并发访问同一数据时的正确性和一致性。

数据库锁可以分为多种类型,包括:

  1. 共享锁(Shared Lock):
    共享锁允许多个事务在读取某个数据时共享该锁,但是不允许进行修改和删除操作,直到所有使用该锁的事务都释放了它。共享锁常用于读操作。

  2. 排他锁(Exclusive Lock):
    排他锁只允许一个事务独占某个数据,不允许其他任何事务对该数据进行读和写操作,直到独占该锁的事务结束。排他锁常用于写操作。

  3. 行级锁(Row Lock):
    行级锁是针对数据库中某一行数据的锁定机制,比如只对一条记录进行锁定,其他行不受影响。行级锁可以减少竞争,提高数据库的并发能力,并且锁定的资源更加精细。

  4. 表级锁(Table Lock):
    表级锁是针对整张表的锁定机制,锁定整张表的数据,其他事务无法进行任何操作。表级锁虽然简单,但并发性能较差,一旦锁住某个表,其他需要访问该表的事务都需要等待。

不同的锁机制可以应对不同的并发场景,开发人员需要根据具体情况选择适合的锁机制。

如果您对本篇学习笔记对你有所启发,欢迎访问我的个人博客了解更多内容:链接地址

  • 21
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值