记MYSQL相关资料—结构化查询语言

记MYSQL相关资料

我电脑win10系统,mysql版本是5.7的。

MySQL 5.7数据库是一种开源的关系型数据库管理系统。

关系型数据库:
	基于关系模型,其中数据被组织为表(或称为关系)。

结构化查询语言(SQL):
	数据定义语言(DDL):用于数据库、数据表的定义。例如:建库、建表、改表、删表、索引、约束等。
	数据操作语言(DML):用于操作数据表记录。例如:新增、更新、删除。
	数据查询语言(DQL):用于查询数据表记录。例如:全查,排序查、分组查、关联查。
	数据控制语言(DCL):用户授权操作。例如:添加用户账号。
	事务控制语言(TCL):用于管理对数据库的一系列操作,确保这些操作要么全部成功执行,要么全部回滚,以保持数据的一致性和完整性。

结构化查询语言(SQL)

DDL语言

DDL(Data Definition Language,数据定义语言)语句包含以下命令:
create:用于创建数据库、表、视图、索引、存储过程等。
alter:用于修改数据库、表、列、约束等的结构。
drop:用于删除数据库、表、视图、索引、存储过程等。
raname:用于重命名数据库对象,如表、列、约束等。
comment:用于添加注释或描述信息到数据库对象。
这些命令用于定义和管理数据库的结构,用于创建、修改、删除数据库对象。

数据格式

数值类型
整数类型:INT、TINYINT、SMALLINT、MEDIUMINT、BIGINT;浮点数类型:FLOAT、DOUBLE、DECIMAL
字符串类型
固定长度字符串:CHAR、可变长度字符串:VARCHAR、长文本字符串:TEXT、枚举类型:ENUM、集合类型:SET
日期和时间类型
日期:DATE、时间:TIME、日期和时间:DATETIME、时间戳:TIMESTAMP
二进制类型
固定长度二进制数据:BINARY、可变长度二进制数据:VARBINARY、二进制大对象,存储大量二进制数据:BLOB
其他类型
BOOLEAN:布尔类型,可以存储 TRUE 或 FALSE
JSON:存储 JSON 格式的数据
GEOMETRY:存储几何类型数据

TEXT类型补充

TEXT类型是用来存储较大文本数据的数据类型。在MySQL中,有四种不同的TEXT类型可供选择:
TINYTEXT:最大长度为255个字符。255B存储空间
TEXT:最大长度为65535个字符。64KB存储空间
MEDIUMTEXT:最大长度为16,777,215个字符。16MB存储空间
LONGTEXT:最大长度为4,294,967,295个字符。4G存储空间
这些TEXT类型可以存储任何字符数据,包括文本、二进制数据和XML数据等。TEXT类型的存储大小是可变的,根据存储的数据量而变化。对于较大的文本数据,建议使用MEDIUMTEXT或LONGTEXT类型。
在MySQL中,TEXT类型的字段可以使用INSERT语句插入数据,使用SELECT语句查询数据,并可以使用UPDATE语句更新数据。可以使用LIKE运算符进行模糊查询,也可以使用内置的函数对TEXT类型的数据进行处理和操作。
需要注意的是,由于TEXT类型存储的数据量较大,因此在进行查询和排序等操作时可能会影响性能。此外,TEXT类型的字段在索引和排序方面的支持相对有限。

创库创表

图书管理系统
实体一:图书。属性:书籍ID、书名、作者、出版日期、价格。
实体二:用户。属性:用户ID、用户名、密码、姓名、联系方式。
实体三:借阅记录。属性:记录ID、用户ID、书籍ID、借阅日期、归还日期。
学生信息管理系统
实体一:班级。属性:班级ID、班级名称
实体二:学生。属性:学生ID、学生姓名、学生年龄、学生性别、所属班级ID
实体三:教师。属性:教师ID、教师姓名
实体四:课程。属性:课程ID、课程名称、授课教师ID
实体五:成绩。属性:成绩ID、学生ID、课程ID、成绩

实现方式
方式一:MySQL可视化工具(navicat、sqlyog)
方式二:MySQL命令行客户端(MySQL 5.7 Command Line Client)

图书管理系统
创建数据库:

创建数据表:
	CREATE TABLE books (
		book_id INT PRIMARY KEY,
		title VARCHAR(100),
		author VARCHAR(100),
		publish_date DATE,
		price DECIMAL(8, 2)
	);
	
	CREATE TABLE users (
		user_id INT PRIMARY KEY,
		username VARCHAR(100),
		password VARCHAR(100),
		name VARCHAR(100),
		contact VARCHAR(100)
	);
	
	CREATE TABLE borrow_records (
		record_id INT PRIMARY KEY,
		user_id INT,
		book_id INT,
		borrow_date DATE,
		return_date DATE,
		FOREIGN KEY (user_id) REFERENCES users(user_id),
		FOREIGN KEY (book_id) REFERENCES books(book_id)
	);

创建索引:
	CREATE INDEX idx_books_title ON books(title);
	CREATE INDEX idx_users_username ON users(username);

设计视图:
	CREATE VIEW book_borrowed_view AS
	SELECT b.title, u.name, br.borrow_date, br.return_date
	FROM books b
	JOIN borrow_records br ON b.book_id = br.book_id
	JOIN users u ON u.user_id = br.user_id;

设计一个存储过程来借阅图书,并更新借阅记录和书籍库存。
	DELIMITER //
	CREATE PROCEDURE borrow_book(IN p_user_id INT, IN p_book_id INT, IN p_borrow_date DATE)
	BEGIN
	-- 插入借阅记录
	INSERT INTO borrow_records (user_id, book_id, borrow_date)
	VALUES (p_user_id, p_book_id, p_borrow_date);
	
	-- 更新书籍库存
	UPDATE books SET stock = stock - 1 WHERE book_id = p_book_id;
	END //
	DELIMITER ;

上述代码中,我们首先使用 DELIMITER 关键字来修改语句的分隔符,以便在存储过程中使用多条 SQL 语句。
使用 CREATE PROCEDURE 关键字来创建一个名为 borrow_book的存储过程。
IN 关键字用于声明输入参数,这里我们声明了三个输入参数 p_user_id、p_book_id、p_borrow_date 。
在存储过程的主体中,我们使用 SELECT 语句查询满足条件的用户信息。最后,使用 DELIMITER 关键字将分隔符恢复为原来的状态。

设计一个触发器的使用案例:
	假设我们有一个订单表(order),包含字段 id、user_id 和 total_amount。我们想要设计一个触发器,在插入新订单时自动更新用户的总消费金额。以下是一个示例触发器的设计和使用:
	CREATE TRIGGER UpdateUserTotalAmount AFTER INSERT ON order
	FOR EACH ROW
	BEGIN
		UPDATE user SET total_amount = total_amount + NEW.total_amount WHERE id = NEW.user_id;
	END;
	
上述代码中,我们使用 CREATE TRIGGER 关键字创建一个名为 UpdateUserTotalAmount 的触发器。
AFTER INSERT ON order 指定了触发器的执行时机,即在订单表插入新记录后触发。
FOR EACH ROW 表示触发器对每一行记录都执行一次。
在触发器的主体中,我们使用 UPDATE 语句更新用户表中对应用户的总消费金额。
NEW 是一个引用新插入的记录的伪表,可以通过 NEW.column_name 的方式引用列值。


导入数据:
	INSERT INTO books (book_id, title, author, publish_date, price)
	VALUES (1, 'Book1', 'Author1', '2022-01-01', 29.99),
	(2, 'Book2', 'Author2', '2022-02-01', 39.99);
	
	INSERT INTO users (user_id, username, password, name, contact)
	VALUES (1, 'user1', 'password1', 'User1', 'user1@example.com'),
	(2, 'user2', 'password2', 'User2', 'user2@example.com');
库的增删改查

打开MySQL命令行终端或通过图形化工具连接到MySQL服务器。输入SQL命令完成任务

查看是否存在指定的数据库:

列出当前所有的数据库:SHOW DATABASES;
查看名为 “mydatabase” 的数据库是否存在:SHOW DATABASES LIKE 'mydatabase';

数据库创建、修改、删除:

创建指定编码格式的数据库:CREATE DATABASE 数据库名 CHARACTER SET 字符集 COLLATE 校对规则;
修改现有数据库的字符集和校对规则:ALTER DATABASE 数据库名 CHARACTER SET 字符集 COLLATE 校对规则;
请注意,MySQL支持多种字符集和校对规则,您可以根据需要选择适合您的数据库的字符集和校对规则。
常用的字符集包括 utf8mb4、utf8、latin1 等,常用的校对规则包括utf8mb4_general_ci、utf8_general_ci、latin1_general_ci 等。

使用 CREATE DATABASE 语句创建数据库。
使用 DROP DATABASE 语句删除数据库。
使用 ALTER DATABASE 语句来修改数据库。

在MySQL 5.7中,可以通过设置字符集和校对规则来创建指定编码格式的数据库。以下是创建指定编码格式的数据库的步骤:
-- 创建指定编码格式的数据库
CREATE DATABASE mydatabase CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
解释:创建了一个名为 "mydatabase" 的数据库,使用了 utf8mb4 字符集和 utf8mb4_general_ci 校对规则。

-- 修改现有数据库的字符集和校对规则
ALTER DATABASE mydatabase CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

-- 创建数据库:
create datebase 数据库名;

-- 删除数据库:
drop database 数据库名;
表的增删改查

查看有无数据表:

显示数据库中所有的数据表:SHOW TABLES;
查看指定数据表的结构:DESCRIBE 表名;或者 DESC 表名;
查询information_schema表判断:SELECT * FROM information_schema.tables WHERE table_schema = '数据库名' AND table_name = '表名';

数据表创建、删除、修改:

使用 CREATE TABLE 语句创建数据表。
使用 DROP TABLE 语句删除数据表。这将永久删除数据表及其所有数据
使用 ALTER TABLE 语句来修改数据表。

删除数据表:DROP TABLE 表名;
修改字段名称:ALTER TABLE 表名 RENAME COLUMN 原字段名 TO 新字段名;
修改字段类型:ALTER TABLE 表名 MODIFY COLUMN 字段名 新数据类型;
在已存在的数据表上添加主键:ALTER TABLE 表名 ADD PRIMARY KEY (列名);
在已存在的数据表上添加外键:ALTER TABLE 表名 ADD FOREIGN KEY (当前表列名) REFERENCES 相关表名(相关表列名);

在创建数据表时指定主键:

创建数据表:需要指定表名和表中的列的名称、数据类型以及其他约束条件。

语法:
CREATE TABLE 表名 (
    列名1 数据类型1,
    列名2 数据类型2,
    ...
    列名N 数据类型N,
    约束条件
);

示例:
CREATE TABLE mytable (
    id INT PRIMARY KEY,
    name VARCHAR(50),
    age INT,
    email VARCHAR(100)
);
这将创建一个名为 mytable 的数据表,包含 id、name、age 和 email 四个列。

*******************或者*********************
语法:
CREATE TABLE 表名 (
    列名1 数据类型1,
    列名2 数据类型2,
    ...
    列名N 数据类型N,
    PRIMARY KEY (列名1, 列名2, ... 列名N)
);

示例:
CREATE TABLE mytable (
    id INT,
    name VARCHAR(50),
    age INT,
    email VARCHAR(100),
    PRIMARY KEY (id)
);
这将创建一个名为 mytable 的数据表,并将 id 列指定为主键。


语法:
ALTER TABLE 表名 ADD PRIMARY KEY (列名);

-- 在已存在的数据表上添加主键:
ALTER TABLE mytable ADD PRIMARY KEY (id);
这将在名为 mytable 的数据表上将 id 列指定为主键。

在创建数据表时指定外键:

请注意,添加主键和外键的操作需要满足一些条件,如列的数据类型必须匹配、外键关系必须存在等。如果不满足这些条件,操作将失败。此外,添加外键还需要确保相关表和列的存在,并且正确设置了索引。

语法:
CREATE TABLE 表名 (
    列名1 数据类型1,
    列名2 数据类型2,
    ...
    列名N 数据类型N,
    FOREIGN KEY (当前表列名) REFERENCES 相关表名(相关表列名)
);

示例:
CREATE TABLE orders (
    order_id INT,
    customer_id INT,
    order_date DATE,
    PRIMARY KEY (order_id),
    FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
);

这将创建一个名为 orders 的数据表,其中 customer_id 列是一个外键,参考了另一个数据表 customers 中的 customer_id 列。


语法:
ALTER TABLE 表名 ADD FOREIGN KEY (当前表列名) REFERENCES 相关表名(相关表列名);

-- 在已存在的数据表上添加外键:
ALTER TABLE orders ADD FOREIGN KEY (customer_id) REFERENCES customers(customer_id);

这将在名为 orders 的数据表上添加一个外键,将 customer_id 列指定为参考了另一个数据表 customers 中的 customer_id 列。

索引视图

索引在MySQL数据库中起到了重要的作用,它可以提高查询的效率和性能。索引是一种数据结构,用于加快对数据库表中数据的访问速度。索引的作用主要体现在以下几个方面:
提高查询效率:索引会按照特定的数据结构对表中的数据进行排序和存储,这样可以加速数据库查询的速度。当查询语句中包含索引列时,数据库系统可以使用索引直接定位到符合条件的数据行,而不需要扫描整个表。
优化排序和分组操作:如果查询包含排序或分组操作,索引可以帮助数据库系统避免对整个表进行排序或分组,而是直接利用索引的有序性进行操作,从而提高查询效率。
加速连接操作:当多个表进行连接查询时,索引可以加速连接操作。通过索引,数据库系统可以快速定位到需要连接的行,从而加快连接查询的速度。
提高数据唯一性约束:通过在唯一约束列上创建唯一索引,可以确保表中的数据在该列上具有唯一性,避免出现重复的数据。

索引是如何发挥作用的:索引是通过创建索引结构将索引列的值与对应的数据行进行关联的。在索引结构中,索引列的值被排序并存储在特定的数据结构中,常见的数据结构包括B树和哈希表。当执行查询语句时,数据库系统会根据查询条件和索引的数据结构,使用适当的算法在索引结构中进行搜索,找到满足条件的数据行。
需要注意的是,虽然索引可以提高查询效率,但过多或不合理的索引也可能对数据库性能产生负面影响。索引会占用存储空间,并且在插入、更新和删除数据时需要维护索引结构,增加了数据操作的开销。因此,在创建索引时需要综合考虑查询频率、查询效率和数据操作的频率,避免创建过多或不必要的索引。

查看表的索引信息

命令一:DESCRIBE table_name;

直接看key字段。有值表示该字段是索引,空值表示该字段不是索引

在MySQL 5.7中,使用DESCRIBE语句查看表的索引信息时,如果存在索引,会显示以下信息:
	
列名(Field):显示表的列名。
类型(Type):显示列的数据类型。
空(Null):显示列是否允许为空值。
键(Key):显示列是否是索引的一部分。如果列是主键,则显示为"PRI";如果列是唯一索引的一部分,则显示为"UNI";如果列是非唯一索引的一部分,则显示为"MUL";如果列不是索引的一部分,则显示为空。
默认值(Default):显示列的默认值。
额外信息(Extra):显示其他信息,如自增(auto_increment)等。

命令二:SHOW INDEX FROM table_name;

直接看有无记录。有记录表示有索引,无记录表示没有索引,

在MySQL 5.7中,使用SHOW INDEX FROM语句查看表的索引信息时,如果存在索引,会显示以下数据:

Table:显示索引所属的表名。
Non_unique:显示索引是否是唯一索引。如果是唯一索引,则值为0;如果是非唯一索引,则值为1。
Key_name:显示索引的名称。
Seq_in_index:显示索引中的列的位置。
Column_name:显示索引中的列名。
Collation:显示列的排序规则。
Cardinality:显示索引的基数,即索引中不重复的值的数量。
Sub_part:如果索引是部分索引,则显示部分索引的长度;否则为空。
Packed:表示索引是否被压缩。如果索引被压缩,则值为“NULL”;否则为空。
Null:显示列是否允许为空值。如果允许为空值,则值为“YES”;否则为“NO”。
Index_type:显示索引的类型,如BTREE、HASH等。
Comment:显示索引的注释。
索引的创建和删除

创建索引:

假设有一个名为users的表,其中包含id、name和email字段。我们可以为name和email字段创建索引,以提高查询性能。创建索引的语法如下:CREATE INDEX index_name ON table_name (column_name);

-- 为name字段创建索引
CREATE INDEX idx_name ON users (name);

-- 为email字段创建索引
CREATE INDEX idx_email ON users (email);

上述示例中,我们分别为name和email字段创建了索引。
这样在查询时,MySQL会直接使用索引而不是全表扫描,提高查询效率。

删除索引:

删除索引的语法如下:ALTER TABLE table_name DROP INDEX idx_name;

-- 删除索引名为idx_email的索引
ALTER TABLE table_name DROP INDEX idx_email;
索引的优化

在创建索引后,还可以进一步优化索引以提高查询性能。例如:联合索引、前缀索引、删除冗余索引、…

在实际应用中,需要根据具体的查询需求和数据特点,选择合适的索引策略,并进行性能测试和调优。

添加联合索引

如果查询中经常使用多个字段进行过滤,可以考虑创建联合索引。
创建联合索引的语法如下:CREATE INDEX idx_name_email ON users (column_name1, column_name2);

普通索引是基于单个列的索引,可以提高查询效率。联合索引是基于多个列的索引,可以提高多列条件查询的效率。在使用联合索引的情况下,如果某个查询只涉及到联合索引中的一部分列,而不涉及到其他列,那么普通索引仍然可以起到优化查询的作用。因此,在使用联合索引的同时,如果有需要,仍然可以创建普通索引来提高查询效率。

例如,如果查询经常根据name和email字段进行过滤,可以创建一个联合索引来覆盖这两个字段:
CREATE INDEX idx_name_email ON users (name, email);
这样一来,在查询时MySQL可以直接使用该联合索引,而无需分别使用单独的索引。

需要注意的是,创建索引会增加存储空间和对插入、更新和删除操作的影响。
因此,在创建索引时需要综合考虑查询频率、查询效率和数据操作的频率,以及存储空间的限制。
添加前缀索引

如果某个字段的长度较长,可以考虑使用前缀索引来减少索引的大小和内存占用。

创建前缀索引的语法如下:CREATE INDEX idx_name_prefix ON users (name(前缀字段长度));

例如,如果name字段的长度较长,可以创建一个前缀索引:
创建联合索引的语法如下:CREATE INDEX idx_name_prefix ON users (name(10));
上述示例中,我们创建了一个前缀索引,只索引name字段的前10个字符。
删除冗余索引

在优化索引时,需要检查并删除冗余索引。如果某个字段已经有了一个包含该字段的索引,那么可以删除该字段单独的索引。

例如,如果已经有了一个包含name和email字段的联合索引,那么可以删除name和email字段的单独索引。
ALTER TABLE table_name DROP INDEX idx_name;
ALTER TABLE table_name DROP INDEX idx_email;
更新统计信息

MySQL使用统计信息来决定使用哪个索引执行查询。因此,需要定期更新表的统计信息,以确保MySQL能够正确选择和使用索引。统计数据包括表中每个列的数据分布、唯一值数量和索引的选择性等信息。这些统计数据用于查询优化器决定如何选择最佳的索引来执行查询。以下是常见的统计信息:

表统计信息:包括表的行数、平均行长度、数据大小、索引大小等。
索引统计信息:包括索引的使用情况、索引的大小、索引的碎片情况等。
查询统计信息:包括查询的执行时间、扫描行数、连接数等。
锁统计信息:包括锁的使用情况、死锁情况等。
线程统计信息:包括线程的数量、线程的状态、线程的执行时间等。
缓存统计信息:包括缓存的命中率、缓存的大小等。
日志统计信息:包括日志的写入速度、日志的大小等。

-- 查询索引统计信息:
SHOW INDEX FROM table_name;
-- 查询表统计信息:
SHOW TABLE STATUS LIKE 'table_name';
-- 查询查询统计信息:
SHOW STATUS LIKE 'Com_select';
-- 查询锁统计信息:
SHOW STATUS LIKE 'Innodb_row_lock_%';
-- 查询线程统计信息:
SHOW STATUS LIKE 'Threads%';
-- 查询缓存统计信息:
SHOW STATUS LIKE 'Qcache%';
-- 查询日志统计信息:
SHOW STATUS LIKE 'Innodb_os_log_%';
...通过这些命令可以获取到MySQL数据库的详细统计信息,用于分析和优化数据库性能。

统计信息更新对于对于索引的影响:

1、首先,打开MySQL的查询日志功能。可以通过修改MySQL配置文件(my.cnf或my.ini)或者在MySQL的命令行中执行以下命令来启用查询日志:SET GLOBAL general_log = 'ON';
2、然后,执行需要进行统计信息更新的SQL语句。可以是INSERT、UPDATE或DELETE语句,这些语句会对表中的数据进行修改。
3、接下来,查看MySQL的查询日志,可以通过以下命令查看最新的查询日志文件:SHOW GLOBAL VARIABLES LIKE 'general_log_file';
打开查询日志文件,查找包含执行的SQL语句的日志记录。其中,会显示执行SQL语句前后索引的状态。执行SQL语句前后,可能会有以下情况发生:
索引被更新:如果SQL语句中有对表中数据的修改操作,如INSERT、UPDATE或DELETE语句,那么相关的索引可能会被更新。
索引被重新构建:如果表中的数据变动较大,或者MySQL的自动更新机制触发了索引的重新构建,那么相关的索引可能会被重新构建。
索引的统计信息被更新:MySQL会根据数据的变动情况,自动更新索引的统计信息,以便优化查询计划。这些统计信息包括索引的基数(cardinality)和数据分布等。

通过查看查询日志,可以了解到索引在执行SQL语句前后的状态变化,进而评估统计信息更新对索引的影响。这有助于了解索引的维护机制和优化策略,以及进行索引的优化和调整。

如何更新统计数据来优化索引:

以下是更新统计数据的几种常见方法:
ANALYZE TABLE 命令:使用ANALYZE TABLE命令可以更新表的统计数据。这个命令会扫描整个表并计算每个列的数据分布、唯一值数量和索引选择性等信息。例如,可以使用以下命令更新表的统计数据:ANALYZE TABLE table_name;这个命令会在后台运行,不会阻塞其他查询操作。
OPTIMIZE TABLE 命令:使用OPTIMIZE TABLE命令可以重建表和索引,从而更新统计数据。这个命令会创建一个新的表,并将数据从旧表复制到新表中,同时重新创建索引和统计信息。例如,可以使用以下命令更新表的统计数据:OPTIMIZE TABLE table_name;这个命令可能需要较长的时间,并且会锁定表,可能会影响其他查询操作。
手动更新统计数据:除了使用命令之外,还可以通过手动插入或更新数据来更新统计信息。例如,可以插入一些新的数据或更新现有数据,然后再使用ANALYZE TABLE命令更新统计信息。
对于大型表,可以使用采样方式更新统计数据,而不是对整个表进行扫描。可以使用以下命令来指定采样百分比:ANALYZE TABLE table_name SAMPLE 10 PERCENT;这个命令会对表的10%的数据进行采样,并计算统计信息。
更新统计数据可以帮助MySQL优化查询计划,选择更合适的索引来执行查询。根据实际情况,可以选择适合的方法来更新统计数据,从而提高查询性能。

查看视图

在MySQL 5.7中,可以使用以下方式来查看当前数据库中是否存在视图:
使用SHOW TABLES语句:如果有视图存在,它们会以"VIEW"作为Type列的值显示。
使用SHOW CREATE VIEW语句:如果视图存在,则会显示视图的创建语句;如果视图不存在,则会显示错误信息。
查询information_schema数据库。查看当前数据库中是否存在视图,并获取有关视图的详细信息。

-- 使用SHOW TABLES语句
SHOW TABLES;

这个语句可以列出当前数据库中的所有表和视图。
如果有视图存在,它们会以"VIEW"作为Type列的值显示。

-- 使用SHOW CREATE VIEW语句
SHOW CREATE VIEW view_name;

这个语句可以查看指定视图的创建语句。
如果视图存在,则会显示视图的创建语句;如果视图不存在,则会显示错误信息。

-- 查询information_schema数据库:
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.VIEWS
WHERE TABLE_SCHEMA = 'your_database_name';

这个查询语句可以查看指定数据库中的所有视图。
将"your_database_name"替换为实际的数据库名称。
视图的增删改查

使用CREATE VIEW语句可以创建视图。
使用ALTER VIEW语句可以修改已存在的视图。
使用DROP VIEW语句可以删除已存在的视图。
使用SELECT语句可以查询视图的数据。视图在使用上类似于表,可以像查询表一样使用SELECT语句查询视图的数据。
需要注意的是,视图只是逻辑上的虚拟表,实际上并不存储数据,而是基于原始表的查询结果生成的。因此,对视图的增删改操作实际上是对基础表的操作。当对视图进行增删改操作时,实际上是对基础表的数据进行了相应的操作,视图会随之更新。

-- 创建视图
CREATE VIEW view_name AS
SELECT column1, column2, ...
FROM table_name
WHERE condition;

其中,view_name是视图的名称,column1, column2等是视图中包含的列,
table_name是视图所基于的表,condition是筛选条件。

-- 修改视图
ALTER VIEW view_name AS
SELECT column1, column2, ...
FROM table_name
WHERE condition;

其中,view_name是要修改的视图的名称,column1, column2等是视图中包含的列,
table_name是视图所基于的表,condition是筛选条件。

-- 删除视图
DROP VIEW view_name;

其中,view_name是要删除的视图的名称。

-- 查询视图中的数据
select * from view_name;

存储过程触发器

当涉及到复杂的数据操作和业务逻辑时,MySQL提供了存储过程和触发器的功能。它们都能提高数据库的性能和安全性,减少代码的重复性。下面是对存储过程和触发器的详细介绍:

存储过程(Stored Procedure):存储过程是一段预先编译好的SQL代码块,可以在数据库中创建和保存。它可以接受参数、执行一系列的SQL语句,并且可以返回结果。存储过程可以用来封装复杂的业务逻辑,提高数据库的性能和安全性,减少网络传输的开销。

存储过程的优点:
重用性:存储过程可以被多次调用,提高了代码的重用性和维护性。
性能优化:存储过程在数据库服务器上执行,减少了网络传输的开销,提高了数据库的性能。
安全性:存储过程可以对数据库进行访问控制,只允许执行特定的操作,提高了数据库的安全性。
简化复杂的操作:存储过程可以封装多个SQL语句和业务逻辑,简化了复杂的操作。

触发器(Trigger):触发器是与数据库表相关联的一段代码,当特定的数据库操作(如插入、更新、删除)发生时,触发器会自动执行。触发器可以用来实现数据的约束和业务规则的自动执行。
触发器的特点:1、与表相关联:触发器是与特定的表相关联的,当与表相关的操作发生时,触发器会被触发执行。2、自动执行:触发器是自动执行的,无需手动调用。3、事件触发:触发器可以与数据库操作(如插入、更新、删除)相关联,当这些操作发生时,触发器会被触发执行。4、触发顺序:触发器可以定义在操作之前或之后执行。

触发器的应用场景:
数据约束:触发器可以用来实现数据的约束,例如检查插入或更新的数据是否符合特定的条件。
日志记录:触发器可以用来实现数据的变更记录,例如记录数据的修改、删除等操作。
自动更新:触发器可以用来实现自动更新相关数据,例如更新某个字段的值或计算某个字段的结果。

总结:存储过程和触发器是MySQL提供的强大功能,可以用来处理复杂的数据操作和业务逻辑。存储过程提供了代码重用、性能优化和安全性等优点,而触发器可以实现数据约束、日志记录和自动更新等功能。它们都能提高数据库的性能和安全性,减少代码的重复性。

查看有无

使用show procedure status语句。这个语句可以列出当前数据库中的所有存储过程。如果有存储过程存在,它们会以"PROCEDURE"作为Type列的值显示。
使用show create procedure语句。这个语句可以查看指定存储过程的创建语句。如果存储过程存在,则会显示存储过程的创建语句;如果存储过程不存在,则会显示错误信息。
使用show triggers语句。这个语句可以列出当前数据库中的所有触发器。如果有触发器存在,它们会以"TRIGGER"作为Trigger_type列的值显示。
使用show create trigger语句。这个语句可以查看指定触发器的创建语句。如果触发器存在,则会显示触发器的创建语句;如果触发器不存在,则会显示错误信息。

-- 查看存储过程信息
SHOW PROCEDURE STATUS;
-- 查看存储过程的创建语句
SHOW CREATE PROCEDURE procedure_name;

-- 查看触发器信息
SHOW TRIGGERS;
-- 查看触发器的创建语句
SHOW CREATE TRIGGER trigger_name;
存储过程的增删用

存储过程提供了封装和重用的功能,可以简化复杂的数据操作,并提高数据库的性能和安全性。
使用CREATE PROCEDURE语句来创建存储过程。使用CALL语句调用存储过程。使用DROP PROCEDURE语句删除存储过程。

示例及讲解:
DELIMITER //
CREATE PROCEDURE procedure_name(in param1 INT, IN param2 VARCHAR(255))
BEGIN
	...SQL语句和逻辑操作
END //
DELIMITER ;

第一步:使用DELIMITER修改语句的分隔符。
第二部:使用CREATE PROCEDURE创建存储过程。
第三步:使用存储过程的参数列表(可选)。(in name type,...)
in关键字用于声明输入参数,name表示参数名称,type表示参数类型
第四步:存储过程的逻辑代码位于BEGIN和END之间。可以在存储过程中执行各种SQL语句和逻辑操作。
第五步:使用 DELIMITER 关键字将分隔符恢复为原来的状态。

-- 创建存储过程
DELIMITER //
CREATE PROCEDURE procedure_name([parameter_list])
BEGIN
-- 存储过程的逻辑代码
END //
DELIMITER ;

在语法中,procedure_name是存储过程的名称,parameter_list是存储过程的参数列表(可选)。
存储过程的逻辑代码位于BEGIN和END之间。可以在存储过程中执行各种SQL语句和逻辑操作。

-- 调用存储过程:
CALL procedure_name([argument_list]);

在语法中,procedure_name是要调用的存储过程的名称,argument_list是传递给存储过程的参数列表(可选)。
根据存储过程的定义,可以传递相应的参数值进行调用。

--删除存储过程:
DROP PROCEDURE IF EXISTS procedure_name;

在语法中,procedure_name是要删除的存储过程的名称。
使用IF EXISTS关键字可以避免在删除不存在的存储过程时出现错误。

存储过程的应用场景:

存储过程在MySQL 5.7中有很多应用场景,以下是一些常见的示例:

数据处理和转换:

存储过程可以用于处理和转换数据,例如将字符串转换为日期格式,执行数学计算等。

示例代码:
DELIMITER //
CREATE PROCEDURE convert_date_string(input_date VARCHAR(10), OUT converted_date DATE)
BEGIN
	SET converted_date = STR_TO_DATE(input_date, '%Y-%m-%d');
END //
DELIMITER ;

-- 调用存储过程
CALL convert_date_string('2022-01-01', @converted_date);
SELECT @converted_date;

数据验证和约束:

存储过程可以用于验证数据并确保其符合特定的约束条件,例如检查输入参数是否符合要求。

示例代码:
DELIMITER //
CREATE PROCEDURE insert_employee(emp_id INT, emp_name VARCHAR(50))
BEGIN
    IF emp_id > 0 AND LENGTH(emp_name) > 0 THEN
    	INSERT INTO employees (id, name) VALUES (emp_id, emp_name);
    ELSE
    	SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Invalid input parameters';
    END IF;
END //
DELIMITER ;

-- 调用存储过程
CALL insert_employee(1001, 'John Doe');
CALL insert_employee(-1, 'Invalid');

数据备份和恢复:

存储过程可以用于执行数据备份和恢复操作,例如将表中的数据导出到文件,或从文件中导入数据到表中。

示例代码:
DELIMITER //
CREATE PROCEDURE backup_table_data(table_name VARCHAR(50), file_name VARCHAR(100))
BEGIN
    SET @query = CONCAT('SELECT * INTO OUTFILE "', file_name, '" FROM ', table_name);
    PREPARE stmt FROM @query;
    EXECUTE stmt;
END //
DELIMITER ;

-- 调用存储过程
CALL backup_table_data('employees', '/path/to/backup.csv');

复杂查询和逻辑处理:

存储过程可以用于执行复杂的查询和逻辑处理,例如联合多个表进行数据分析和计算。

示例代码:
DELIMITER //
CREATE PROCEDURE calculate_total_sales(year INT, OUT total_sales DECIMAL(10, 2))
BEGIN
    SELECT SUM(sales_amount) INTO total_sales
    FROM sales
    WHERE YEAR(sales_date) = year;
END //
DELIMITER ;

-- 调用存储过程
CALL calculate_total_sales(2022, @total_sales);
SELECT @total_sales;
触发器的增删用

在MySQL 5.7中,可以使用CREATE TRIGGER语句来创建触发器,使用DROP TRIGGER语句来删除触发器,并使用调用DML语句(如INSERT、UPDATE、DELETE)来触发触发器的执行。这样就可以实现在特定操作发生时自动执行相关代码逻辑的功能。以下是触发器的创建、删除和调用的示例:

创建触发器:

使用CREATE TRIGGER语句来创建触发器。触发器可以在表上的INSERT、UPDATE、DELETE操作之前或之后触发执行相关的代码逻辑。

示例代码:
   DELIMITER //
   CREATE TRIGGER audit_trigger
   AFTER INSERT ON employees
   FOR EACH ROW
   BEGIN
	 INSERT INTO audit_log (table_name, action_type)
	   VALUES ('employees', 'INSERT');
   END //
   DELIMITER ;

在示例中,创建了一个名为"audit_trigger"的触发器。
它被定义为在"employees"表上的INSERT操作之后触发执行。
触发器的代码逻辑是将相关信息插入到"audit_log"表中。

删除触发器:

使用DROP TRIGGER语句来删除触发器。

示例代码:
	DROP TRIGGER IF EXISTS audit_trigger;

在示例中,使用DROP TRIGGER语句删除名为"audit_trigger"的触发器。
如果触发器不存在,则该语句不会产生错误。

调用触发器:

触发器是与表相关联的对象,无需直接调用。当表上的INSERT、UPDATE或DELETE操作发生时,触发器会自动被触发执行。

示例代码:
   -- 执行插入操作,触发触发器
   INSERT INTO employees (id, name) VALUES (1001, 'John Doe');

在示例中,执行了一个插入操作,将数据插入到"employees"表中。由于在该表上定义了触发器"audit_trigger",因此在插入操作之后,触发器会被自动触发执行。

触发器的应用场景:

触发器(Trigger)是MySQL数据库中的一种对象,它与数据库表相关联,可以在插入、更新、删除等操作发生时自动触发执行相关的代码逻辑。MySQL 5.7支持在表上创建触发器。以下是一些常见的触发器应用场景的示例,实际上触发器可以用于更多复杂的数据处理和业务逻辑操作。根据具体的需求,可以创建适合的触发器来实现特定的功能。

数据审计:

创建一个触发器,用于记录表中的插入、更新和删除操作,以便进行数据审计和跟踪。

示例代码:
   CREATE TABLE audit_log (
	 id INT AUTO_INCREMENT PRIMARY KEY,
	 table_name VARCHAR(50),
	 action_type VARCHAR(10),
	 action_timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
   );

   DELIMITER //
   CREATE TRIGGER audit_trigger
   AFTER INSERT ON employees
   FOR EACH ROW
   BEGIN
	 INSERT INTO audit_log (table_name, action_type)
	   VALUES ('employees', 'INSERT');
   END //
   DELIMITER ;

   -- 执行插入操作
   INSERT INTO employees (id, name) VALUES (1001, 'John Doe');

   -- 查看审计日志
   SELECT * FROM audit_log;

数据完整性约束:

创建一个触发器,用于在插入或更新操作发生时检查数据的完整性,确保满足特定的约束条件。

示例代码:

   CREATE TABLE orders (
	 id INT AUTO_INCREMENT PRIMARY KEY,
	 order_date DATE,
	 total_amount DECIMAL(10, 2),
	 status VARCHAR(20)
   );

   DELIMITER //
   CREATE TRIGGER check_order_status
   BEFORE INSERT OR UPDATE ON orders
   FOR EACH ROW
   BEGIN
	 IF NEW.status NOT IN ('pending', 'completed', 'cancelled') THEN
	   SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Invalid order status';
	 END IF;
   END //
   DELIMITER ;

   -- 执行插入操作
   INSERT INTO orders (order_date, total_amount, status)
	 VALUES ('2022-01-01', 100.00, 'invalid');

   -- 查看错误信息
   SHOW WARNINGS;

数据同步:

创建一个触发器,在主表上插入、更新、删除操作发生时,自动同步相关的数据到从表中。

示例代码:

   CREATE TABLE customers (
	 id INT AUTO_INCREMENT PRIMARY KEY,
	 name VARCHAR(50),
	 total_orders INT
   );

   CREATE TABLE orders (
	 id INT AUTO_INCREMENT PRIMARY KEY,
	 customer_id INT,
	 order_date DATE,
	 total_amount DECIMAL(10, 2)
   );

   DELIMITER //
   CREATE TRIGGER sync_customer_orders
   AFTER INSERT ON orders
   FOR EACH ROW
   BEGIN
	 UPDATE customers
	 SET total_orders = total_orders + 1
	 WHERE id = NEW.customer_id;
   END //
   DELIMITER ;

   -- 执行插入操作
   INSERT INTO customers (name, total_orders) VALUES ('John Doe', 0);
   INSERT INTO orders (customer_id, order_date, total_amount)
	 VALUES (1, '2022-01-01', 100.00);

   -- 查看同步结果
   SELECT * FROM customers;

DML语言

DML(Data Manipulation Language,数据操作语言)语句包含以下命令:
insert:用于向数据库表中插入新的数据。
update:用于更新数据库表中的现有数据。
delete:用于从数据库表中删除数据。
truncate:用于删除表中的所有数据。
replace:类似于insert命令,但如果存在相同的唯一键,则先删除旧数据再插入新数据。
load data infile:用于从外部文件导入数据到数据库表中。
这些命令用于对数据库中的数据进行增加、删除、修改、导入等操作。用于修改和管理数据库中的数据。

新增记录

方式一:
	MySQL可视化工具(navicat、sqlyog)
方式二:
	MySQL命令行客户端(MySQL 5.7 Command Line Client)
	
新增一条记录:INSERT INTO语句
	INSERT INTO table_name (column1, column2, ...) VALUES (value1, value2, ...);
	
新增多条记录:INSERT INTO语句
    INSERT INTO table_name (column1, column2, ...)
       VALUES (value1, value2, ...),
              (value3, value4, ...),
              ...;
                  
批量新增记录(INSERT INTO…SELECT语句):
    INSERT INTO table_name (column1, column2, ...)
    SELECT value1, value2, ... FROM another_table WHERE condition;
	   
总结:
	要在MySQL中新增一条记录,可以使用INSERT INTO语句。如果要新增多条记录或者进行批量新增记录,可以使用INSERT INTO语句的多值插入方式或INSERT INTO…SELECT语句。
注意点:
	新增记录时要确保插入的值与表的列定义相匹配,并遵守表中的约束。table_name是要插入数据的表名,column1、column2等是要插入数据的列名,value1、value2等是要插入的具体值。VALUES后面添加多组括号,每组括号表示一条记录。

修改记录

方式一:
	MySQL可视化工具(navicat、sqlyog)
方式二:
	MySQL命令行客户端(MySQL 5.7 Command Line Client)
	
指定条件修改记录
    UPDATE table_name
    	SET column1 = new_value1, column2 = new_value2, ...
    	WHERE condition;
关联表修改记录
    UPDATE table_name
    	JOIN another_table ON table_name.column1 = another_table.column1
    	SET table_name.column2 = another_table.column2;
	
注意点:
	table_name是要修改数据的表名,column1、column2等是要修改的列名,new_value1、new_value2等是要修改的新值,condition是筛选要修改的记录的条件。在修改记录时,要确保更新的值与表的列定义相匹配,并遵守表中的约束。

删除记录

方式一:
	MySQL可视化工具(navicat、sqlyog)
方式二:
	MySQL命令行客户端(MySQL 5.7 Command Line Client)
	
删除记录:DELETE FROM table_name WHERE condition;
清除记录,自增主键ID归零:truncate table table_name;
案例:
	删除所有记录:
		DELETE FROM table_name;
	删除一条记录:
		DELETE FROM table_name WHERE column1 = value1;
	删除多条记录:
		DELETE FROM table_name WHERE column1 > value1;
	批量删除记录:
        DELETE FROM table_name WHERE column1 
            IN (value1, value2, value1, ...);

注意点:
	table_name是要插入数据的表名,column1是要插入数据的列名,value1、value2等是要插入的具体值。请注意在删除记录时,要慎重操作,确保删除的记录符合你的意图,并备份重要数据以防止意外删除。

DQL语言

DQL(Data Query Language,数据查询语言)语句包含以下命令:
select:用于从数据库表中查询数据。
from:指定要查询的数据库表。
where:用于指定查询条件,筛选满足条件的数据。
group by:用于对查询结果进行分组。
having:用于对分组后的数据进行筛选。
order by:用于对查询结果进行排序。
limit:用于限制查询结果的数量。
join:用于将多个表关联起来进行查询。
union:用于合并多个查询结果集。
distinct:用于去除查询结果中的重复数据。
exists、not exists、in、not in、like、between、……

这些命令主要用于查询和检索数据库中的数据。用于精确地筛选和处理数据,例如子查询、连接查询、聚合函数等,以满足更复杂的查询需求。

简单查询

单表查询,配合着一些函数进行单表查询。加点条件、分组、统计、日期、排序、……的单表查询

select结果集、from指定表、where筛选条件、group by分组字段、having筛选条件、order by排序字段、limit个数

全查:
	SELECT column1, column2, ...
	   FROM table
条件查询:
	SELECT column1, column2, ...
	   FROM table
	   WHERE condition;
分组查:
	SELECT column1, column2, ...
	   FROM table
	   GROUP BY column1, column2, ...;
分组条件查:
	SELECT column1, column2, ...
	   FROM table
	   GROUP BY column1, column2, ...
	   HAVING condition;
排序查:
	SELECT column1, column2, ...
        FROM table
        ORDER BY column1 [ASC|DESC], column2 [ASC|DESC], ...;
指定个数:
	SELECT column1, column2, ...
        FROM table
        LIMIT [offset,] row_count;
        补充:offset是可选的,表示要跳过的行数。row_count表示要返回的行数。
条件分组筛选排序指定个数查:
	SELECT column1, column2, ...
		FROM table
		WHERE condition
		GROUP BY column1, column2, ...
		HAVING condition
		ORDER BY column1 [ASC|DESC], column2 [ASC|DESC], ...
		LIMIT [offset,] row_count;
总结:
	select 结果集 
	from 表名 
	where 筛选条件 
	group by 分组字段 
	having 筛选条件 
	order by 排序字段 正序倒序 
	limit 个数;
select结果集

去重:distinct
统计:count()、sum()、avg()、max()、min()、
算术:+ - * /
……

去重:
	select distinct column1
统计:
	select count(*), sum(column1), avg(column1), max(column1), min(column1)
算术:
	select name, score + addScore as score
其他:
	-- 获取最后插入行的自增ID值。
	select last_insert_id();
	
1、字段值为空的情况,可以使用:ifnull(xx字段,0),将空值赋0
2、字段值为空字符串的情况,可以使用:if(xx字段="",xx字段,0),将空字符串赋0
from指定表

真实表、结果集、关联表。
FROM子句用于指定要查询的表或视图。它是SELECT语句的一部分,并在SELECT子句之后、WHERE子句之前使用。

真实表:
	from table1;
结果集:
	from (select column1, column2 from table1) as AAA
关联表:
	from table1 t1 left join table2 t2 on t1.column = t2.column
where操作符

​ WHERE子句用于在SELECT语句中筛选满足指定条件的行。它允许使用比较操作符、逻辑操作符和条件表达式来定义查询的过滤条件。
算术:+ - * /
比较:“=”、“!=”、“<>”、“>”、“>=”、“<”、“<=”、
逻辑:“and”、“or”
肯定:“bteween and”、“in”、“is null”、“like”、“rlike”、
否定:“not between and”、“not in”、“is not null”、“not like”、“not rlike”、

比较:
	where column1 = value1;
逻辑:
	并且:where column1 = value1 and column2 = value2;
	或者:where column1 = value1 or column2 = value2;
在指定的值列表中:
	肯定:where column1 in (value1, value2, value3, ...);有值符合要求
	否定:where column1 not in (value1, value2, value3);所有值都不符合
模糊匹配:
	where column1 like '%xx%';	内容带xx的
	where column1 like 'xx%';	内容以xx结尾的 
	where column1 like '%xx';	内容以xx开头的
为空判断:
	where column1 is null;
group by、having

​ GROUP BY子句用于将查询结果按照指定的列进行分组。它将相同值的行分为一组,并将这些组作为结果集的一部分返回。
​ HAVING子句用于在GROUP BY子句之后对分组的结果进行筛选。它允许使用聚合函数和条件表达式来过滤分组后的结果。

分组列名必须出现在select结果集中:
    SELECT department, COUNT(*) as total_employees 
    	FROM employees
        GROUP BY department;
筛选分组结果的列名必须出现在select结果集中:
    SELECT department, COUNT(*) as total_employees
        FROM employees
        GROUP BY department
        HAVING total_employees >= 5;
总结:
	group by子句中的列名必须是select子句中出现的列或聚合函数。
	having子句中的列名必须是select子句中出现的列或聚合函数。
order by、limit

​ ORDER BY子句用于按照指定的列对查询结果进行排序。它可以按照升序(ASC)或降序(DESC)排列结果。
​ LIMIT子句用于限制查询结果集的返回行数。它可以用于分页查询或仅返回前几行结果。

升序:
	ORDER BY column1 ASC;
降序:
	ORDER BY column1 DESC;
返回前十行记录:
	LIMIT 10;
跳过前五行,返回接下来的十行记录:
	LIMIT 5, 10;
跳过前二十行,返回接下来的十行记录:
	LIMIT 10 OFFSET 20;
函数补充

字符串函数【拼接、截取、替换、大小写转换、去除两端空白、返回长度、……】
concat()、substring()、replace()、upper()、lower()、trim()、length()

数值函数【四舍五入、向下取整、向上取整、返回绝对值、返回两个数的模(余数)、……】
round()、floor()、ceiling()、abs()、mod()

日期和时间函数【当前日期和时间、当前日期、当前时间、日期格式化、日期加减运算、日期天数差、……】
now()、curdate()、curtime()、date_format()、dateadd()、datesub()、datediff()

条件函数【根据条件返回不同的值、根据条件执行不同的操作、……】
if()、case()、ifnull()、nullif()

1、最近每年的总记录数:
    思路:使用GROUP BY子句和YEAR函数对日期列进行分组,并使用COUNT函数计算每年的记录数。
    SELECT YEAR(date_column) AS year, COUNT(*) AS total_records
    FROM table
    GROUP BY YEAR(date_column);
	
2、今年每个月份的总记录数:
    思路:使用GROUP BY子句和MONTH函数对日期列进行分组,并使用COUNT函数计算每个月份的记录数。
    SELECT MONTH(date_column) AS month, COUNT(*) AS total_records
    FROM table
    WHERE YEAR(date_column) = YEAR(CURRENT_DATE)
    GROUP BY MONTH(date_column);

3、这个月每天总记录数:
    思路:使用GROUP BY子句和DATE函数对日期列进行分组,并使用COUNT函数计算每天的记录数。
    SELECT DATE(date_column) AS day, COUNT(*) AS total_records
    FROM table
    WHERE YEAR(date_column) = YEAR(CURRENT_DATE) AND MONTH(date_column) = MONTH(CURRENT_DATE)
    GROUP BY DATE(date_column);
        这将返回这个月每天的日期和对应的总记录数。

4、这周每天的总记录数:
    思路:使用GROUP BY子句和WEEKDAY函数对日期列进行分组,并使用COUNT函数计算每天的记录数。
    SELECT WEEKDAY(date_column) AS weekday, COUNT(*) AS total_records
    FROM table
    WHERE YEARWEEK(date_column) = YEARWEEK(CURRENT_DATE)
    GROUP BY WEEKDAY(date_column);
        这将返回这周每天的星期几和对应的总记录数。

5、最近三十天的日收入以及总收入
	最近三十天的日收入:使用DATE_SUB函数和GROUP BY子句对日期列进行筛选和分组,并使用SUM函数计算每天的收入总和。
	SELECT DATE(date_column) AS day, SUM(income) AS daily_income
	FROM table
	WHERE date_column >= DATE_SUB(CURRENT_DATE, INTERVAL 30 DAY)
	GROUP BY DATE(date_column)
	ORDER BY DATE(date_column) DESC;

	最近三十天的总收入:在三十天的日收入的基础上再次使用SUM函数计算总和。
	SELECT SUM(daily_income) AS total_income
	FROM (
		SELECT DATE(date_column) AS day, SUM(income) AS daily_income
		FROM table
		WHERE date_column >= DATE_SUB(CURRENT_DATE, INTERVAL 30 DAY)
		GROUP BY DATE(date_column)
	) AS subquery;

注意:
	上述查询中的table应替换为实际的表名,date_column应替换为实际的日期列名,income应替换为实际的收入列名。另外,根据实际情况,可能需要对日期条件和日期格式进行调整。

初级查询

子查询

在MySQL中,子查询(Subquery)是指在一个查询语句中嵌套另一个完整的查询语句。子查询可以作为主查询的一部分,用于提供更复杂的查询逻辑和过滤条件。子查询通常出现在主查询的FROM子句、WHERE子句、HAVING子句或SELECT子句中。它可以返回一个结果集,该结果集可以被主查询引用和处理。

常用的关键字如下:
in:满足存在(用于判断某个值是否存在于子查询的结果集中)
not in:满足不存在(用于判断某个值不存在于子查询的结果集中。)
exists:满足有结果集(用于判断子查询是否返回了结果集,返回结果集则条件成立)
not exists:满足无结果集(用于判断子查询是否返回了结果集,无返回结果集则条件成立)
any:满足任一(比较某个值与子查询的结果集中的任意一个值是否满足条件)
all:满足全部(比较某个值与子查询的结果集中的所有值是否都满足条件)

常见的子查询结构如下
标量子查询(Scalar):一个列作为子查询,嵌套在查询的SELECT语句中,作为一个列的值
列子查询(Column):多个列作为子查询,嵌套在查询的FROM子句中,作为一个表
行子查询(Row):一个或多个行的结果集,嵌套在查询的WHERE子句中,作为一个条件表达式
表子查询(Table)多行多列的结果集,嵌套在查询的FROM子句中,作为一个虚拟表

SELECT [列名] FROM [表名] WHERE [条件] IN (子查询)
SELECT [列名] FROM [表名] WHERE [条件] NOT IN (子查询)
SELECT [列名] FROM [表名] WHERE [条件] EXISTS (子查询)
SELECT [列名] FROM [表名] WHERE [条件] NOT EXISTS (子查询)
SELECT [列名] FROM [表名] WHERE [条件] ANY (子查询)
SELECT [列名] FROM [表名] WHERE [条件] ALL (子查询)
子查询中可以嵌套子查询,用于进一步筛选和过滤结果集。没有not any、没有not all

标量子查询:
=> 返回了学生表中最大的年龄值
SELECT name, (SELECT MAX(age) FROM students) AS max_age FROM students;

列子查询:
=> 返回了学生表中的姓名和年龄列,然后在外部查询中对这个子查询进行过滤,筛选出年龄大于18岁的学生姓名
SELECT name FROM (SELECT name, age FROM students) AS subquery WHERE age > 18;

行子查询:
=> 返回了学生表中id为1的学生的姓名和年龄,然后在外部查询中使用(name, age) = ...的方式,通过比较一整行的值来进行条件判断。
SELECT name FROM students WHERE (name, age) = (SELECT name, age FROM students WHERE id = 1);

表子查询:
=> 根据学生姓名分组,计算每个学生的总分,然后在外部查询中对这个子查询进行查询,获取每个学生的姓名和总分。
SELECT subquery.name, subquery.total_score FROM (SELECT name, SUM(score) AS total_score FROM scores GROUP BY name) AS subquery;

IN子查询:
=> 返回了成绩表中分数大于90的学生ID,然后在外部查询中使用IN子查询,判断学生表中的学生ID是否存在于子查询的结果集中。
SELECT name FROM students WHERE student_id IN (SELECT student_id FROM scores WHERE score > 90);

NOT IN子查询:
=> 返回了成绩表中分数大于90的学生ID,然后在外部查询中使用NOT IN子查询,判断学生表中的学生ID是否不在子查询的结果集中。
SELECT name FROM students WHERE student_id NOT IN (SELECT student_id FROM scores WHERE score > 90);

双重IN子查询:
=> 返回了科目表中名称为'Math'的科目ID,然后在外部查询的子查询中使用IN子查询,判断成绩表中的科目ID是否存在于子查询的结果集中,最终筛选出学生在数学科目上的成绩。
SELECT name FROM students WHERE student_id 
IN (SELECT student_idFROM scores WHERE subject_id 
IN (SELECT subject_id FROM subjects WHERE subject_name = 'Math'));

EXISTS子查询:
=> 返回了成绩表中与学生表关联的记录,然后在外部查询中使用EXISTS子查询,判断学生表中的学生是否存在与子查询的结果集中。
SELECT name FROM students s WHERE 
EXISTS (SELECT 1 FROM scores sc WHERE s.student_id = sc.student_id);

NOT EXISTS子查询:
=> 返回了成绩表中与学生表关联的记录,然后在外部查询中使用NOT EXISTS子查询,判断学生表中的学生是否不存在于子查询的结果集中。
SELECT name FROM students s WHERE 
NOT EXISTS (SELECT 1 FROM scores sc WHERE s.student_id = sc.student_id);

双重EXISTS子查询:
=> 返回了科目表中名称为'Math'的科目ID,然后在外部查询的子查询中使用EXISTS子查询,判断成绩表中的学生ID是否存在于子查询的结果集中,同时再判断科目ID是否存在于子查询的结果集中,最终筛选出学生在数学科目上的成绩。
SELECT name FROM students s WHERE 
EXISTS (SELECT 1 FROM scores sc WHERE s.student_id = sc.student_id AND 
EXISTS (SELECT 1 FROM subjects sub WHERE sub.subject_id = sc.subject_id AND sub.subject_name = 'Math'));
	
ANY/SOME子查询:
=> 返回了性别为男性的学生年龄,然后在外部查询中使用ANY子查询,判断学生表中的年龄是否大于子查询的结果集中的任意一个值。
SELECT name FROM students WHERE age > 
ANY (SELECT age FROM students WHERE gender = 'male');

NOT ANY/SOME子查询:
在MySQL 5.7中,并没有直接支持NOT ANY子查询的语法,但可以通过使用其他方式,如NOT IN子查询或其他操作符的组合,来实现与NOT ANY相同的查询效果。

双重ANY子查询:
=> 返回了科目ID为2的成绩,然后在外部查询的子查询中使用ANY子查询,判断成绩表中的分数是否大于子查询的结果集中的任意一个值,同时再判断年龄是否大于子查询的结果集中的任意一个值,最终筛选出年龄大于某个科目成绩中的任意一个分数的学生。
SELECT name FROM students WHERE age > 
ANY (SELECT age FROM scores WHERE subject_id = 1 AND score > 
ANY (SELECT score FROM scores WHERE subject_id = 2));

ALL子查询:
SELECT name FROM students WHERE age > 
ALL (SELECT age FROM students WHERE gender = 'female');
返回了性别为女性的学生年龄,然后在外部查询中使用ALL子查询,判断学生表中的年龄是否大于子查询的结果集中的所有值。

NOT ALL子查询:
在MySQL 5.7中,并没有直接支持NOT ALL子查询的语法,但可以通过使用其他方式,如NOT IN子查询或NOT EXISTS子查询或者其他操作符的组合,来实现与NOT ANY相同的查询效果。

双重ALL子查询:
=> 返回了科目ID为2的成绩,然后在外部查询的子查询中使用ALL子查询,判断成绩表中的分数是否都大于子查询的结果集中的所有值,同时再判断年龄是否大于子查询的结果集中的所有值,最终筛选出年龄大于某个科目成绩中的所有分数的学生。
SELECT name FROM students WHERE age > 
ALL (SELECT age FROM scores WHERE subject_id = 1 AND score > 
ALL (SELECT score FROM scores WHERE subject_id = 2));
关联查询

在MySQL中,关联查询(Join)是指将两个或多个表基于某个共同的列进行连接,从而获取到相关联的数据。关联查询可以通过在SELECT语句中使用JOIN子句来实现。连接的结果是一个包含了两个或多个表中相关数据的虚拟表。常用的关联查询类型有:
INNER JOIN:内连接,返回两个表中满足连接条件的数据。
LEFT JOIN:左连接,返回左表(table1)中的所有记录,以及满足连接条件的右表(table2)中的记录。
RIGHT JOIN:右连接,返回右表(table2)中的所有记录,以及满足连接条件的左表(table1)中的记录。
FULL JOIN:全连接,返回左表(table1)和右表(table2)中的所有记录,无论是否满足连接条件。

补充:UNION:将两个或多个查询的结果合并成一个结果集。
关联查询可以使得在一条查询语句中获取到来自多个表的相关数据,避免了多次查询和数据处理的复杂性。使用合适的连接类型和连接条件,可以根据具体的需求实现不同的关联查询操作。

自连接(Self Join):将表与自身进行连接,用于在同一表中比较不同行之间的数据。
    SELECT * FROM table1 t1
    INNER JOIN table1 t2 ON t1.column = t2.column;

内连接(INNER JOIN):返回两个表中满足连接条件的行。
    SELECT * FROM table1
    INNER JOIN table2 ON table1.column = table2.column;

左连接(LEFT JOIN):返回左表中所有的行,以及右表中满足连接条件的行。
    SELECT * FROM table1
    LEFT JOIN table2 ON table1.column = table2.column;

右连接(RIGHT JOIN):返回右表中所有的行,以及左表中满足连接条件的行。
    SELECT * FROM table1
    RIGHT JOIN table2 ON table1.column = table2.column;

全连接(FULL JOIN):返回左表和右表中所有的行,不管是否满足连接条件。
    SELECT * FROM table1
    FULL JOIN table2 ON table1.column = table2.column;

联合查询(UNION):将两个或多个查询的结果合并成一个结果集。
    SELECT column1 FROM table1
    UNION
    SELECT column2 FROM table2;
变量查询

在MySQL中,变量查询(Variable Query)是指通过使用变量来存储和检索数据。

变量查询的定义包括以下几个方面:
1、变量声明:在MySQL中,可以使用SET语句来声明和初始化变量。例如,SET @var_name = value;会创建一个名为var_name的变量,并将其初始化为value。
2、变量赋值:可以使用SET语句来为变量赋值。例如,SET @var_name = expression;会将表达式的值赋给变量var_name。
3、变量引用:在查询中,可以使用@符号来引用变量。例如,SELECT @var_name;会检索变量var_name的值。
4、变量计算:变量可以用于进行各种计算和操作。例如,可以将查询结果存储在变量中,然后使用变量进行其他计算或比较。

需要注意的是,MySQL的变量是会话级别的,只在当前会话中有效。在新的会话中,变量需要重新声明和赋值。总之,MySQL的变量查询提供了一种灵活的方式来存储和检索数据,可以在查询中进行各种计算和操作,以满足不同的需求。

常用案例一:编号排序
set @A :=0;  
select (@A :=@A+1) as rank,name from table;

变量查询应用:分组排序查询

1、小组最高分排名
2、分组后每个小组成员成绩排名

每个小组最高分排名

查询每个小组成绩最高分排名序号
select name,score,(@rank := @rank + 1) as rank from (
    select name,max(convert(score,signed)) as score 
	from game_record 
	group by name 
	order by score desc
	) as table1,(select @rank :=0) r;
注意:
	这里的convert(score,signed),是因为我score类型是varchar。
	所以我使用convert(xxx,signed)将它转成整数类型,然后进行最值处理。

分组后小组成员成绩排名

查询每个小组内部成员成绩排名
    SELECT t1.group_id, t1.member_id, t1.score, t1.rank
        FROM (
            SELECT group_id, member_id, score,
                @rank := IF(@prev_group = group_id, @rank + 1, 1) AS rank,
                @prev_group := group_id
            FROM table
            ORDER BY group_id, score DESC
        ) AS t1;
注意:
	table应替换为实际的表名,
	group_id应替换为实际的小组ID列名,
	member_id应替换为实际的成员ID列名,
	score应替换为实际的成绩列名。
    在查询中,使用了MySQL的用户变量@rank和@prev_group来记录排名和前一个小组ID。
    子查询中,首先根据小组ID和成绩进行排序,然后使用IF函数和变量来计算排名。
    如果当前小组ID和前一个小组ID相同,排名加1,否则排名重置为1。
    最外层的SELECT语句用于返回小组ID、成员ID、成绩和排名。

DCL语言

DCL(Data Control Language,数据控制语言)语句包含以下命令:
grant:用于授予用户或角色访问数据库对象的权限。
revoke:用于撤销用户或角色对数据库对象的访问权限。
通过grant和revoke指令,管理员可以灵活地管理MySQL数据库的访问和操作权限,确保数据的安全性和完整性。

grant指令:

grant是MySQL中用于授权用户访问数据库和执行特定操作的指令。它允许管理员为用户分配特定的权限,从而控制用户对数据库的访问和操作。其语法如下:GRANT privileges ON database.table TO user@host [IDENTIFIED BY 'password'];

privileges表示要授予的权限,可以是ALL PRIVILEGES、SELECT、INSERT、UPDATE、DELETE等。
database.table表示要授权的数据库和表名。如果要授权所有数据库,则可以使用通配符*。
user@host表示要授权的用户和主机。如果要授权所有用户和主机,则可以使用通配符%。
[IDENTIFIED BY ‘password’]是可选项,用于设置用户的密码。

示例:GRANT SELECT, INSERT ON database.* TO 'user'@'localhost' IDENTIFIED BY 'password';
以上示例将授予’user’@‘localhost’用户在’database’数据库中的所有表上执行SELECT和INSERT操作的权限,并设置密码为’password’。

revoke指令:

revoke是MySQL中用于撤销用户权限的指令。它允许管理员取消之前授予的权限,从而限制用户对数据库的访问和操作。其语法如下:REVOKE privileges ON database.table FROM user@host;

privileges表示要撤销的权限,可以是ALL PRIVILEGES、SELECT、INSERT、UPDATE、DELETE等。
database.table表示要撤销权限的数据库和表名。如果要撤销所有数据库的权限,则可以使用通配符*。
user@host表示要撤销权限的用户和主机。如果要撤销所有用户和主机的权限,则可以使用通配符%。

示例:REVOKE SELECT, INSERT ON database.* FROM 'user'@'localhost';
以上示例将撤销’user’@'localhost’用户在’database’数据库中的所有表上的SELECT和INSERT权限。

TCL语言

事务控制语言(TCL)。事务是一组SQL语句的执行单元,它们要么全部执行成功,要么全部回滚到事务开始之前的状态。事务的使用场景通常涉及对数据库的一系列操作,确保数据的一致性和完整性。

ACID特性:

原子性(Atomicity):事务中的所有操作要么全部成功执行,要么全部回滚,没有部分执行的情况。
一致性(Consistency):事务执行前后,数据库的状态保持一致性。事务的执行不会破坏数据库的完整性约束。
隔离性(Isolation):事务的执行在逻辑上是隔离的,即一个事务的执行不会受到其他事务的干扰。
持久性(Durability):一旦事务提交,其修改的数据将永久保存在数据库中,即使发生系统故障也不会丢失。

相关命令:

设置是否自动提交事务
临时设置:
SET autocommit = 0;将自动提交事务关闭。
SET autocommit = 1;将自动提交事务打开。
永久设置:
在MySQL配置文件(例如my.cnf或my.ini)中添加或修改autocommit的值。
设置autocommit = 0将自动提交事务关闭。
设置autocommit = 1将自动提交事务打开。

开始一个新的事务
START TRANSACTION; 标准语法
BEGIN; 简化版语法,在MySQL中被解析为START TRANSACTION语句,因此它们是等效的。

创建保存点
SAVEPOINT savepoint1;创建1号保存点
SAVEPOINT savepoint2;创建2号保存点
通过使用SAVEPOINT,可以更细粒度地控制事务的回滚范围,提高事务的灵活性和可靠性。分为回滚部分事务和多层嵌套事务。然而,需要注意的是,SAVEPOINT只在当前事务中有效,当事务提交后,保存点将被释放。

释放指定保存点
RELEASE SAVEPOINT savepoint2:

回滚到指定保存点,撤销之后的所有保存点
ROLLBACK TO savepoint1;

结束事务
COMMIT;提交事务
ROLLBACK;回滚事务

总的流程:关闭自动提交事务 -> 开始新事务 -> 事务处理 -> 结束事务 -> 开启自动提交事务
-- 关闭自动提交事务
-- 开始一个新的事务

    -- 执行一系列的SQL语句
    -- 创建第一个保存点
    -- 执行一系列的SQL语句
    -- 创建第二个保存点
    -- 执行一系列的SQL语句
	-- 回滚到第一个的保存点
	
-- 结束事务语句:
-- 开启自动提交事务

具体应用

银行转账案例、购买商品案例、订单处理案例、退款处理案例、预订案例

银行转账案例

银行转账涉及的事务操作通常包括以下步骤:
开始事务:使用 BEGIN 或 START TRANSACTION 语句来开始一个事务。
查询账户余额:在事务中,首先需要查询转出账户和转入账户的余额,以确认转出账户有足够的金额可以转账。
SELECT balance FROM accounts WHERE account_number = ‘转出账户账号’ FOR UPDATE;
SELECT balance FROM accounts WHERE account_number = ‘转入账户账号’ FOR UPDATE;
使用 FOR UPDATE 锁定查询的行,以确保其他事务不能同时修改这些行。
执行转账操作:根据转出账户和转入账户的余额,计算转账后的余额,并更新两个账户的余额。
UPDATE accounts SET balance = balance - 转账金额 WHERE account_number = ‘转出账户账号’;
UPDATE accounts SET balance = balance + 转账金额 WHERE account_number = ‘转入账户账号’;
提交或回滚事务:根据转账操作的结果,决定是否提交事务或回滚事务。
如果转账操作成功,即转出账户有足够的余额并且更新操作没有错误,使用 COMMIT 语句提交事务。
如果转账操作失败,包括转出账户余额不足或更新操作出错,使用 ROLLBACK 语句回滚事务。
结束事务:使用 COMMIT 或 ROLLBACK 语句结束事务。

需要注意的是,银行转账是一个复杂的过程,还需要考虑并发访问、锁定机制、异常处理等因素,以确保数据的一致性和可靠性。以下示例只是一个简单的介绍,实际应用中可能需要更复杂的逻辑和处理方式。

BEGIN; -- 开始事务

-- 查询转出账户余额
SELECT balance FROM accounts WHERE account_number = '转出账户账号' FOR UPDATE;
SET @balance_out := 转出账户余额;

-- 查询转入账户余额
SELECT balance FROM accounts WHERE account_number = '转入账户账号' FOR UPDATE;
SET @balance_in := 转入账户余额;

-- 判断转出账户余额是否足够
IF @balance_out >= 转账金额 THEN
    -- 更新转出账户余额
    UPDATE accounts SET balance = balance - 转账金额 WHERE account_number = '转出账户账号';
    -- 更新转入账户余额
    UPDATE accounts SET balance = balance + 转账金额 WHERE account_number = '转入账户账号';
    COMMIT; -- 提交事务
    ELSE
	ROLLBACK; -- 回滚事务
END IF;
购买商品案例

购买商品涉及的事务操作通常包括以下步骤:
开始事务:使用 BEGIN 或 START TRANSACTION 语句来开始一个事务。
查询商品和用户信息:在事务中,首先需要查询购买的商品的详细信息以及用户的账户余额情况,以确认购买可以被处理。
SELECT * FROM products WHERE product_id = ‘商品ID’ FOR UPDATE;
SELECT * FROM users WHERE user_id = ‘用户ID’ FOR UPDATE;
使用 FOR UPDATE 锁定查询的行,以确保其他事务不能同时修改这些行。
执行购买操作:根据商品的详细信息和用户的账户余额情况,进行购买操作,包括扣减库存、扣款、生成订单等。
UPDATE products SET stock = stock - 购买数量 WHERE product_id = ‘商品ID’;
UPDATE users SET balance = balance - 购买金额 WHERE user_id = ‘用户ID’;
INSERT INTO orders (user_id, product_id, quantity, amount) VALUES (‘用户ID’, ‘商品ID’, 购买数量, 购买金额);
提交或回滚事务:根据购买操作的结果,决定是否提交事务或回滚事务。
如果购买操作成功,即库存充足、账户余额足够并且更新操作没有错误,使用 COMMIT 语句提交事务。
如果购买操作失败,包括库存不足、账户余额不足或更新操作出错,使用 ROLLBACK 语句回滚事务。
结束事务:使用 COMMIT 或 ROLLBACK 语句结束事务。

需要注意的是,购买商品涉及到多个表的操作,要确保数据的一致性和可靠性,需要仔细考虑并发访问、锁定机制、异常处理等因素。以下示例只是一个简单的介绍,实际应用中可能需要根据具体情况进行更复杂的逻辑和处理方式。

BEGIN; -- 开始事务

-- 查询商品信息
SELECT * FROM products WHERE product_id = '商品ID' FOR UPDATE;
SET @product_stock := 商品库存;

-- 查询用户账户余额
SELECT * FROM users WHERE user_id = '用户ID' FOR UPDATE;
SET @user_balance := 用户账户余额;

-- 判断库存和账户余额是否满足购买条件
IF @product_stock >= 购买数量 AND @user_balance >= 购买金额 THEN
  -- 扣减库存
  UPDATE products SET stock = stock - 购买数量 WHERE product_id = '商品ID';
  -- 扣款
  UPDATE users SET balance = balance - 购买金额 WHERE user_id = '用户ID';
  -- 生成订单
  INSERT INTO orders (user_id, product_id, quantity, amount) VALUES ('用户ID', '商品ID', 购买数量, 购买金额);
  COMMIT; -- 提交事务
ELSE
  ROLLBACK; -- 回滚事务
END IF;
订单处理案例

订单处理涉及的事务操作通常包括以下步骤:
开始事务:使用 BEGIN 或 START TRANSACTION 语句来开始一个事务。
查询订单和库存:在事务中,首先需要查询订单的详细信息以及相关商品的库存情况,以确认订单可以被处理。
SELECT * FROM orders WHERE order_id = ‘订单ID’ FOR UPDATE;
SELECT * FROM products WHERE product_id IN (‘商品ID1’, ‘商品ID2’, … ) FOR UPDATE;
使用 FOR UPDATE 锁定查询的行,以确保其他事务不能同时修改这些行。
执行订单处理操作:根据订单的详细信息和商品的库存情况,进行订单处理操作,包括扣减库存、生成发货单、更新订单状态等。
UPDATE products SET stock = stock - 购买数量 WHERE product_id = ‘商品ID’;
INSERT INTO shipments (order_id, product_id, quantity) VALUES (‘订单ID’, ‘商品ID’, 购买数量);
UPDATE orders SET status = ‘已发货’ WHERE order_id = ‘订单ID’;
提交或回滚事务:根据订单处理操作的结果,决定是否提交事务或回滚事务。
如果订单处理操作成功,即库存充足并且更新操作没有错误,使用 COMMIT 语句提交事务。
如果订单处理操作失败,包括库存不足或更新操作出错,使用 ROLLBACK 语句回滚事务。
结束事务:使用 COMMIT 或 ROLLBACK 语句结束事务。

需要注意的是,订单处理涉及到多个表的操作,要确保数据的一致性和可靠性,需要仔细考虑并发访问、锁定机制、异常处理等因素。以下示例只是一个简单的介绍,实际应用中可能需要根据具体情况进行更复杂的逻辑和处理方式。

BEGIN; -- 开始事务

-- 查询订单信息
SELECT * FROM orders WHERE order_id = '订单ID' FOR UPDATE;
SET @order_status := 订单状态;

-- 查询商品库存
SELECT * FROM products WHERE product_id IN ('商品ID1', '商品ID2', ...) FOR UPDATE;
SET @product_stock := 商品库存;

-- 判断订单状态和商品库存是否满足处理条件
IF @order_status = '待发货' AND @product_stock >= 购买数量 THEN
    -- 扣减库存
    UPDATE products SET stock = stock - 购买数量 WHERE product_id = '商品ID';
    -- 生成发货单
    INSERT INTO shipments (order_id, product_id, quantity) VALUES ('订单ID', '商品ID', 购买数量);
    -- 更新订单状态
    UPDATE orders SET status = '已发货' WHERE order_id = '订单ID';
    COMMIT; -- 提交事务
    ELSE
	ROLLBACK; -- 回滚事务
END IF;
退款处理案例

退款处理涉及的事务操作通常包括以下步骤:
开始事务:使用 BEGIN 或 START TRANSACTION 语句来开始一个事务。
查询订单和账户信息:在事务中,首先需要查询退款订单的详细信息以及相关账户的余额情况,以确认退款可以被处理。
SELECT * FROM orders WHERE order_id = ‘订单ID’ FOR UPDATE;
SELECT * FROM accounts WHERE account_id = ‘账户ID’ FOR UPDATE;
使用 FOR UPDATE 锁定查询的行,以确保其他事务不能同时修改这些行。
执行退款处理操作:根据退款订单的详细信息和账户的余额情况,进行退款处理操作,包括将款项返还给用户并更新订单状态和账户余额。
UPDATE orders SET status = ‘已退款’ WHERE order_id = ‘订单ID’;
UPDATE accounts SET balance = balance + 退款金额 WHERE account_id = ‘账户ID’;
提交或回滚事务:根据退款处理操作的结果,决定是否提交事务或回滚事务。
如果退款处理操作成功,即账户余额足够并且更新操作没有错误,使用 COMMIT 语句提交事务。
如果退款处理操作失败,包括账户余额不足或更新操作出错,使用 ROLLBACK 语句回滚事务。
结束事务:使用 COMMIT 或 ROLLBACK 语句结束事务。

需要注意的是,退款处理涉及到多个表的操作,要确保数据的一致性和可靠性,需要仔细考虑并发访问、锁定机制、异常处理等因素。以下示例只是一个简单的介绍,实际应用中可能需要根据具体情况进行更复杂的逻辑和处理方式。

BEGIN; -- 开始事务

-- 查询订单信息
SELECT * FROM orders WHERE order_id = '订单ID' FOR UPDATE;
SET @order_status := 订单状态;

-- 查询账户余额
SELECT * FROM accounts WHERE account_id = '账户ID' FOR UPDATE;
SET @account_balance := 账户余额;

-- 判断订单状态和账户余额是否满足退款条件
IF @order_status = '已发货' AND @account_balance >= 退款金额 THEN
	-- 更新订单状态
    UPDATE orders SET status = '已退款' WHERE order_id = '订单ID';
    -- 更新账户余额
    UPDATE accounts SET balance = balance + 退款金额 WHERE account_id = '账户ID';
    COMMIT; -- 提交事务
	ELSE
	ROLLBACK; -- 回滚事务
END IF;
预定和取消预订

预订案例涉及的事务操作通常包括以下步骤:
开始事务:使用 BEGIN 或 START TRANSACTION 语句来开始一个事务。
查询资源信息:在事务中,首先需要查询预订所需的资源的详细信息,以确认是否可以进行预订。
SELECT * FROM resources WHERE resource_id = ‘资源ID’ FOR UPDATE;
使用 FOR UPDATE 锁定查询的行,以确保其他事务不能同时修改这些行。
执行预订操作:根据资源的详细信息和预订要求,进行预订操作,包括更新资源状态、插入预订记录等。
UPDATE resources SET status = ‘已预订’ WHERE resource_id = ‘资源ID’;
INSERT INTO bookings (booking_id, user_id, resource_id, start_date, end_date) VALUES (‘预订ID’, ‘用户ID’, ‘资源ID’, ‘开始日期’, ‘结束日期’);
提交或回滚事务:根据预订操作的结果,决定是否提交事务或回滚事务。
​ 如果预订操作成功,即资源状态成功更新、预订记录成功插入,使用 COMMIT 语句提交事务。
​ 如果预订操作失败,包括资源状态更新出错、插入预订记录出错或其他原因导致的错误,使用 ROLLBACK 语句回滚事务。
结束事务:使用 COMMIT 或 ROLLBACK 语句结束事务。

取消预订案例涉及的事务操作通常包括以下步骤:
开始事务:使用 BEGIN 或 START TRANSACTION 语句来开始一个事务。
查询预订信息:在事务中,首先需要查询要取消的预订的详细信息,以确认是否可以进行取消预订。
​ SELECT * FROM bookings WHERE booking_id = ‘预订ID’ FOR UPDATE;
​ 使用 FOR UPDATE 锁定查询的行,以确保其他事务不能同时修改这些行。
执行取消预订操作:根据预订的详细信息,进行取消预订操作,包括更新资源状态、删除预订记录等。
UPDATE resources SET status = ‘可用’ WHERE resource_id = ‘资源ID’;
DELETE FROM bookings WHERE booking_id = ‘预订ID’;
提交或回滚事务:根据取消预订操作的结果,决定是否提交事务或回滚事务。
​ 如果取消预订操作成功,即资源状态成功更新、预订记录成功删除,使用 COMMIT 语句提交事务。
​ 如果取消预订操作失败,包括资源状态更新出错、删除预订记录出错或其他原因导致的错误,使用 ROLLBACK 语句回滚事务。
结束事务:使用 COMMIT 或 ROLLBACK 语句结束事务。

需要注意的是:
​ 预订案例涉及到对资源表和预订表的操作,要确保数据的一致性和可靠性,需要仔细考虑并发访问、锁定机制、异常处理等因素;取消预订案例涉及到对资源表和预订表的操作,要确保数据的一致性和可靠性,需要仔细考虑并发访问、锁定机制、异常处理等因素。

预订

BEGIN; -- 开始事务

-- 查询资源信息
SELECT * FROM resources WHERE resource_id = '资源ID' FOR UPDATE;
SET @resource_status := 资源状态;

-- 判断资源状态是否可预订
IF @resource_status = '可用' THEN
	-- 更新资源状态
	UPDATE resources SET status = '已预订' WHERE resource_id = '资源ID';
	-- 插入预订记录
	INSERT INTO bookings (booking_id, user_id, resource_id, start_date, end_date) VALUES ('预订ID', '用户ID', '资源ID', '开始日期', '结束日期');
	COMMIT; -- 提交事务
ELSE
	ROLLBACK; -- 回滚事务
END IF;

取消预订

BEGIN; -- 开始事务

-- 查询预订信息
SELECT * FROM bookings WHERE booking_id = '预订ID' FOR UPDATE;
SET @booking_exists := ROW_COUNT();

-- 判断是否存在预订记录
IF @booking_exists > 0 THEN
	-- 存在预订记录,执行取消预订操作
	UPDATE resources SET status = '可用' WHERE resource_id = '资源ID';
	DELETE FROM bookings WHERE booking_id = '预订ID';
	COMMIT; -- 提交事务
ELSE
	ROLLBACK; -- 回滚事务
END IF;
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值