从零开始的MySQL学习

MySQL

从零开始的MySQL学习

第一节 数据库

重点:数据库通过SQL等标准语言进行动作,数据库的概念、分类,数据管理系统(操纵和管理数据库的大型软件)

数据库(Database)

是按照数据结构来组织、存储和管理数据的仓库。它允许用户高效地访问、插入、更新和删除数据。

数据库的相关概念

1. 数据(Data)

数据是描述事物的符号记录,可以是数字、文字、图形、声音等。在数据库中,数据是被组织和存储的基本对象。

2. 数据库管理系统(DBMS)

数据库管理系统(Database Management System,DBMS)是位于用户和操作系统之间的一层数据管理软件。它为用户或应用程序提供访问数据库的方法,包括数据定义、数据操纵、数据控制等功能。

3. 数据库系统(DBS)

数据库系统(Database System,DBS)是指在计算机系统中引入数据库后的系统。它由数据库、数据库管理系统、数据库管理员、硬件平台和软件平台组成。

4. 数据模型(Data Model)

数据模型是数据库中数据特征的描述,是数据库系统的核心和基础。常见的数据模型包括:

  • 层次模型(Hierarchical Model):数据以树形结构组织,每个节点有且仅有一个父节点(根节点除外)。
  • 网状模型(Network Model):数据以网状结构组织,允许一个节点有多个父节点。
  • 关系模型(Relational Model):数据以表格形式组织,每个表称为一个关系,表中的每一行称为一个元组,每一列称为一个属性。
5. 关系数据库(Relational Database)

关系数据库是基于关系模型的数据库。它使用表格来存储数据,每个表格由行(记录)和列(字段)组成。关系数据库是最常用的一种数据库类型,具有简单、易懂、易于维护等优点。

6. SQL(Structured Query Language)

SQL 是一种用于管理和操作关系数据库的标准编程语言。它提供了数据定义(DDL)、数据操纵(DML)、数据控制(DCL)等功能。常见的 SQL 语句包括:

  • 数据定义:CREATE TABLEALTER TABLEDROP TABLE 等。
  • 数据操纵:INSERTSELECTUPDATEDELETE 等。
  • 数据控制:GRANTREVOKE 等。
7. 数据库设计(Database Design)

数据库设计是创建一个满足用户需求的数据库的过程。它包括需求分析、概念设计(如 E-R 图)、逻辑设计(如关系模式)、物理设计(如存储结构)等步骤。

8. 事务(Transaction)

事务是数据库中一系列的操作,这些操作要么全部成功,要么全部失败。事务具有四个特性,即 ACID 特性:

  • 原子性(Atomicity):事务中的所有操作要么全部完成,要么全部不完成。
  • 一致性(Consistency):事务执行前后,数据库的状态保持一致。
  • 隔离性(Isolation):并发执行的事务之间相互隔离,互不干扰。
  • 持久性(Durability):事务一旦提交,其结果就是永久的,即使系统故障也不会丢失。
9. 索引(Index)

索引是数据库中用于加速数据检索的一种数据结构。它类似于书籍的目录,通过索引可以快速定位到数据的位置,从而提高查询效率。

10. 视图(View)

视图是基于一个或多个表的虚拟表,其内容由 SQL 查询定义。视图不存储数据,而是存储查询语句,当查询视图时,数据库会动态生成数据。

数据库的类型

  1. 关系数据库(Relational Database)

    • 代表:MySQL、PostgreSQL、Oracle、SQL Server。
    • 特点:使用表格存储数据,支持 SQL 语言,具有强大的事务处理能力。
  2. 非关系数据库(NoSQL Database)

    • 代表:MongoDB、Redis、Cassandra。
    • 特点:不使用表格存储数据,支持灵活的数据模型,适合处理大规模分布式数据。
  3. 内存数据库(In-Memory Database)

    • 代表:Redis、Memcached。
    • 特点:数据存储在内存中,访问速度极快,适合需要快速读写的应用。
  4. 对象关系数据库(Object-Relational Database)

    • 代表:PostgreSQL。
    • 特点:结合了关系数据库和面向对象数据库的特点,支持复杂数据类型和方法。
MySQL数据模型:
  • 客户端—>DBMS—>数据库—>表

第二节 SQL

SQL分类

前四个分类为基础

1. 数据定义语言(DDL,Data Definition Language)

DDL 提供了定义和修改数据库结构的语句,包括创建、修改和删除数据库对象(如表、索引、视图、触发器等)。

  • CREATE:创建新的数据库对象。
  • ALTER:修改现有数据库对象的结构。
  • DROP:删除数据库对象。
  • TRUNCATE:快速删除表中的所有行,但不删除表本身。

2. 数据操纵语言(DML,Data Manipulation Language)

DML 提供了访问和修改数据库中数据的语句,包括插入、更新和删除数据。

  • INSERT:向表中插入新数据。
  • UPDATE:修改表中的现有数据。
  • DELETE:从表中删除数据。

3. 数据查询语言(DQL,Data Query Language)

DQL 主要包括 SELECT 语句,用于查询数据库中的数据。

  • SELECT:从数据库中检索数据。

4. 数据控制语言(DCL,Data Control Language)

DCL 提供了控制数据库访问权限的语句,包括授予和撤销用户对数据库对象的访问权限。

  • GRANT:授予用户或角色对数据库对象的特定权限。
  • REVOKE:撤销用户或角色的权限。

5. 事务控制语言(TCL,Transaction Control Language)

TCL 提供了管理数据库事务的语句,确保数据的一致性和完整性。

  • BEGINSTART TRANSACTION:开始一个新的事务。
  • COMMIT:提交事务,使自事务开始以来对数据库的所有更改成为永久性更改。
  • ROLLBACK:回滚事务,撤销自事务开始以来对数据库的所有更改。
  • SAVEPOINT:设置事务的保存点,允许部分回滚。

6. 数据访问语言(DAL,Data Access Language)

虽然不是 SQL 标准的一部分,但 DAL 通常指的是用于访问数据库的编程接口和工具,如 JDBC、ODBC、OLE DB 等。

7. 存储过程和函数

存储过程和函数是一组为了完成特定功能的 SQL 语句,它们被预先编写并存储在数据库中,可以通过一个调用语句来执行。

  • CREATE PROCEDURE:创建存储过程。
  • CREATE FUNCTION:创建函数。

8. 触发器(Triggers)

触发器是数据库中的一种特殊类型的存储过程,它们在特定的数据库事件(如 INSERT、UPDATE 或 DELETE)发生时自动执行。

  1. CREATE TRIGGER:创建触发器。

具体操作

一.DDL

1. 数据查询(SELECT)

SELECT column1, column2, ...
FROM table_name
WHERE condition
ORDER BY column;

2. 数据插入(INSERT)

INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);

3. 数据更新(UPDATE)

UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;

4. 数据删除(DELETE)

DELETE FROM table_name
WHERE condition;

5. 创建表(CREATE TABLE)

CREATE TABLE table_name (column1 datatype,column2 datatype,...
);

6. 修改表结构(ALTER TABLE)

ALTER TABLE table_name
ADD column_name datatype;

7. 删除表(DROP TABLE)

DROP TABLE table_name;

8. 创建索引(CREATE INDEX)

CREATE INDEX index_name
ON table_name (column);

9. 删除索引(DROP INDEX)

DROP INDEX index_name;

10. 创建视图(CREATE VIEW)

CREATE VIEW view_name AS
SELECT column1, column2, ...
FROM table_name
WHERE condition;

11. 删除视图(DROP VIEW)

DROP VIEW view_name;

12. 创建存储过程(CREATE PROCEDURE)

CREATE PROCEDURE procedure_name (parameter_list)
BEGIN-- SQL statements
END;

13. 调用存储过程(CALL)

CALL procedure_name(value1, value2, ...);

14. 删除存储过程(DROP PROCEDURE)

DROP PROCEDURE procedure_name;

15. 创建触发器(CREATE TRIGGER)

CREATE TRIGGER trigger_name
BEFORE|AFTER INSERT|UPDATE|DELETE ON table_name
FOR EACH ROW
BEGIN-- SQL statements
END;

16. 删除触发器(DROP TRIGGER)

DROP TRIGGER trigger_name;

17. 设置权限(GRANT)

GRANT SELECT, INSERT ON database_name.table_name TO 'username'@'host';

18. 撤销权限(REVOKE)

REVOKE SELECT, INSERT ON database_name.table_name FROM 'username'@'host';

19. 创建数据库(CREATE DATABASE)

CREATE DATABASE database_name;

20. 删除数据库(DROP DATABASE)

DROP DATABASE database_name;
列出数值类型
类型大小(字节)有符号范围无符号范围精度(小数点后位数)用途
TINYINT1-128 到 1270 到 255不适用小范围整数
SMALLINT2-32768 到 327670 到 65535不适用中等范围整数
MEDIUMINT3-8388608 到 83886070 到 16777215不适用大范围整数
INT4-2147483648 到 21474836470 到 4294967295不适用通用整数
BIGINT8-9223372036854775808 到 92233720368547758070 到 18446744073709551615不适用极大范围整数
FLOAT4±1.17549435 × 10^−38 到 ±3.40282347 × 10^38±1.17549435 × 10^−38 到 ±3.40282347 × 10^38不适用单精度浮点数
DOUBLE8±2.2250738585072014 × 10^−308 到 ±1.7976931348623157 × 10^308±2.2250738585072014 × 10^−308 到 ±1.7976931348623157 × 10^308不适用双精度浮点数
DECIMAL动态取决于数值和精度取决于数值和精度可指定精确的十进制表示
BIT动态不适用不适用不适用位字段
BOOLEAN1不适用不适用不适用布尔值
字符串类型
类型大小限制描述
CHAR(n)0 到 255 字节固定长度字符串。不足部分用空格填充。
VARCHAR(n)0 到 65,535 字节可变长度字符串。存储时只占用实际需要的空间加上一个长度字节。
TINYTEXT0 到 255 字节短文本字符串。
TEXT0 到 65,535 字节长文本字符串。
MEDIUMTEXT0 到 16,777,215 字节较长文本字符串。
LONGTEXT0 到 4,294,967,295 字节非常长的文本字符串。
ENUM1 或 2 字节枚举类型,由一组预定义的字符串值组成。
SET1、2、3、4 或 8 字节集合类型,由一组预定义的字符串值组成,可以存储多个值。
BINARY(n)0 到 255 字节固定长度的二进制字符串。
VARBINARY(n)0 到 65,535 字节可变长度的二进制字符串。
TINYBLOB0 到 255 字节短二进制数据。
BLOB0 到 65,535 字节长二进制数据。
MEDIUMBLOB0 到 16,777,215 字节较长二进制数据。
LONGBLOB0 到 4,294,967,295 字节非常长的二进制数据。
VALCHAR相对于CHAR性能差一些
日期类型
类型格式/范围描述
DATEYYYY-MM-DD存储日期,格式为年-月-日。
范围:0001-01-01 至 9999-12-31
TIMEHH:MM:SS存储时间,格式为小时:分钟:秒。
范围:-838:59:59 至 838:59:59
DATETIMEYYYY-MM-DD HH:MM:SS存储日期和时间,格式为年-月-日 时:分:秒。
范围:0001-01-01 00:00:00 至 9999-12-31 23:59:59
TIMESTAMPYYYY-MM-DD HH:MM:SS存储日期和时间,通常用于自动生成的时间戳。
范围:1970-01-01 00:00:01 UTC 至 2038-01-19 03:14:07 UTC
范围:0001-01-01 00:00:00 至 9999-12-31 23:59:59(有符号)
YEARYYYY存储年份,格式为四位数字。
范围:1901 至 2155

举例

现在我们创建一张表举例

CREATE TABLE EMP (ID INT,WORKNO VARCHAR(10) COMMENT '工号',NAME VARCHAR(10) COMMENT '姓名',GENDER CHAR(1) COMMENT '性别',AGE TINYINT UNSIGNED COMMENT '年龄',IDCARD CHAR(18) COMMENT '身份证',ENTRYDATE DATE COMMENT '入职时间'
) COMMENT '员工表';
--一些操作
ALTER TABLE EMP ADD NICKNAME VARCHAR(20) COMMENT '昵称';
ALTER TABLE EMP MODIFY ;
ALTER TABLE EMP CHANGE NICKNAME USERNANE VARCHAR (30) COMMENT'用户名';
ALTER TABLE EMP DROP USERNAME;
ALTER TABLE EMP RENAME TO EMPLOY;
DROP TABLE IF EXISTS EMPLOY;//删除表,所有数据也跟着被删除
TRUNCATE TABLE EMPLOY;//留下空表,删除所有数据
注意事项:

中英文的输入如引号分号等,括号不是大括号,COMMENT后面要有一个空格。

二.MySQL图形化

三.DML(增删改)

INSERT INTO EMP (ID,WORKNO,NAME,GENDER,AGE,IDCARD,ENTRYDATE) VALUES (1,'1','A','男',10,'123456789012345678','2000-01-01');  SELECT * FROM EMP;UPDATE EMP SET NAME = 'YOU',GENDER = '女' WHERE ID = 1;UPDATE EMP SET NAME = 'YOUNG' WHERE ID = 1;DELETE FROM EMP WHERE GENDER = '女';

四.DQL(查询)

核心SELECT语句
SELECT NAME,WORKNO,AGE FROM ENP;SELECT * FROM EMP WHERE ID = 1;实际中尽量不要用*,不直观,如此处直接把所有要查询的输出来就行SELECT NAME AS 'XINGMIN' FROM EMP;//AS可以省略SELECT  DISTINCT NAME FROM EMP;//查询没有重复
比较运算符
  1. 等于 (=)

    • 检查两个值是否相等。
    • 示例:SELECT * FROM table_name WHERE column_name = 'value';
  2. 不等于 (<>!=)

    • 检查两个值是否不相等。
    • 示例:SELECT * FROM table_name WHERE column_name <> 'value';
  3. 大于 (>)

    • 检查左边的值是否大于右边的值。
    • 示例:SELECT * FROM table_name WHERE column_name > 10;
  4. 小于 (<)

    • 检查左边的值是否小于右边的值。
    • 示例:SELECT * FROM table_name WHERE column_name < 5;
  5. 大于等于 (>=)

    • 检查左边的值是否大于或等于右边的值。
    • 示例:SELECT * FROM table_name WHERE column_name >= 20;
  6. 小于等于 (<=)

    • 检查左边的值是否小于或等于右边的值。
    • 示例:SELECT * FROM table_name WHERE column_name <= 50;
  7. IS NULL

    • 检查值是否为 NULL。
    • 示例:SELECT * FROM table_name WHERE column_name IS NULL;
  8. IS NOT NULL

    • 检查值是否不为 NULL。
    • 示例:SELECT * FROM table_name WHERE column_name IS NOT NULL;
  9. BETWEEN

    • 检查一个值是否在两个指定的值之间(包括边界值)。
    • 示例:SELECT * FROM table_name WHERE column_name BETWEEN 10 AND 20;
  10. IN

    • 检查一个值是否包含在一组指定的值中。
    • 示例:SELECT * FROM table_name WHERE column_name IN ('value1', 'value2', 'value3');
  11. LIKE

    • 检查一个值是否符合指定的模式(使用通配符 %_)。
    • 示例:SELECT * FROM table_name WHERE column_name LIKE '%value%';
  12. REGEXPRLIKE(取决于数据库系统):

    • 检查一个值是否符合指定的正则表达式模式。
    • 示例:SELECT * FROM table_name WHERE column_name REGEXP '^value.*';
逻辑运算符
  1. AND

    • 逻辑“与”运算符。只有当所有条件都为 true 时,结果才为 true
    • 示例:SELECT * FROM table_name WHERE condition1 AND condition2;
  2. OR

    • 逻辑“或”运算符。只要有一个条件为 true,结果就为 true
    • 示例:SELECT * FROM table_name WHERE condition1 OR condition2;
  3. NOT

    • 逻辑“非”运算符。用于反转条件的逻辑值,将 true 转换为 false,将 false 转换为 true
    • 示例:SELECT * FROM table_name WHERE NOT condition;
  4. XOR

    • 逻辑“异或”运算符。当且仅当两个条件的逻辑值不同时,结果为 true
    • 示例:SELECT * FROM table_name WHERE condition1 XOR condition2;(注意:并非所有数据库系统都支持 XOR 运算符。)

使用逻辑运算符的注意事项:

  • 优先级:逻辑运算符具有不同的优先级。通常,NOT 的优先级最高,其次是 AND,然后是 OR。可以使用括号来明确指定运算顺序。
  • 括号:在复杂的逻辑表达式中,使用括号来分组条件,确保逻辑运算的顺序符合你的预期。
  • 性能:在某些情况下,逻辑运算符的使用可能会影响查询性能。合理地构建查询条件可以提高查询效率。
示例

假设有一个名为 employees 的表,包含员工的 agesalary 列,可以使用逻辑运算符来构建复杂的查询:

-- 选择年龄大于30且工资高于5000的员工
SELECT * FROM employees WHERE age > 30 AND salary > 5000;-- 选择年龄小于30或工资低于5000的员工
SELECT * FROM employees WHERE age < 30 OR salary < 5000;-- 选择工资高于5000但年龄不大于40的员工
SELECT * FROM employees WHERE salary > 5000 AND NOT (age > 40);-- 选择年龄大于30或工资高于5000,但不是两者都满足的员工
SELECT * FROM employees WHERE (age > 30 XOR salary > 5000);
基本查询
  1. 查询所有列

    SELECT * FROM table_name;
    
  2. 查询特定列

    SELECT column1, column2 FROM table_name;
    
  3. 查询符合条件的行

    SELECT * FROM table_name WHERE condition;
    
  4. 查询结果排序

    SELECT * FROM table_name ORDER BY column ASC;  -- 升序
    SELECT * FROM table_name ORDER BY column DESC; -- 降序
    
  5. 查询结果分页(MySQL):

    SELECT * FROM table_name LIMIT 10 OFFSET 20; -- 从第21行开始,取10行
    
聚合查询
  1. 使用聚合函数

    SELECT COUNT(*) FROM table_name; -- 计算行数
    SELECT SUM(column) FROM table_name; -- 计算列的总和
    SELECT AVG(column) FROM table_name; -- 计算列的平均值
    SELECT MAX(column), MIN(column) FROM table_name; -- 找出列的最大值和最小值
    
  2. 分组查询

    SELECT column, COUNT(*) FROM table_name GROUP BY column;
    
  3. 过滤分组后的结果(使用 HAVING 子句):

    SELECT column, COUNT(*) FROM table_name GROUP BY column HAVING COUNT(*) > 1;
    
连接查询
  1. 内连接INNER JOIN):

    SELECT * FROM table1 INNER JOIN table2 ON table1.column_name = table2.column_name;
    
  2. 左连接LEFT JOIN):

    SELECT * FROM table1 LEFT JOIN table2 ON table1.column_name = table2.column_name;
    
  3. 右连接RIGHT JOIN):

    SELECT * FROM table1 RIGHT JOIN table2 ON table1.column_name = table2.column_name;
    
子查询
  1. SELECT 语句中使用子查询

    SELECT * FROM table_name WHERE column_name IN (SELECT column_name FROM other_table);
    
  2. FROM 子句中使用子查询

    SELECT * FROM (SELECT column_name FROM table_name) AS derived_table;
    
联合查询
  1. 合并多个查询结果(使用 UNION):

    SELECT column_name FROM table1
    UNION
    SELECT column_name FROM table2;
    
  2. 合并多个查询结果并去重(使用 UNION DISTINCTDISTINCT):

    SELECT DISTINCT column_name FROM table1
    UNION DISTINCT
    SELECT DISTINCT column_name FROM table2;
    
直接说似乎不易理解其执行顺序,这里给出样例
  1. FROM

    • 首先,DBMS 处理 FROM 子句,这涉及到从指定的表或子查询中检索数据。
  2. JOIN

    • 如果查询中包含 JOIN 操作,DBMS 将执行表的连接操作,根据指定的连接条件合并表中的数据。
  3. WHERE

    • WHERE 子句在 FROMJOIN 之后执行,用于过滤结果集,只保留满足条件的行。
  4. GROUP BY

    • 如果查询包含 GROUP BY 子句,DBMS 将对 WHERE 过滤后的结果集进行分组。
  5. HAVING

    • HAVING 子句在 GROUP BY 之后执行,用于过滤分组后的结果,只保留满足特定条件的组。
  6. SELECT

    • SELECT 子句指定了查询需要返回的列。在这个阶段,DBMS 会从处理过的数据中选择指定的列。
  7. DISTINCT

    • 如果查询中包含 DISTINCT 关键字,DBMS 将从 SELECT 列表中移除重复的行。
  8. ORDER BY

    • 最后,ORDER BY 子句对查询结果进行排序,按照指定的列和顺序返回最终结果。
  9. LIMIT

    • 在某些数据库系统中,如 MySQL,LIMIT 子句用于限制返回的行数,通常在 ORDER BY 之后执行。
示例查询及其执行顺序

考虑以下查询:

SELECT DISTINCT column1, column2
FROM table1
INNER JOIN table2 ON table1.id = table2.id
WHERE column1 > 100
GROUP BY column2
HAVING COUNT(*) > 5
ORDER BY column1 DESC
LIMIT 10;

执行顺序如下:

  1. FROM:从 table1table2 中检索数据。
  2. INNER JOIN:根据 table1.id = table2.id 连接表。
  3. WHERE:过滤 column1 > 100 的行。
  4. GROUP BY:按 column2 分组。
  5. HAVING:过滤 COUNT(*) > 5 的组。
  6. SELECT:选择 column1column2
  7. DISTINCT:移除重复的行。
  8. ORDER BY:按 column1 DESC 排序。
  9. LIMIT:限制结果为前 10 行。

五.DCL

DCL 包括的常用 SQL 命令主要有 GRANTREVOKE

当然,以下是一些使用 DCL(数据控制语言)的 GRANTREVOKE 命令的例子,这些命令用于管理用户权限:

GRANT 命令的例子

  1. 授予用户对特定表的 SELECT 和 INSERT 权限

    GRANT SELECT, INSERT ON database_name.table_name TO 'username'@'host';
    

    这条命令授予名为 username 的用户对 database_name 数据库中 table_name 表的查询(SELECT)和插入(INSERT)权限。

  2. 授予用户对所有表的 SELECT 权限

    GRANT SELECT ON database_name.* TO 'username'@'host';
    

    这条命令授予用户对 database_name 数据库中所有表的查询(SELECT)权限。

  3. 授予用户对数据库的所有权限,并允许其将权限授予其他用户

    GRANT ALL PRIVILEGES ON database_name.* TO 'username'@'host' WITH GRANT OPTION;
    

    这条命令授予用户所有权限,并允许该用户将这些权限授予其他用户。

  4. 授予用户对数据库中所有新创建的表和存储过程的权限

    GRANT SELECT, INSERT ON database_name.* TO 'username'@'host' WITH GRANT OPTION;
    

    这条命令授予用户对现有和未来创建的所有表的 SELECT 和 INSERT 权限。

REVOKE 命令的例子

  1. 撤销用户对特定表的 INSERT 权限

    REVOKE INSERT ON database_name.table_name FROM 'username'@'host';
    

    这条命令撤销了之前授予 username 用户对 database_name 数据库中 table_name 表的 INSERT 权限。

  2. 撤销用户对数据库的所有权限

    REVOKE ALL PRIVILEGES ON database_name.* FROM 'username'@'host';
    

    这条命令撤销了用户对 database_name 数据库的所有权限。

  3. 撤销用户授予其他用户的权限

    REVOKE GRANT OPTION ON database_name.* FROM 'username'@'host';
    

    这条命令撤销了用户 username 授予其他用户权限的能力。

  4. 级联撤销用户对特定表的所有权限

    REVOKE ALL PRIVILEGES ON database_name.table_name FROM 'username'@'host' CASCADE;
    

    这条命令不仅撤销了用户对 table_name 表的所有权限,还撤销了该用户可能已经授予其他用户的权限。

在使用这些命令时,需要替换 database_nametable_nameusernamehost 为实际的数据库名、表名、用户名和主机名。此外,确保有足够的权限来授予或撤销权限,通常是数据库管理员(DBA)或具有相应权限的用户。

第三节 函数

字符串函数

1. CONCAT()

用于连接两个或多个字符串。

SELECT CONCAT('Hello', ' ', 'World') AS ConcatenatedString;

结果:Hello World

2. LENGTH() 或 CHAR_LENGTH()

返回字符串的长度。

SELECT LENGTH('Hello World') AS StringLength;

结果:11

3. SUBSTRING() 或 SUBSTR()

从字符串中提取子字符串。

SELECT SUBSTRING('Hello World', 1, 5) AS SubString;

结果:Hello

4. POSITION() 或 INSTR()

返回子字符串在字符串中的位置。

SELECT POSITION('World' IN 'Hello World') AS Position;

结果:7

5. REPLACE()

替换字符串中的某些字符。

SELECT REPLACE('Hello World', 'World', 'SQL') AS ReplacedString;

结果:Hello SQL

6.LTRIM() 和 RTRIM()

分别去除字符串左侧和右侧的空格。

SELECT LTRIM('  Hello World') AS LeftTrimmed, RTRIM('Hello World  ') AS RightTrimmed;

结果:Hello WorldHello World

7. TRIM()

去除字符串两侧的空格。

SELECT TRIM('  Hello World  ') AS TrimmedString;

结果:Hello World

8. UPPER() 和 LOWER()

分别将字符串转换为大写和转换为小写。

SELECT UPPER('Hello World') AS UpperString, LOWER('Hello World') AS LowerString;

结果:HELLO WORLDhello world

9. LEFT() 和 RIGHT()

分别从字符串的左侧和右侧提取指定数量的字符。

SELECT LEFT('Hello World', 5) AS LeftString, RIGHT('Hello World', 5) AS RightString;

结果:HelloWorld

10. REVERSE()

反转字符串。

SELECT REVERSE('Hello World') AS ReversedString;

结果:dlroW olleH
在 SQL 中,数值函数用于执行各种数值计算,包括数学运算、四舍五入、取整、随机数生成等。以下是一些常见的数值函数:

数值函数

1. ABS(x)

返回指定数值的绝对值。

SELECT ABS(-10) AS AbsoluteValue;

结果:10

2. CEILING(x)

返回大于或等于给定数值的最小整数。

SELECT CEILING(3.14) AS CeilingValue;

结果:4

3. FLOOR(x)

返回小于或等于给定数值的最大整数。

SELECT FLOOR(3.14) AS FloorValue;

结果:3

4. ROUND(x)

将给定数值四舍五入到最接近的整数。

SELECT ROUND(3.14159) AS RoundedValue;

结果:3

5. TRUNCATE(x, d)

截断一个数字到指定的小数位数。

SELECT TRUNCATE(3.14159, 2) AS TruncatedValue;

结果:3.14

6. POWER(x, y) 或 EXP(x)

返回 x 的 y 次幂。

SELECT POWER(2, 3) AS PowerValue;

结果:8

7. SQRT(x)

返回给定数值的平方根。

SELECT SQRT(9) AS SquareRoot;

结果:3

8. LOG(x)

返回给定数值的自然对数(以 e 为底)。

SELECT LOG(2.718281828) AS NaturalLogarithm;

结果:1

9. LN(x)

返回给定数值的自然对数(以 e 为底)。

SELECT LN(2.718281828) AS NaturalLogarithm;

结果:1

10. MOD(x, y)

返回 x 除以 y 的余数。

SELECT MOD(7, 3) AS Modulus;

结果:1

11. SIGN(x)

返回给定数值的符号,正数返回 1,负数返回 -1,零返回 0。

SELECT SIGN(-5) AS SignValue;

结果:-1

12. PI()

返回圆周率 π 的值。

SELECT PI() AS PiValue;

结果:3.141592653589793

13. RANDOM() 或 RAND()

返回一个随机浮点数,范围从 0 到 1。

SELECT RANDOM() AS RandomValue;

结果:0.123456789(示例值,实际值随机)

14. TRUNCATETABLE(x, y)

截断数值 x 到 y 位小数(与 TRUNCATE 相似)。

SELECT TRUNCATETABLE(123.45678, 2) AS TruncatedValue;

结果:123.45

日期函数

1. CURRENT_DATE 或 CURDATE()

返回当前日期。

SELECT CURRENT_DATE;

2. CURRENT_TIME 或 CURTIME()

返回当前时间。

SELECT CURRENT_TIME;

3. NOW() 或 CURRENT_TIMESTAMP

返回当前日期和时间。

SELECT NOW();

4. DATE_ADD(date, INTERVAL expr type)

给定日期加上一个时间间隔。

SELECT DATE_ADD('2024-01-01', INTERVAL 10 DAY);

结果:2024-01-11

5. DATE_SUB(date, INTERVAL expr type)

从给定日期减去一个时间间隔。

SELECT DATE_SUB('2024-01-15', INTERVAL 10 DAY);

结果:2024-01-05

6. DATEDIFF(date1, date2)

返回两个日期之间的天数差异。

SELECT DATEDIFF('2024-01-05', '2024-01-01');

结果:4

7. DATE_FORMAT(date, format)

将日期格式化为字符串。

SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s');

结果:格式化后的当前日期和时间字符串

8. STR_TO_DATE(string, format)

将字符串转换为日期,根据提供的格式。

SELECT STR_TO_DATE('2024-06-13', '%Y-%m-%d');

结果:2024-06-13

9. ADDDATE(date, interval)

给定日期加上一个时间间隔(年、月、日等)。

SELECT ADDDATE('2024-01-01', INTERVAL 1 MONTH);

结果:2024-02-01

10. LAST_DAY(date)

返回一个月份的最后一天。

SELECT LAST_DAY('2024-01-15');

结果:2024-01-31

11. MONTH(), DAY(), YEAR(), HOUR(), MINUTE(), SECOND()

从日期时间值中提取特定的部分。

SELECT YEAR('2024-06-13 12:30:00'), MONTH('2024-06-13 12:30:00'), DAY('2024-06-13 12:30:00');

结果:2024 6 13

流程函数

1. 控制流程函数

这些函数主要用于控制 SQL 语句的执行流程,虽然它们并不直接类似于编程语言中的流程控制结构。

  • CASE 表达式:类似于编程语言中的 if-else 语句,用于基于条件选择不同的值。

    SELECT column1,CASE WHEN condition1 THEN result1WHEN condition2 THEN result2ELSE result3END AS new_column
    FROM table_name;
    
  • IF() 函数(在某些数据库系统中可用):直接返回条件为真的结果。

    SELECT IF(column1 > 0, 'Positive', 'Non-positive') AS sign
    FROM table_name;
    

2. 窗口函数

窗口函数允许你对一组行执行计算,这些行与当前行有某种关系(例如,它们可能是查询结果集中当前行的一部分)。

  • ROW_NUMBER():为结果集中的每行分配一个唯一的连续整数。

    SELECT ROW_NUMBER() OVER (ORDER BY column1) AS row_num, column1
    FROM table_name;
    
  • RANK():为结果集中的每行分配一个排名,相同值的行将获得相同的排名。

    SELECT RANK() OVER (ORDER BY column1 DESC) AS rank, column1
    FROM table_name;
    
  • DENSE_RANK():类似于 RANK(),但排名之间没有间隔。

    SELECT DENSE_RANK() OVER (ORDER BY column1 DESC) AS dense_rank, column1
    FROM table_name;
    

3. 递归查询

在支持递归查询的数据库系统中(如 PostgreSQL、SQL Server 等),可以使用递归公用表表达式(CTE)来实现递归。

  • 递归 CTE:用于执行递归查询。
    WITH RECURSIVE cte (column1, column2) AS (SELECT column1, column2 FROM table_name WHERE conditionUNION ALLSELECT t.column1, t.column2 FROM table_name t INNER JOIN cte ON condition
    )
    SELECT * FROM cte;
    

第四节 约束

1. 主键约束(PRIMARY KEY)

确保列(或列的组合)中的每个值都是唯一的,并且不允许 NULL 值。

CREATE TABLE Employees (EmployeeID int NOT NULL,FirstName varchar(50),LastName varchar(50),Email varchar(100),PRIMARY KEY (EmployeeID)
);

2. 外键约束(FOREIGN KEY)

用于在两个表之间建立链接,并确保引用的数据的完整性。

CREATE TABLE Orders (OrderID int NOT NULL,EmployeeID int,OrderDate date,PRIMARY KEY (OrderID),FOREIGN KEY (EmployeeID) REFERENCES Employees(EmployeeID)
);

3. 唯一约束(UNIQUE)

保证列中的所有值都是不同的。

CREATE TABLE Students (StudentID int NOT NULL,FirstName varchar(50),LastName varchar(50),Email varchar(100) UNIQUE
);

4. 非空约束(NOT NULL)

确保列中的值不能为 NULL。

CREATE TABLE Products (ProductID int NOT NULL,ProductName varchar(100) NOT NULL,Price decimal(10, 2)
);

5. 检查约束(CHECK)

确保列中的值满足特定的条件。

CREATE TABLE Products (ProductID int NOT NULL,ProductName varchar(100) NOT NULL,Price decimal(10, 2),CHECK (Price > 0)
);

6. 默认值约束(DEFAULT)

当没有为列提供值时,将自动填充一个默认值。

CREATE TABLE Employees (EmployeeID int NOT NULL,FirstName varchar(50),LastName varchar(50),Email varchar(100),Salary decimal(10, 2) DEFAULT 50000,PRIMARY KEY (EmployeeID)
);

7. 级联约束(CASCADE)

通常与外键约束一起使用,用于定义当被引用的键被更新或删除时,应该对引用的键执行什么操作。

CREATE TABLE Orders (OrderID int NOT NULL,EmployeeID int,OrderDate date,PRIMARY KEY (OrderID),FOREIGN KEY (EmployeeID) REFERENCES Employees(EmployeeID) ON DELETE CASCADE ON UPDATE CASCADE
);

8. 索引(INDEX)

虽然不是标准的约束类型,但索引用于优化查询性能,可以强制数据的排序和查找。

CREATE INDEX idx_lastname ON Employees (LastName);

第五节 多表查询

一.多表查询关系

多表查询通常涉及到两个或多个表之间的关系,这些关系可以是显式的(如通过外键约束定义)或隐式的(在查询中指定)。

1. 一对一关系(One-to-One Relationship)

在一对一关系中,一个表中的每一行只与另一个表中的一行相关联。这种关系较少见,因为通常可以将这两个表合并为一个表。

示例:
SELECT a.column1, b.column2
FROM table1 a
INNER JOIN table2 b ON a.id = b.id;

2. 一对多关系(One-to-Many Relationship)

在一对多关系中,一个表中的一行可以与另一个表中的多行相关联。这是最常见的关系类型,例如,一个客户可以有多个订单。

示例:
SELECT customers.name, orders.order_date
FROM customers
INNER JOIN orders ON customers.id = orders.customer_id;

3. 多对多关系(Many-to-Many Relationship)

在多对多关系中,一个表中的多行可以与另一个表中的多行相关联。这种关系通常需要通过一个中间表(也称为联结表或关联表)来实现。

示例:

假设有两个表 studentscourses,它们通过中间表 enrollments 相关联。

SELECT students.name, courses.name
FROM students
INNER JOIN enrollments ON students.id = enrollments.student_id
INNER JOIN courses ON enrollments.course_id = courses.id;

二.连接类型

在多表查询中,可以使用不同类型的连接来检索数据:

  • 内连接(INNER JOIN):只返回两个表中匹配的行。
  • 左连接(LEFT JOIN):返回左表的所有行,即使右表中没有匹配的行。
  • 右连接(RIGHT JOIN):返回右表的所有行,即使左表中没有匹配的行。
  • 全外连接(FULL OUTER JOIN):返回两个表中任一表的所有行,如果某一侧没有匹配的行,则该侧的结果为 NULL
  • 内连接(INNER JOIN)是 SQL 中最常用的连接类型之一,用于结合两个或多个表中相关的数据记录。内连接只返回两个表中匹配条件的行,即两个表中都有对应值的记录。
内连接

内连接的基本语法如下:

SELECT column_list
FROM table1
INNER JOIN table2
ON table1.common_field = table2.common_field;
  • column_list:你想从连接的结果中选择的列列表。
  • table1table2:你想要连接的表名。
  • common_field:两个表中用于匹配行的共同列名。

不建议隐式内连接,无关键字而指代不清晰,如有需求再看

示例

假设有两个表:Employees(员工表)和Departments(部门表),它们通过 DepartmentID 相关联。

Employees 表:

  • EmployeeID(员工ID)
  • FirstName(名字)
  • LastName(姓氏)
  • DepartmentID(部门ID)

Departments 表:

  • DepartmentID(部门ID)
  • DepartmentName(部门名称)

要获取每位员工及其所在部门的名称,可以使用以下 SQL 语句:

SELECT Employees.FirstName, Employees.LastName, Departments.DepartmentName
FROM Employees
INNER JOIN Departments ON Employees.DepartmentID = Departments.DepartmentID;
操作说明
  1. 选择相关列:从两个表中选择需要显示的列。在这个例子中,选择了员工的名字、姓氏和部门名称。

  2. 指定连接条件:使用 ON 子句指定连接条件,即 Employees.DepartmentID = Departments.DepartmentID。这表示只返回两个表中 DepartmentID 匹配的行。

  3. 返回匹配行:查询结果将只包含 DepartmentID 在两个表中都存在的行。

外连接

外连接(OUTER JOIN)是 SQL 中的一种连接类型,它用于返回两个表中满足连接条件的行,以及不满足条件的行。外连接包括左外连接(LEFT JOIN)、右外连接(RIGHT JOIN)和全外连接(FULL JOIN)三种类型。

左外连接(LEFT JOIN)返回左表(LEFT JOIN 左边的表)的所有行,即使右表中没有匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列为空值。例如,以下语句展示了如何使用左外连接来获取员工及其部门名称,即使某些员工没有分配部门:

SELECT e.name, d.department_name
FROM employees e
LEFT JOIN departments d ON e.department_id = d.department_id;

左外连接的结果特点是包含左表所有记录,右表无匹配时显示NULL。

右外连接(RIGHT JOIN)与左外连接相反,它返回右表(RIGHT JOIN 右边的表)的所有记录,即使左表中没有匹配的行。如果右表中的记录在左表中没有匹配,则左表的列会显示为 NULL。例如:

SELECT e.name, d.department_name
FROM employees e
RIGHT JOIN departments d ON e.department_id = d.department_id;

右外连接的结果特点是包含右表所有记录,左表无匹配时显示NULL。

全外连接(FULL JOIN)结合了左外连接和右外连接的结果,包含两个表中的所有记录,无论是否有匹配。无匹配的部分显示为 NULL。例如:

SELECT * FROM employees
LEFT JOIN departments USING(department_id)
UNION
SELECT * FROM employees
RIGHT JOIN departments USING(department_id);

全外连接的结果特点是包含两个表所有记录,无匹配部分显示NULL。
左外连接(LEFT JOIN)和右外连接(RIGHT JOIN)是 SQL 中用于执行多表查询的两种不同的连接类型。每种连接类型都有其特定的用途和结果集,但在某些情况下,一个左外连接可以通过调整为右外连接,反之亦然。这种转换可以通过改变连接的表和条件来实现。

左外连接转换为右外连接

左外连接返回左表的所有行,即使右表中没有匹配的行。如果右表中没有匹配的行,则结果中右表的列会是 NULL

要将左外连接转换为右外连接,需要交换两个表的位置,并调整 ON 子句中的条件。

示例:

假设有两个表 employeesdepartments,其中 employees 表有一个外键 department_id 指向 departments 表的主键 id

左外连接:

SELECT employees.name, departments.department_name
FROM employees
LEFT JOIN departments ON employees.department_id = departments.id;

转换为右外连接:

SELECT departments.department_name, employees.name
FROM departments
RIGHT JOIN employees ON employees.department_id = departments.id;
自连接

自连接是一种特殊的数据库连接操作,其中一个表与自身进行连接。

SELECT a.column1, b.column2
FROM table_name AS a
JOIN table_name AS b ON a.common_field = b.common_field;
  • table_name 是进行自连接的表名。
  • ab 是该表的别名,用于区分连接的两个部分。
  • common_field 是用于连接的共同字段。
示例查询:查找每位员工及其经理的姓名
SELECT a.name AS Employee, b.name AS Manager
FROM employees AS a
JOIN employees AS b ON a.manager_id = b.employee_id;

在这个查询中:

  • abemployees 表的别名。
  • a 代表下属员工,b 代表经理。
  • 连接条件 a.manager_id = b.employee_id 确保每位员工与其经理正确匹配。
  1. 别名:在自连接中,别名非常重要,因为它们帮助区分连接的两个部分。
  2. 连接条件:确保连接条件正确,以反映表中的实际关系。
  3. 性能:自连接可能会影响查询性能,特别是在大型数据集上。优化查询和使用索引可以提高效率。
联合连接

UNIONUNION ALL 是 SQL 中用于合并两个或多个查询结果集的关键词,它们之间的主要区别在于是否去除重复行。

UNION

UNION 用于合并两个或多个 SELECT 语句的结果集,并自动去除结果集中的重复行。每个 SELECT 语句必须具有相同数量的列,并且相应的列必须具有兼容的数据类型。

示例:

SELECT name FROM customers
UNION
SELECT name FROM suppliers;

这个查询会返回 customers 表和 suppliers 表中所有不重复的名字列表。

UNION ALL

UNION ALL(或简单地写作 UNION)与 UNION 类似,但它不会去除结果集中的重复行,即保留所有行,包括重复的行。

示例:

SELECT name FROM customers
UNION ALL
SELECT name FROM suppliers;

这个查询会返回 customers 表和 suppliers 表中的所有名字,包括重复的名字。

区别

  • 去重UNION 会去除重复行,而 UNION ALL 不会。
  • 性能:如果不需要去重,使用 UNION ALL 可能会更快,因为数据库不需要额外处理来识别和去除重复行。

在实际使用中,选择 UNION 还是 UNION ALL 取决于是否需要去除结果集中的重复数据。如果需要一个不包含重复项的列表,使用 UNION;如果需要包含所有项,包括重复的,使用 UNION ALL

三.子查询和派生表

  • 子查询:在主查询中嵌套的查询,通常用于筛选或计算。
    SELECT * FROM (SELECT column1, column2 FROM table1 WHERE condition
    ) AS derived_table;
    
    子查询(Subquery)是嵌套在另一个查询中的 SQL 查询,它可以在 SELECTINSERTUPDATEDELETE 语句中使用。子查询通常用于从数据库检索数据,然后将其作为条件或值传递给外部查询。

子查询的基本用法

子查询可以出现在 SQL 语句的 WHERE 子句、HAVING 子句、SELECT 列表、FROM 子句或 JOIN 子句中。

1. 在 WHERE 子句中使用子查询
SELECT column_name(s)
FROM table_name
WHERE column_name IN (SELECT column_name FROM other_table WHERE condition);

这个子查询从 other_table 中选择符合特定条件的 column_name 值,然后在外部查询中检查 table_name 中的 column_name 是否存在于这些值中。

2. 在 SELECT 列表中使用子查询
SELECT column_name, (SELECT MAX(column_name) FROM other_table) AS max_value
FROM table_name;

这个子查询为 table_name 的每一行检索 other_tablecolumn_name 的最大值。

3. 在 FROM 子句中使用子查询(派生表)
SELECT a.column_name, b.column_name
FROM table_name a, (SELECT column_name FROM other_table WHERE condition) b;

或者使用 WITH 子句(公用表表达式,CTE)在 SQL 标准中:

WITH DerivedTable AS (SELECT column_name FROM other_table WHERE condition
)
SELECT a.column_name, b.column_name
FROM table_name a, DerivedTable b;

这个子查询创建了一个派生表,该表可以在外部查询中像普通表一样使用。

4. 在 JOIN 子句中使用子查询
SELECT a.column_name, b.column_name
FROM table_name a
JOIN (SELECT column_name FROM other_table WHERE condition) b ON a.common_field = b.common_field;

这个子查询在 JOIN 操作中使用,将 other_table 表中符合特定条件的行与 table_name 表进行连接。

注意
  • 子查询必须用括号括起来。
  • 子查询可以是任何有效的 SELECT 语句,包括使用聚合函数、GROUP BY 子句或 HAVING 子句。
  • 子查询的结果集必须与外部查询的相应部分兼容(例如,外部查询的 WHERE 子句中使用子查询时,子查询的结果集应该是一个单一的列)。

分类

1.标量子查询

标量子查询的常见用途包括:

  1. 作为条件:在 WHERE 子句中使用标量子查询来过滤结果。

    SELECT * FROM emp
    WHERE salary > (SELECT AVG(salary) FROM emp);
    

    在这个例子中,标量子查询 (SELECT AVG(salary) FROM emp) 用于找出工资高于平均工资的员工。

  2. 作为列值:在 SELECT 列表中使用标量子查询来计算或获取额外的列值。

    SELECT empno, name, (SELECT deptno FROM dept WHERE deptno = emp.deptno) AS deptno
    FROM emp;
    

    这里,标量子查询 (SELECT deptno FROM dept WHERE deptno = emp.deptno) 用于获取与员工部门表中相应部门编号匹配的部门编号。

  3. 作为排序依据:在 ORDER BY 子句中使用标量子查询来对结果进行排序。

    SELECT * FROM emp
    ORDER BY (SELECT COUNT(*) FROM orders WHERE orders.empno = emp.empno) DESC;
    

    这个例子中,标量子查询 (SELECT COUNT(*) FROM orders WHERE orders.empno = emp.empno) 用于根据员工的订单数量对员工进行排序。

2.列子查询

列子查询通常用于在 SELECT 语句中计算派生列(Derived Column)的值。例如,你可能想要在查询结果中包含一个计算字段或从另一个表中检索的值。

SELECT column1, (SELECT column2 FROM other_table WHERE condition) AS alias
FROM table1;

在这个例子中,子查询 (SELECT column2 FROM other_table WHERE condition) 被用来为 table1 的每一行计算或检索一个值,并将这个值作为 alias 列返回。
假设有两个表:employeesdepartmentsemployees 表包含员工信息,而 departments 表包含部门信息。每个员工属于一个部门,部门有一个 department_id

employees 表结构:

  • employee_id
  • name
  • department_id

departments 表结构:

  • department_id
  • department_name

要获取所有员工及其部门名称,可以使用列子查询:

SELECT e.name, d.department_name
FROM employees e
JOIN departments d ON e.department_id = d.department_id;

实现相同的结果,可以这样做:

SELECT e.name, (SELECT d.department_name FROM departments d WHERE d.department_id = e.department_id) AS department_name
FROM employees e;

在这个例子中,子查询 (SELECT d.department_name FROM departments d WHERE d.department_id = e.department_id)employees 表中的每个员工检索相应的部门名称。

注意事项
  • 列子查询必须返回单个值,或者与外部查询的行数相匹配的值。
  • 如果子查询返回多行,那么外部查询的每一行都会与子查询返回的每一行进行组合,这可能导致结果集的行数急剧增加(笛卡尔积)。
  • 在使用列子查询时,确保子查询的逻辑正确,以避免产生错误的结果或性能问题。
表子查询

表子查询的基本语法如下:

SELECT column_list
FROM (SELECT column_listFROM table_nameWHERE condition
) AS alias_name
WHERE another_condition;
  • column_list 是你想选择的列名列表。
  • table_name 是原始表的名称。
  • condition 是用于筛选原始表中行的条件。
  • alias_name 是子查询结果集的别名,用于在外部查询中引用。

要获取所有员工及其部门名称,可以使用表子查询:

SELECT e.name, d.department_name
FROM employees e
JOIN (SELECT department_id, department_nameFROM departments
) d ON e.department_id = d.department_id;

在这个例子中,子查询 SELECT department_id, department_name FROM departments 作为一个临时表,与 employees 表进行连接。

  • 派生表:在 FROM 子句中定义的子查询,可以像普通表一样使用。
    SELECT a.*, b.*
    FROM table1 a
    JOIN (SELECT * FROM table2 WHERE condition
    ) b ON a.common_field = b.common_field;
    

第六节 事务

事务(Transaction)是数据库管理系统中的一个核心概念,用于确保数据的完整性和一致性。在 SQL 中,事务是一组不可分割的操作序列,这些操作要么全部成功,要么全部不做,是一个原子操作单元。

事务的特性

事务具有 ACID 特性,即:

  • 原子性(Atomicity):事务中的所有操作要么全部完成,要么全部不做,不能只执行其中的一部分。
  • 一致性(Consistency):事务执行前后,数据库保持一致性状态。
  • 隔离性(Isolation):事务的执行不受其他并发事务的干扰,事务之间是相互隔离的。
  • 持久性(Durability):一旦事务提交,则其结果将永久保存在数据库中,即使系统发生故障也不会丢失。
事务的操作

事务的操作通常包括:

  • 开始事务:标记事务的开始。
  • 提交事务:将事务中的所有修改永久保存到数据库中。
  • 回滚事务:撤销事务中的所有修改,保持数据库状态不变。
SQL 中的事务语句

在 SQL 中,可以使用以下语句来控制事务:

  • BEGIN TRANSACTIONSTART TRANSACTION:开始一个新的事务。
  • COMMIT:提交当前事务,将事务中的所有修改永久保存到数据库。
  • ROLLBACK:回滚当前事务,撤销事务中的所有修改。
  • SAVEPOINT:创建事务的保存点,可以在回滚时指定回滚到某个保存点。
事务的使用示例
-- 开始事务
START TRANSACTION;-- 执行一些操作
UPDATE account SET balance = balance - 100 WHERE account_id = 1;
UPDATE account SET balance = balance + 100 WHERE account_id = 2;-- 提交事务,使操作永久生效
COMMIT;-- 如果需要回滚
ROLLBACK;
  • 性能:虽然事务确保了数据的安全性,但过多或过长的事务可能会影响数据库性能。
  • 锁定:事务可能会导致数据库锁定,影响其他用户的访问。
  • 错误处理:在事务中的错误需要被适当处理,以避免事务失败。
  • 自动提交:许多数据库系统默认在每个单独的 SQL 语句后自动提交事务,可以通过设置数据库的自动提交行为来改变这一行为。
  • 并发事务问题通常出现在多用户同时对数据库进行读写操作时,可能会导致数据的不一致性。这些问题包括:
  1. 脏读(Dirty Read):一个事务读取了另一个事务未提交的修改数据。
  2. 不可重复读(Non-repeatable Read):在同一事务中,多次读取同一数据集合时,由于其他事务的修改,导致读取结果不一致。
  3. 幻读(Phantom Read):在同一事务中,多次查询时,结果集的行数不一致,看起来像是出现了“幻影”的行。这通常是由其他事务插入或删除了符合查询条件的行导致的。

事务隔离级别是解决这些问题的关键机制,它定义了事务间的隔离程度。SQL标准定义了四个隔离级别:

  1. 读未提交(Read Uncommitted):最低隔离级别,允许脏读,因为事务可以读取未提交事务修改的数据。
  2. 读已提交(Read Committed):确保事务只能读取已提交的数据,避免了脏读,但可能会出现不可重复读和幻读。
  3. 可重复读(Repeatable Read):保证在同一事务中多次读取同一数据集合时,结果是一致的,避免了不可重复读,但幻读仍有可能发生。
  4. 串行化(Serializable):最高隔离级别,事务完全隔离,像事务是串行执行的一样,避免了脏读、不可重复读和幻读,但可能会牺牲一些并发性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.tpcf.cn/diannao/91150.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Docker 高级管理--Dockerfile镜像制作

二:Dockerfile 语法基础 1:基础指令 (1)FROM 指定基础镜像&#xff0c;所有的 Dockerfile 都必须以 FROM 指令开头&#xff0c;它定义了新镜像基于哪个基础镜像构建。 FRoM ubuntu:20.04 (2)MAINTAINER(已奔用&#xff0c;推荐使用LABEL) 用于指定镜像的维护者信息。不过在较…

LeetCode 692题解 | 前K个高频单词

前K个高频单词一、题目链接二、题目三、分析四、代码一、题目链接 692.前K个高频单词 二、题目 三、分析 本题目我们利用map统计出次数以后&#xff0c;返回的答案应该按单词出现频率由高到低排序&#xff0c;有一个特殊要求&#xff0c;如果不同的单词有相同出现频率&#…

C++ 中的 std::bind 用法

在现代 C++ 编程中,std::bind 是一个非常强大但常常被误解的工具。它允许我们将函数(包括成员函数)、参数进行绑定,并生成一个新的可调用对象。这在编写异步回调、事件处理、适配器模式等场景中非常有用。 🔧 一、std::bind 是什么? std::bind 是定义在 <functiona…

Spring Boot秒级冷启动方案:阿里云FC落地实战(含成本对比)

Spring Boot秒级冷启动方案&#xff1a;阿里云FC落地实战&#xff08;含成本对比&#xff09;一、冷启动痛点与FC核心优势1. 传统Spring Boot冷启动瓶颈2. 阿里云FC核心能力二、秒级冷启动架构设计1. 整体架构2. 关键组件选型三、5大核心优化策略1. 应用瘦身&#xff08;JAR包精…

搜索引擎vs向量数据库:LangChain混合检索架构实战解析

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。一、LangChain搜索工具实战&#xff1a;集成DuckDuckGo实现实时信息查询 核心场景&#xff1a;解决大模型知识滞后问题&#xff0c;通过搜索引擎获取实…

【算法】贪心算法:将数组和减半的最少操作次数C++

文章目录前言题目解析算法原理代码示例策略证明前言 题目的链接&#xff0c;大家可以先试着去做一下再来看一下思路。2208. 将数组和减半的最少操作次数 - 力扣&#xff08;LeetCode&#xff09; 题目解析 要认真去把题目看一遍&#xff0c;画出题目中的有用信息。 示例一定是…

git异常退出,应该是内存不足

这次下载代码&#xff1a; 公司虚拟机到了一定步骤&#xff0c;肯定退出。而家里的虚拟机则完全正常。我把家里的虚拟机复制到公司&#xff0c;还是崩溃。 差异在哪里&#xff1f;公司电脑虚拟机内存设置为10G&#xff0c;家里的16。因为家里电脑64G内存。 后来确认&#xff…

机器学习13——支持向量机下

支持向量机下 非线性支持向量机&#xff08;Non-linear SVMs&#xff09;详解 核心思想 当数据在原始空间线性不可分时&#xff0c;通过**核技巧&#xff08;Kernel Trick&#xff09;**将数据映射到高维特征空间&#xff0c;使其在该空间中线性可分。 比如以下的样本在一维空间…

GPT-4和Claude哪个好

选择GPT-4还是Claude?这就像在问“苹果还是橙子哪个更好”——‌答案完全取决于你的具体需求‌。两者都是顶尖大语言模型,但各有特色。 我为你做了详细对比,帮你快速定位哪个更适合你: 🧠 核心能力对比 特性GPT-4 (OpenAI)Claude (Anthropic)‌语言理解/推理‌顶尖水平,…

RHCE考试 ——笔记

RHCE模拟测试exam_start ehcerht-vmctl start all考前说明• 请勿更改 IP 地址。DNS 解析完整主机名&#xff0c;同时也解析短名称。• 所有系统的 root 密码都是 redhat• Ansible 控制节点上已创建用户账户 devops。可以使用 ssh 访问• 所需的所有镜像保存在镜像仓库 utilit…

信创 CDC 实战 | TiDB 实时入仓难点与解决方案解析(以 ClickHouse 为例)

国产数据库加速进入核心系统&#xff0c;传统同步工具却频频“掉链子”。本系列文章聚焦 OceanBase、GaussDB、TDSQL、达梦等主流信创数据库&#xff0c;逐一拆解其日志机制与同步难点&#xff0c;结合 TapData 的实践经验&#xff0c;系统讲解从 CDC 捕获到实时入仓&#xff0…

Linux修炼:自动化构建make/Makefile

Hello大家好&#xff01;很高兴我们又见面啦&#xff01;给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 我的博客&#xff1a;<但凡. 我的专栏&#xff1a;《编程之路》、《数据结构与算法之美》、《C修炼之路》、《Linux修炼&#xff1a;终端之内 洞悉真理…

GaussDB 分布式部署下创建表方法

1、问题现象 分布式集群采用水平分表的方式,将业务数据表的元组/行打散存储到各个节点内。 2、技术背景 通过全并行数据处理技术和快速定位到数据存储位置等手段可极大提升数据库性能,GaussDB分布式部署下可以创建俩种类型表,在做实际业务系统开发时根据业务场景创建不同表。…

Padavan路由器设置DNSmasq的DHCP Option

是下文的拓展&#xff1a;由于更换路由器为Padavan&#xff0c;需要配置DHCP option才能使得AC能够纳管AP 爱快路由器下水星&#xff08;Mercury&#xff09;无线管理器AC跨三层发现AP_爱快管理第三方ap-CSDN博客 DNSmasq全部配置请参考&#xff1a;Man page of DNSMASQ dhcp-…

Ubuntu 22.04 Server 虚拟机初始化配置与优化指南

✅ Ubuntu 22.04 本地/通用服务器初始化配置清单 1. 设置时区 sudo timedatectl set-timezone Asia/Shanghai2. 防火墙配置&#xff08;UFW&#xff09; sudo ufw enable sudo ufw default deny # 可选放通SSH或其他端口 sudo ufw allow 22/tcp # 查看状态 sudo ufw status # 禁…

如何在服务器上运行一个github项目

一、事情的缘起 今天一个朋友向我推荐了小红书上的一个视频&#xff0c;我看了一下这是一个在演示TypeWords项目的视频。这个项目是Github上采用vue来编写的一个开源项目。我进入该项目后看到了给出的样例网址2study.top&#xff0c;然后到上面看了一下。我发现这是一个通过打…

7.14 Java基础|String 和StringBuilder

补充注意&#xff1a;1、StringBuilder 的 append 方法可以接收整数类型的参数&#xff0c;并将其自动转换为字符串后添加到 StringBuilder 中2、该方法适用于所有基本数据类型&#xff08;如 long、double 等&#xff09;和对象&#xff08;通过调用其 toString() 方法&#x…

React 第六十九节 Router中renderMatches的使用详解及注意事项

前言 renderMatches 是 React Router 的一个高级实用函数&#xff0c;用于根据路由匹配结果渲染对应的组件树。它提供了对路由渲染过程的底层控制能力&#xff0c;特别适用于自定义路由渲染逻辑的场景。 一、基本概念和功能 renderMatches 函数的作用是将路由匹配结果转换为 Re…

esp8266-01S实现PPM波形

esp8266-01虽然小众&#xff0c;但是功能可不能少。因航模需要让ESP8266-01生成PPM波形。#include <ESP8266WiFi.h> #include <Ticker.h> // 仅用于延时函数替代#define PPM_PIN 2 // 使用 GPIO2 (需断开串口上传时的连接) #define CHANNELS 4 // PPM通道数量…

使用 pytest 测试框架构建自动化测试套件之一

pytest 是一个非常灵活且强大的测试框架&#xff0c;它支持简单的单元测试到复杂的功能测试。显著特点是其简洁的语法&#xff0c;可以无需继承 TestCase 类直接使用函数来编写测试用例&#xff0c;并通过 assert语句 进行断言。还支持参数化测试、丰富的插件系统。 pytest自动…