Mosh 的 MySQL 课程编程练习题目与答案

这篇文章是我观看 Mosh 的 MySQL 完整版课程进行题目练习的记录,视频的话去 B 站搜索就能找到,数据库文件的话可以从这里下载。

目录

    • 第二章
      • 2- SELECT 子句
      • 3- WHERE 子句
      • 4- 逻辑运算符
      • 5- IN 运算符
      • 6- BETWEEN 运算符
      • 7- LIKE 运算符
      • 8- REGEXP 运算符(正则表达式)
      • 9- IS NULL 运算符
      • 10- ORDER BY 子句
      • 11- LIMIT 子句
    • 第三章
      • 1- 内连接 INNER JOIN
      • 2- 跨数据库连接
      • 3- 自连接 SELF JOIN
      • 4- 多表连接
      • 5- 复合连接条件(复合主键)
      • 6- 隐式连接(不建议使用)
      • 7- 外连接 OUTER JOIN
      • 8- 多表外连接
      • 9- 自外连接
      • 10- USING 子句
      • 11- 自然连接(不建议使用)
      • 12- 交叉连接
      • 13- 联合 Unions
    • 第四章
      • 1- 列属性
      • 2- 插入单行
      • 3- 插入多行
      • 4- 插入分层行
      • 5- 创建表复制
      • 6- 更新单行
      • 7- 更新多行
      • 8- 在 Update 中使用子查询
      • 9- 删除行
      • 10- 恢复(重建)数据库
    • 第五章
      • 1- 聚合函数 Aggregate Functions
      • 2- GROUP BY 子句
      • 3- HAVING 子句
      • 4- ROLLUP 运算符
    • 第六章
      • 2- 子查询
      • 3- IN 运算符
      • 4- 子查询 vs 连接
      • 5- ALL 关键字
      • 6- ANY 关键字
      • 7- 相关子查询(子查询中用到了父表)
      • 8- EXISTS 运算符
      • 9- SELECT 子句中的子查询
      • 10- FROM 子句中的子查询(更推荐视图)
    • 第七章
      • 1- 数值函数
      • 2- 字符串函数
      • 3- 日期函数
      • 4- 格式化日期函数
      • 5- 计算日期与时间
      • 6- 处理 NULL 值的函数
      • 7- IF 函数
      • 8- CASE 函数
    • 第八章
      • 1- 创建视图
      • 2- 更新或删除视图
      • 3- 可更新视图
      • 4- WITH OPTION CHECK 子句
      • 5- 视图总结
    • 第九章
      • 1- 什么是存储过程 Stored Procedures
      • 2- 创建存储过程
      • 3- 使用工作台创建存储过程
      • 4- 删除存储过程
      • 5- 参数 Parameters
      • 6- 处理为 NULL 和多个参数
      • 7- 验证参数
      • 8- 输出参数(不建议使用)
      • 9- 变量
      • 10- 函数
    • 第十一章
      • 1- 事务 Transaction
      • 2- 创建事务
      • 3- 并发和锁定 Concurrency and Locking
      • 4- 并发问题
      • 5- 事务隔离级别 Transaction Isolation Level
      • 6- 死锁 Deadlocks


第二章

2- SELECT 子句

题目:

在这里插入图片描述

解答:

USE sql_store;SELECT name, unit_price, unit_price * 1.1 AS new_price
FROM products

3- WHERE 子句

题目:

在这里插入图片描述

注:这是 2019 年的课程

解答:

SELECT *
FROM orders
WHERE order_date >= '2019-01-01'

4- 逻辑运算符

问题:

在这里插入图片描述

解答:

SELECT *
FROM order_items
WHERE order_id = 6 AND (quantity * unit_price) > 30

5- IN 运算符

问题:

在这里插入图片描述

解答:

SELECT *
FROM products
WHERE quantity_in_stock IN (49, 38, 72)

6- BETWEEN 运算符

问题:

在这里插入图片描述

解答:

SELECT *
FROM customers
WHERE birth_date BETWEEN '1990-01-01' AND '2000-01-01'

7- LIKE 运算符

问题:

在这里插入图片描述

解答:

SELECT *
FROM customers
WHERE address LIKE '%trail%' OR address LIKE '%avenue%'
SELECT *
FROM customers
WHERE phone LIKE '%9'

8- REGEXP 运算符(正则表达式)

问题:

在这里插入图片描述

解答:

SELECT *
FROM customers
WHERE first_name REGEXP 'ELKA|AMBUR'
SELECT *
FROM customers
WHERE last_name REGEXP 'EY$|ON$'
SELECT *
FROM customers
WHERE last_name REGEXP '^MY|SE'
SELECT *
FROM customers
WHERE last_name REGEXP 'B[RU]'

9- IS NULL 运算符

问题:

在这里插入图片描述

解答:

SELECT *
FROM orders
WHERE shipper_id IS NULL

10- ORDER BY 子句

问题:

在这里插入图片描述

返回 order_id 为 2 的表,且按总价格降序排列

解答:

SELECT order_id, product_id, quantity, unit_price
FROM order_items
WHERE order_id = 2
ORDER BY quantity * unit_price DESC

11- LIMIT 子句

问题:

在这里插入图片描述

返回 points 最高的三个顾客

解答:

SELECT *
FROM customers
ORDER BY points DESC
LIMIT 3

第三章

1- 内连接 INNER JOIN

问题:连接 order_items 和 products 表,返回 order_id、product_id 和order_items 中的 quantity、unit_price

解答:JOIN 即为 INNER JOIN,默认就是内连接

SELECT order_id, oi.product_id, quantity, oi.unit_price
FROM order_items AS oi
JOIN products AS pON oi.product_id = p.product_id

2- 跨数据库连接

USE sql_store;SELECT *
FROM order_items AS oi
JOIN sql_inventory.products AS pON oi.product_id = p.product_id

使用 USE 选中一个数据库作为当前数据库,然后对于不在此数据库中的表,例如另一个数据库 sql_inventory 中的 products 表,可以通过加前缀进行连接。

3- 自连接 SELF JOIN

USE sql_hr;SELECTe.employee_id,e.first_name,m.first_name AS Manager
FROM employees AS e
JOIN employees AS mON e.reports_to = m.employee_id

employees 表当中的每一个员工都有员工编号,而员工的直属上司也有编号,可以通过自连接找到每一个编号员工的名字以及其直属上司的名字。自连接时要给表起不同的别名,且要在查询的列前面加前缀。

4- 多表连接

问题:将 sql_invoicing 数据库里面的 payments 表与 payment_methods、clients 表进行连接。

解答

USE sql_invoicing;SELECT p.date,p.amount,pm.name,c.name
FROM payments AS p
JOIN payment_methods AS pmON p.payment_method = pm.payment_method_id
JOIN clients AS cON p.client_id = c.client_id

5- 复合连接条件(复合主键)

当表中存在复合主键时,连接表就需要多个条件语句了(AND),例如 order_items 表的主键就是由 order_id 和 product_id 组成的:

在这里插入图片描述

如果想将 order_items 与 order_item_notes 连接起来,代码如下:

USE sql_store;SELECT *
FROM order_items AS oi
JOIN order_item_notes AS oinON oi.order_id = oin.order_idAND oi.product_id = oin.product_id

6- 隐式连接(不建议使用)

对于本章第一节的连接,我们也可以用 WHERE 子句实现:

SELECT order_id, oi.product_id, quantity, oi.unit_price
FROM order_items AS oi, products AS p
WHERE oi.product_id = p.product_id

虽然可以得到与使用 JOIN 一样的功能,但是不建议使用,因为很容易忘记使用 WHERE 子句,不小心得到交叉连接。而使用 JOIN 则规定一定要写 ON 后面的条件,否则会得到语法错误。

7- 外连接 OUTER JOIN

问题:连接 product 表和 order_items 表,返回 product_id、name、quantity, 但是要包含所有的产品,无论这个产品是否有 order

解答:LEFT JOIN 和 RIGHT JOIN 即为 LEFT OUTER JOIN 和 RIGHT OUTER JOIN,默认就是外连接。LEFT JOIN 就是把左边的表的所有内容进行返回,而不管它是否满足 ON 后面的条件;RIGHT JOIN 就是把右边的表的所有内容进行返回,也是不管它是否满足 ON 后面的条件。

SELECT p.product_id, p.name, oi.quantity
FROM products AS p
LEFT JOIN order_items AS oiON p.product_id = oi.product_id

8- 多表外连接

问题

在这里插入图片描述

解答:对于 customers 表和 order_statuses 表,内连接和外连接是一样的,因为每一个 order 都肯定有 customer 和 status

SELECT o.order_date,o.order_id,c.first_name,s.name AS shipper,os.name AS status
FROM orders AS o
LEFT JOIN customers AS c  # 可用 JOINON o.customer_id = c.customer_id
LEFT JOIN order_statuses AS os  # 可用 JOINON o.status = os.order_status_id
LEFT JOIN shippers AS sON o.shipper_id = s.shipper_id

9- 自外连接

在自连接中,我们可以找到每一个编号员工的名字以及其直属上司的名字,但是,缺少了直属上司的编号,这是最高的直属上司自己没有任何的上司,所以在自(内)连接中会被忽略,改为使用自外连接就可以得到这个条目。

USE sql_hr;SELECTe.employee_id,e.first_name,m.first_name AS Manager
FROM employees AS e
LEFT JOIN employees AS mON e.reports_to = m.employee_id

在这里插入图片描述

10- USING 子句

问题:从 sql_invoicing 库的 payments 表中查询如下结果

在这里插入图片描述

解答:连接两个表的关联列如果名字相同,就可以用 USING,如果名字不相同就还得用 ON

USE sql_invoicing;SELECTp.date,p.client_id AS client,p.amount,pm.name
FROM payments AS p
JOIN clients AS cUSING (client_id)
JOIN payment_methods AS pmON p.payment_method = pm.payment_method_id

11- 自然连接(不建议使用)

我们知道,连接两个表的关联列如果名字相同,就可以用 USING。

SELECTo.order_id,c.first_name
FROM orders AS o
JOIN customers AS cUSING (customer_id)

有一种比用 USING 更加偷懒的方法,是让数据库软件自己找出具有相同名字的列作为关联列,这就是所谓的自然连接。

SELECTo.order_id,c.first_name
FROM orders AS o
NATURAL JOIN customers AS c

但是这样会导致我们无法控制数据库的行为,所以不建议使用。

12- 交叉连接

问题

在这里插入图片描述

解答:交叉连接就是返回两个表中的所有内容,所以没有 ON 条件语句。
显式就是用一个表 CROSS JOIN 另一个表,隐式就是 FROM 多个表

显式

SELECTp.name AS product,s.name AS shipper
FROM products AS p
CROSS JOIN shippers AS s
ORDER BY product

隐式

SELECTp.name AS product,s.name AS shipper
FROM products AS p, shippers AS s
ORDER BY product

13- 联合 Unions

问题:从 customers 表中查询下列结果,其中 type 分为青铜、白银和黄金,对应 points 为 2000 以下,2000 - 3000 和 3000 以上,结果按姓氏排序

在这里插入图片描述

解答

SELECTcustomer_id,first_name,points,'Bronze' AS type
FROM customers
WHERE points < 2000
UNION
SELECTcustomer_id,first_name,points,'Silver' AS type
FROM customers
WHERE points BETWEEN 2000 AND 3000
UNION
SELECTcustomer_id,first_name,points,'Gold'
FROM customers AS type
WHERE points > 3000
ORDER BY first_name

第四章

1- 列属性

点击表格的第二个图标,可以看到表格的各种属性

在这里插入图片描述

例如,customers 表中,PK 表示主键,所以 customer_id 就是主键,且它的 AI 是勾选的,意思是自动递增,即新增(插入)一行时会自动填入加一的值。NN 表示 None NULL 即不能为 NULL 值。Datatype 是数据类型,VARCHAR(50) 表示可变长的字符串,最长为 50;CHAR(2) 表示不可变长的字符串,长度固定为 2

在这里插入图片描述

2- 插入单行

INSERT INTO 表名 (列名,如果全选就忽略)
VALUES (1行列值),(2行列值),(3行列值)

VALUES 实际上是一个函数,负责将行转换为表,所以如果使用了子查询 SELECT 语句,就不需要 VALUES 了。

3- 插入多行

问题:
在这里插入图片描述
解答:

INSERT INTO products (name, quantity_in_stock, unit_price)
VALUES  ('Product1', 19, 2.2),('Product2', 20, 2.2),('Product3', 21, 2.2)

4- 插入分层行

如何同时向 orders 表和 order_items 表进行插入数据呢?特别地,order_items 表具有复合主键。

在这里插入图片描述

方法是先向 orders 表插入一行数据,order_id 因为是自动递增的,所以没有指定其插入值;然后借助函数 last_insert_id() ,我们可以得到最新的 order_id,然后再利用这个 order_id 在 order_items 表中进行插入。

INSERT INTO orders (customer_id, order_date, status)
VALUES (1, '2022-04-24', 1);INSERT INTO order_items  # 列全选
VALUES(last_insert_id(), 1, 1, 2.95),(last_insert_id(), 2, 1, 3.95)

5- 创建表复制

问题:在 sql_invoicing 库中,创建 invoices 表的一个副本名为 invoices_archived,用 client_name 代替 client_id 列,且只保留 payment_date 非空的行。

解答:

CREATE TABLE invoices_archived AS
SELECT i.invoice_id, i.number, c.name, i.invoice_total, i.payment_total, i.invoice_date, i.due_date, i.payment_date
FROM invoices AS i
JOIN clients AS cUSING (client_id)
WHERE i.payment_date IS NOT NULL

6- 更新单行

UPDATE 表名
SET 列名1 = 新值1, 列名2 = 新值2
WHERE 选中某一行

如果某一列有默认值,赋值的时候可以写 DEFAULT 表示新值为默认值。

7- 更新多行

MySQL 的 Workbench 默认是不能更新多行,需要点击菜单栏中的 Edit 的 Preference,然后点击 SQL Editor,将其最下面的勾选框取消勾选,然后重启软件即可。

在这里插入图片描述

问题

在这里插入图片描述

解答:

USE sql_store;UPDATE customers
SET points = points + 50
WHERE birth_date < '1990-01-01'

8- 在 Update 中使用子查询

问题:对于 sql_store 库里的 orders 表中,customer_id 对应 customers 表中 points 大于 3000 的行,更新其 comments 为 ‘Gold Customer’

解答:

UPDATE orders
SET comments = 'Gold Customer'
WHERE customer_id IN (SELECT customer_idFROM customersWHERE points > 3000
)

9- 删除行

DELETE FROM 表名
WHERE 选中某一或多行(子查询)

如果没有写 WHERE 子句,就会删除整个表,非常危险。

10- 恢复(重建)数据库

经过一系列更改后数据库发生了变化,为了后面的课程能继续使用相同的数据库,需要恢复数据库。点击菜单栏的 File 的 Open SQL Script,选择 create-databases.sql 文件,然后执行它,课程的数据库就重建好了。


第五章

1- 聚合函数 Aggregate Functions

MAX(列名)  求最大值
MIN(列名)  求最小值
AVG(列名)  求平均值
SUM(列名)  求总和
COUNT(列名)  算行数

注意聚合函数只计算非空值 Not NULL,所以对于 COUNT 函数,如果要算表中有多少行,就使用 COUNT(*) 而不是 COUNT(列名);如果要去除重复行,就写 DISTINCT 列名

问题:从 sql_invoicing 库的 invoices 表生成以下查询

在这里插入图片描述

注:第三列和第四列的结果可以与图片不同

解答:

USE sql_invoicing;SELECT 'First half of 2019' AS date_range, SUM(invoice_total) AS total_sales, SUM(payment_total) AS total_payments, SUM(invoice_total - payment_total) AS what_we_expect
FROM invoices
WHERE invoice_date BETWEEN '2019-01-01' AND '2019-06-30'
UNION
SELECT 'Second half of 2019' AS date_range, SUM(invoice_total) AS total_sales, SUM(payment_total) AS total_payments, SUM(invoice_total - payment_total) AS what_we_expect
FROM invoices
WHERE invoice_date BETWEEN '2019-07-01' AND '2019-12-31'
UNION
SELECT 'Total' AS date_range, SUM(invoice_total) AS total_sales, SUM(payment_total) AS total_payments, SUM(invoice_total - payment_total) AS what_we_expect
FROM invoices
WHERE invoice_date BETWEEN '2019-01-01' AND '2019-12-31'

2- GROUP BY 子句

问题:从 sql_invoicing 库的 payments 和 invoices 表生成以下查询,要求根据 date 和 payment_method 的组合进行分组

在这里插入图片描述

解答:

SELECT p.date AS date,pm.name AS payment_method,SUM(amount) AS total_payments
FROM payments AS p
JOIN payment_methods AS pmON p.payment_method = pm.payment_method_id
GROUP BY date, payment_method
ORDER BY date

3- HAVING 子句

WHERE 子句和 HAVING 子句有两点区别:1、前者在行分组前筛选数据,后者在行分组后筛选数据;2、前者可以使用所有的列,后者只能使用 SELECT 子句包含的列。

问题:从 sql_store 库,查询所在 state 为 VA 且消费超过 100 的顾客

在这里插入图片描述

在这里插入图片描述

解答:

SELECT c.customer_id,c.first_name,c.last_name,SUM(oi.quantity * oi.unit_price) AS total_sales
FROM customers AS c
JOIN orders AS oUSING (customer_id)
JOIN order_items AS oiUSING (order_id)
WHERE state = 'VA'
GROUP BY 	c.customer_id,c.first_name,c.last_name
HAVING total_sales > 100

4- ROLLUP 运算符

问题:从 sql_invoicing 库的 payments 表生成以下查询

在这里插入图片描述

解答:

SELECT pm.name AS payment_method,SUM(p.amount) AS total
FROM payments AS p
JOIN payment_methods AS pmON p.payment_method = pm.payment_method_id
GROUP BY pm.name WITH ROLLUP  # 不能用 payment_method

注意如果使用了 ROLLUP,GROUP BY 的列就不能用别名(payment_method),一定要用真名(pm.name),否则会出错。


第六章

2- 子查询

问题:

在这里插入图片描述

解答:

USE sql_hr;SELECT *
FROM employees
WHERE salary > (SELECT AVG(salary)FROM employees
)

3- IN 运算符

问题:

在这里插入图片描述

解答:

USE sql_invoicing;SELECT *
FROM clients
WHERE client_id NOT IN (SELECT DISTINCT client_idFROM invoices
)

4- 子查询 vs 连接

问题:用子查询和连接两种方法完成以下查询

在这里插入图片描述

解答:使用子查询还是连接的可读性更高,具体问题具体分析。

子查询

USE sql_store;SELECT DISTINCT customer_id, first_name, last_name
FROM customers
WHERE customer_id IN (SELECT customer_idFROM ordersWHERE order_id IN (SELECT order_idFROM order_itemsWHERE product_id = 3)
)

连接(这题更推荐用)

USE sql_store;SELECT DISTINCT customer_id, first_name, last_name
FROM customers
JOIN ordersUSING (customer_id)
JOIN order_itemsUSING (order_id)
WHERE order_items.product_id = 3

5- ALL 关键字

问题:

在这里插入图片描述

解答:大于 MAX 值 <=> 大于 ALL 值

USE sql_invoicing;SELECT *
FROM invoices
WHERE invoice_total > (SELECT MAX(invoice_total)FROM invoicesWHERE client_id = 3
)
USE sql_invoicing;SELECT *
FROM invoices
WHERE invoice_total > ALL (SELECT invoice_totalFROM invoicesWHERE client_id = 3
)

6- ANY 关键字

问题:

在这里插入图片描述

解答:IN <=> 等于 ANY

SELECT *
FROM clients
WHERE client_id IN (SELECT client_idFROM invoicesGROUP BY client_idHAVING COUNT(*) >= 2
)
SELECT *
FROM clients
WHERE client_id = ANY(SELECT client_idFROM invoicesGROUP BY client_idHAVING COUNT(*) >= 2
)

7- 相关子查询(子查询中用到了父表)

普通的子查询只执行一次,返回结果,然后执行父查询;相关子查询则会在父表中的每一行都执行一次,所以执行用时更长。

问题:

在这里插入图片描述

解答:

USE sql_invoicing;SELECT *
FROM invoices AS i
WHERE invoice_total > (SELECT AVG(invoice_total)FROM invoicesWHERE client_id = i.client_id
)

8- EXISTS 运算符

如果 IN 运算符后面跟着一个子查询,而子查询返回的表非常大,此时就可以使用 EXISTS 运算符代替它。EXIST 运算符会在父表中逐行判断,是否存在符合的列,如果存在则返回,所以是一次返回一行一列或一行多列,不会返回多行一列或多行多列(非常大)。

问题:

在这里插入图片描述

解答:
IN 运算符

USE sql_store;SELECT *
FROM products AS p
WHERE product_id NOT IN (SELECT product_idFROM order_items
)

EXISTS 运算符

USE sql_store;SELECT *
FROM products AS p
WHERE NOT EXISTS (SELECT product_idFROM order_itemsWHERE product_id = p.product_id
)

9- SELECT 子句中的子查询

在这里插入图片描述

要从 invoices 表中实现以上的查询,代码如下:

USE sql_invoicing;SELECT invoice_id,invoice_total,(SELECT AVG(invoice_total)FROM invoices) AS invoice_average,invoice_total - (SELECT invoice_average) AS difference
FROM invoices

有两个点要注意:1、必须使用子查询,而不能直接使用聚合函数 AVG,这是因为直接聚合只会返回一行,如图所示:

在这里插入图片描述

子查询聚合函数的作用类似于聚合得到一个平均值,然后每行都是这个值:

在这里插入图片描述
2、给第三列的平均值起了别名以后,不能直接在第四列使用,否则会报错:

在这里插入图片描述

再写一个一样的子查询又比较啰嗦,正确的做法是直接 SELECT 别名然后加括号即可 (SELECT invoice_average)

问题:

在这里插入图片描述

解答:

SELECT c.client_id,c.name,(SELECT SUM(invoice_total)FROM invoicesWHERE client_id = c.client_id) AS total_sales,(SELECT AVG(invoice_total)FROM invoices) AS average,(SELECT total_sales) - (SELECT average) AS difference
FROM clients AS c

原本以为要用连接 JOIN,但实际上用了子查询就不需要用连接了。

10- FROM 子句中的子查询(更推荐视图)

子查询可以用于各种地方,FROM 子句也不例外,如下代码:

SELECT *
FROM ( SELECT c.client_id,c.name,(SELECT SUM(invoice_total)FROM invoicesWHERE client_id = c.client_id) AS total_sales,(SELECT AVG(invoice_total)FROM invoices) AS average,(SELECT total_sales) - (SELECT average) AS differenceFROM clients AS c
) AS sales_summary
WHERE total_sales IS NOT NULL

可以得到以下的查询,去除了 total_sales 为空的行:

在这里插入图片描述

注意代码中必须给子查询一个别名,否则会报错。

第七章

1- 数值函数

# 四舍五入函数
ROUND(5.745)     # 6
ROUND(5.745, 2)  # 5.75
# 截断函数
TRUNCATE(5.745, 2)  # 5.74
# 取上限函数
CEILING(5.745) # 6
# 取下限函数
FLOOR(5.745) # 5
# 绝对值函数
ABS(-5.745)  # 5.745

2- 字符串函数

# 求字符串长度
LENGTH('Sky') # 3
# 变大写
UPPER('Sky') # 'SKY'
# 变小写
LOWER('Sky') # 'sky'
# 去掉左边空格
LTRIM('  Sky') # 'Sky'
# 去掉右边空格
RTRIM('Sky  ') # 'Sky'
# 去掉所有空格
TRIM('  Sky  ') # 'Sky'
# 从左边开始索引(起始位置为 1)
LEFT('Computer', 3) # 'Com'
# 从右边开始索引
RIGHT('Computer', 3) # 'ter'
# 用(起始位置 + 子串长度)索引
SUBSTRING('Computer', 3, 4) # 'mput'
# 寻找子串,若不存在则返回 0
LOCATE('p', 'Computer') # 4
LOCATE('a', 'Computer') # 0
# 替换子串
REPLACE('Computer', 'ter', 'ted') # 'Computed'
# 连接字符串
CONCAT('apple', ' ', 'tree') # 'apple tree'

3- 日期函数

在这里插入图片描述

在这里插入图片描述

如图所示,NOW 函数可返回当前的日期+时间,CURDATE 返回当前日期,CURTIME 返回当前时间;对日期使用 YEAR 可获得年,使用 MONTH 可获得月,以此类推。

4- 格式化日期函数

在这里插入图片描述

时间为 2022/5/5 16:58,可以用格式化日期函数自定义时间的显示格式。

5- 计算日期与时间

	DATE_ADD(NOW(), INTERVAL 1 YEAR) # '2023-05-05 17:08:53'DATE_ADD(NOW(), INTERVAL 1 MONTH) # '2022-06-05 17:08:53'DATE_ADD(NOW(), INTERVAL 1 DAY) # '2022-05-06 17:08:53'DATE_SUB(NOW(), INTERVAL 1 YEAR) # '2021-05-05 17:08:53'DATE_SUB(NOW(), INTERVAL 1 MONTH) # '2022-04-05 17:08:53'DATE_SUB(NOW(), INTERVAL 1 DAY) # '2022-05-04 17:08:53'DATEDIFF(NOW(), '2023-01-01') # '124'

DATE_ADD 与 DATE_SUB 函数可以对某个日期进行加或减(可以为负数),DATEDIFF 则可以求两个日期之差。

6- 处理 NULL 值的函数

问题:

在这里插入图片描述

解答:

SELECTCONCAT(first_name, ' ', last_name) AS name,IFNULL(phone, 'Unknown') AS phone
FROM customers

或者

SELECTCONCAT(first_name, ' ', last_name) AS name,COALESCE(phone, 'Unknown') AS phone
FROM customers

两者的区别在于,IFNULL 只是简单地用后一个值替换掉前面为 NULL 的值,而 COALESCE 可以用作 COALESCE(列1, 列2, '...'),如果列 1 为空就用列 2 替换,但如果列 2 也为空就用字符串替换。

7- IF 函数

问题:生成以下查询,最后一列是根据倒数第二列生成的。

在这里插入图片描述

解答:

SELECToi.product_id,p.name,COUNT(*) AS orders,IF(COUNT(*) > 1, 'Many times', 'Once') AS frequency
FROM order_items AS oi
JOIN products AS pON oi.product_id = p.product_id
GROUP BY oi.product_id, p.name

8- CASE 函数

问题:生成以下查询,最后一列是根据倒数第二列生成的。

在这里插入图片描述

解答:

SELECTCONCAT(first_name, ' ', last_name) AS customer,points,CASEWHEN points > 3000 THEN 'Gold'WHEN points BETWEEN 2000 AND 3000 THEN 'Silver'WHEN points < 2000 THEN 'Bronze'END AS category
FROM customers

第八章

1- 创建视图

问题:创建有 client_id、name 和 balance 三列的视图,其中 balance 是 invoice_total 与 payment_total 之差。

在这里插入图片描述

解答:

CREATE VIEW clients_balance AS
SELECTc.client_id,c.name,invoice_total - payment_total AS balance
FROM invoices AS i
JOIN clients AS cUSING (client_id)
GROUP BY client_id, name

创建了的视图经过刷新后,可以在左边目录栏找到。

在这里插入图片描述

2- 更新或删除视图

# 更新视图
REPLACE VIEW 视图名 AS ...
# 删除视图
DROP VIEW 视图名

3- 可更新视图

一般情况下我们都会在表中进行数据插入、更新或删除,但有时我们只拥有视图,如果视图是可更新的话我们就能够通过视图进行数据插入、更新或删除。当视图代码中没有 DISTINCT、聚合函数、GROUP BY(HAVING)和 UNION 时,视图就是可更新的。

4- WITH OPTION CHECK 子句

在生成视图的代码最后,使用 WITH OPTION CHECK 子句,可以阻止对视图中的一行进行更新或者删除。

5- 视图总结

视图是虚拟的表,它包含的不是数据而是根据需要检索数据的查询。假设视图包含的查询十分复杂,在生成视图之后,我们就可以直接在视图上进行后续的操作,更加简单,但性能不变(因为本质还是得先执行复杂查询)。同时我们也可以保护基础数据,增加安全性。

第九章

1- 什么是存储过程 Stored Procedures

存储过程是一个包含一堆 SQL 代码的数据库对象(类似于函数),应用程序通过调用存储过程来获取或保存数据,因为 SQL 代码如果和应用程序代码放在一起会很麻烦(难读、多次编译)。

在这里插入图片描述

2- 创建存储过程

问题:创建一个存储过程,其中包含的 SQL 语句是返回所有 balance(invoice_total - payment_total) > 0 的 invoices

在这里插入图片描述

解答

DELIMITER $$
CREATE PROCEDURE get_invoices_with_balance()
BEGINSELECT *FROM invoicesWHERE invoice_total - payment_total > 0;
END$$DELIMITER ;

在 MySQL 中,创建存储过程前需要定义新的分隔符,常用 $$,然后才是 CREATE PROCEDURE,后面写存储过程的名称和括号,再然后就是在 BEGINEND 的中间写查询语句,之后再用一次分隔符 $$,这样两个分隔符之间的内容就是 MySQL 需要执行的内容,最后再把分隔符改回来。

调用创建好的存储过程可以通过工作台,或者用 CALL 语句:

CALL sql_invoicing.get_invoices_with_balance();

3- 使用工作台创建存储过程

如果觉得创建存储过程需要定义新的分隔符太麻烦,可以通过右键点击库中的 Stored Procedures,选择创建存储过程,就会弹出新的窗口,在红色框直接写我们需要的查询语句,然后点击右下角的 Apply 即可。

在这里插入图片描述

4- 删除存储过程

要删除我们前面创建过的存储过程,用下面这一行代码即可:

DROP PROCEDURE get_invoices_with_balance

5- 参数 Parameters

问题:创建一个存储过程,它可以返回我们指定的一个 client_id 的所有 invoices

在这里插入图片描述

解答

DELIMITER $$
CREATE PROCEDURE get_invoices_with_client(client_id INT)
BEGINSELECT *FROM invoices AS iWHERE i.client_id = client_id;
END$$DELIMITER ;

创建好存储过程 get_invoices_with_client 之后,调用它需要提供 client_id 参数:

在这里插入图片描述

6- 处理为 NULL 和多个参数

问题:创建一个存储过程,它接受两个参数 client_id 和 payment_method_id,返回参数指定的所有 payments 表中的内容,如果参数为 NULL 则返回该列的所有行。

在这里插入图片描述

解答:如果参数为 NULL 则等于它自己,相当于返回所有的行

DELIMITER $$
CREATE PROCEDURE get_payments
(client_id INT,payment_method_id TINYINT
)
BEGINSELECT *FROM payments AS pWHERE p.client_id = IFNULL(client_id, p.client_id) AND p.payment_method = IFNULL(payment_method_id, p.payment_method);
END$$DELIMITER ;

想传入 NULL 作为参数,只能通过 CALL 而不是工作台进行过程的调用:

CALL sql_invoicing.get_payments(NULL, NULL);

7- 验证参数

如果参数是金额 payment_amount,我们不希望它出现负值,就可以用 IF 语句,自定义返回 SQL 的状态码和错误信息,如下所示:

在这里插入图片描述

8- 输出参数(不建议使用)

在这里插入图片描述
如果在参数前面加上 OUT,它们就是输出变量,将值通过 INTO 就能传给输出参数。调用该过程实际上就等于:

在这里插入图片描述

相当于 MySQL 自动帮我们初始化了两个变量,然后将变量传入存储过程并调用,最后再 SELECT 这两个变量,得到查询。

9- 变量

之前看到的通过 set @name = value; 定义的是用户变量,如果是在存储过程中定义的则是局部变量,如下所示:

在这里插入图片描述

10- 函数

函数和存储过程类似,区别在于函数必须返回值,而过程不一定返回值(例如执行插入和删除操作);过程可以调用函数,函数不能调用过程。更多区别看这里

在这里插入图片描述
在这里插入图片描述

第十一章

1- 事务 Transaction

定义,事务是代表单个工作单元的一组 SQL 语句,因此这一组语句要么作为整体全部执行成功,要么全部都不执行,避免了出现一些语句执行成功而另一些语句执行失败所导致的意外结果。

事务必须满足4个条件(ACID)::原子性Atomicity,或称不可分割性)、一致性Consistency)、隔离性Isolation,又称独立性)、持久性Durability)。

原子性:一个事务中的所有操作就跟原子一样不可分割,要么全部完成,要么全部不完成,不会结束在中间某个环节。

一致性:在事务开始之前和结束以后,数据库的一致性(某种预设规则)都没有被破坏,反之如果出现某些语句执行成功而某些语句执行失败的情况,一致性就可能被破坏。

隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。

持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

2- 创建事务

在这里插入图片描述

创建事务很简单,就是在一组 SQL 语句(insert, update, delete)前面加上 START TRANSACTION ,后面加上 COMMIT,这样如果你只执行第5、6行语句,是不会有结果的,必须执行第8、9行才行。

3- 并发和锁定 Concurrency and Locking

所谓并发,就是有两个或以上的用户同时访问相同的数据,当一个用户修改其他用户正在检索或者修改的数据时,并发就可能会出现问题。

模拟两个用户的方法很简单,就是在 MYSQL Workbench 的主页新建一个会话,两个会话即两个用户,然后我们尝试两个用户同时进行 UPDATE 数据的操作:

在这里插入图片描述

这是第一个用户的事务,第二个用户的事务也是一模一样,然后我们只执行第一个用户的前三行 SQL语句,此时如果我们去执行第二个用户的 SQL 语句,运行到第 3 行就会卡住(不停旋转):

在这里插入图片描述

这是因为第一个用户准备更新的那行已经被锁住了,所以别的用户无法对其进行更新。只有当第一个用户的事务 COMMIT 之后,第二个用户才可以顺利执行自己的事务。

4- 并发问题

1、Lost Updates 丢失更新

在这里插入图片描述

如图所示,当用户A和用户B都要对某行数据进行更新时,较晚提交的事务会覆盖较早提交的事务,假设如果用户B较晚提交事务,最终的结果就是 John, NY, 20,用户A所做的更新将会丢失。
解决方法就是锁定机制。

2、Dirty Reads 脏读

在这里插入图片描述

事务A将某顾客的积分从10分变成了20分,如果在事务A提交之前,事务B读取了该顾客的积分,就会是20分,事务B可能根据其作出了一些决策(例如升级会员卡),但是如果事务A提交失败回退了呢?这就相当于事务B读取到了不存在的积分数据,即所谓的脏读。

3、Non-repeatable Reads 不可重复读

在这里插入图片描述

事务A查询得到分数是10,如果事务B更新了分数值为0,则事务A中再次查询分数就会得到不一样的结果(0分),即不可重复读,这在某些场合是我们不希望看到的。

4、Phantom Reads 幻读

在这里插入图片描述

事务A正在进行查询,如果事务B在同一时间进行了分数的更新,但是提交的时间又晚于事务A,就会使得事务A错过了某些大于10分的顾客,即所谓的幻读。

5- 事务隔离级别 Transaction Isolation Level

在这里插入图片描述

共四种事务的隔离级别,最低级的是读未提交,该级别下可能出现之前提到过的所有并发问题,但是性能最好(没有锁);
其次是读已提交,它可以解决脏读的问题,例如前面例子中的事务B,只有当事务A成功提交之后,事务B才会读取该数据,但是如果事务B读取了两次数据呢?第一次读取了数据之后,事务A中修改了数据并成功提交,事务B第二次读取的数据就会不一样,即不可重复读;
MySQL 中默认的是可重复读,顾名思义,该隔离级别下的事务,多次读取同一个数据,不管有没有别的事务更改过该数据,都会得到相同的结果;
最后的是序列化,相当于让事务序列地执行,一个事务成功提交之后再开始下一个事务,但这样就没有了并行操作,性能比较差。

展示当前的事务隔离级别和更改事务隔离级别如下:

在这里插入图片描述

6- 死锁 Deadlocks

在这里插入图片描述

在这里插入图片描述

假设有两个用户,他们各自的事务都是更新 customers 和 orders 表,但是顺序不同。由于在 MySQL 中事务并发的时候,处理中的数据会被锁住,所以当两个用户都执行至第三行语句时,customers 和 orders 表都被锁住了,导致两个用户的第四行语句都无法执行,即为死锁。

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

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

相关文章

《ASP.NET Core 真机拆解》 送书活动结果公布

截至2020.09.26 本次送书活动 送福利 | 送书5本 ASP.NET Core 真机拆解 。下面把Top 5的留言截图给大家回顾一下。特别鸣谢作者罗志超提供的图书。以下5位同学将获赠书籍一本&#xff1a;傲慢的上校静阿花阿定傲慢与偏见以上同学请在2020年9月30日24&#xff1a;00之前加小二微…

跟我一起学.NetCore之静态文件处理的那些事

前言如今前后端分离开发模式如火如荼&#xff0c;开发职责更加分明&#xff08;当然前后端一起搞的模式也没有完全褪去&#xff09;&#xff1b;而对于每个公司产品实施来说&#xff0c;部署模式会稍有差别&#xff0c;有的会单独将前端文件部署为一个站点&#xff0c;有的会将…

深度学习入门笔记(3)——用梯度下降进行参数更新

首先是对感知器的简单回顾&#xff0c;假设现有的训练集为 D&#xff0c;共有 n 个训练数据&#xff0c;每个数据都有 m 个输入特征和一个输出标签。一个 epoch 就是遍历一次整个训练集&#xff0c;对于每一个训练数据&#xff0c;都计算其预测、计算误差、更新参数。 在一个 e…

ASP.NET Core Blazor Webassembly 之 路由

web最精妙的设计就是通过url把多个页面串联起来&#xff0c;并且可以互相跳转。我们开发系统的时候总是需要使用路由来实现页面间的跳转。传统的web开发主要是使用a标签或者是服务端redirect来跳转。那今天来看看Blazor是如何进行路由的。使用page指定组件的路由path我们可以在…

手撕单例模式(详解)

一:设计模式概述 1:设计模式的概念 软件设计模式&#xff08;Software Design Pattern&#xff09;&#xff0c;又称设计模式&#xff0c;是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。它描述了在软件设计过程中的一些不断重复发生的问题&#xff0…

微软发布.NET 5.0 RC1,未来将只有一个.NET

本周早些时候&#xff0c;微软发布了.NET 5.0 RC1&#xff0c;这是.NET 5 在11 月正式发布之前的第一个“go-live”版本。.NET 5 是.NET 生态系统的统一平台&#xff0c;将所有组件打包成一个跨平台包。新版本包含了.NET Core 3 的很多改进&#xff0c;包括新的语言版本(C# 9 和…

深度学习入门笔记(4)—— Pytorch 和计算图的简单介绍

Pytorch 顾名思义&#xff0c;就是 Torch 7 移植到 Python 的版本&#xff0c;其最大亮点就是自动微分、动态计算图和 Numpy 集成。 Pytorch 相比于 Numpy&#xff0c;优点在于支持 GPU 计算甚至是多设备计算&#xff0c;以及动态计算图。 在 import 的时候&#xff0c;得记住 …

leetcode26. 删除有序数组中的重复项

一:题目 二:上码 // class Solution { // public: // int removeDuplicates(vector<int>& nums) { // //排序 // sort(nums.begin(),nums.end());// //调用unique&#xff08;&#xff09;将vector当中的相同元素 放到 容器的最后面 //…

楼继伟:现有5G技术很不成熟

日前&#xff0c;财政部原部长楼继伟表示&#xff0c;基础设施适度超前是必要的&#xff0c;但有些方面过度超前&#xff0c;抬高了用户成本或不可持续的公共部门债务。现有5G技术很不成熟&#xff0c;数千亿级的投资已经布下&#xff0c;而且运营成本极高&#xff0c;找不到应…

深度学习入门笔记(5)—— Pytorch API 的基本用法框架

第一步&#xff0c;通常是定义我们的神经网络模型。类名后的括号表示我们定义的类会继承 torch.nn.Module&#xff0c;而 super 函数就是调用父类的方法&#xff0c;后面跟 __init__() 就是调用 torch.nn.Module 的构造函数&#xff0c;然后就是我们自定义的模型及其参数。在 f…

跟我一起学.NetCore之路由的最佳实现

前言路由&#xff0c;这词绝对不陌生&#xff0c;不管在前端还是后端都经常提到&#xff0c;而这节不说其他&#xff0c;就聊.NetCore的路由&#xff1b;在之前的Asp.Net MVC 中&#xff0c;路由算是面试时必问的考点&#xff0c;可见其重要性&#xff0c;它的主要作用是映射UR…

leetcode844. 比较含退格的字符串

一:题目 二:上码 class Solution {public:/**思路:1.利用栈 我们将字符串中的单个元素都入栈 当遇到#的时候将将栈顶元素弹出*/bool backspaceCompare(string s, string t) {stack<int> s1;stack<int> s2;for (int i 0; i < s.size(); i) {if(s[i] ! #) s1.pu…

BeetleX之HTTP网关部署

BeetleX组件提供了HTTP网关组件&#xff0c;但使用过程中需要自己写宿主程序来启动它。为了更好的直接使用&#xff0c;组件发布了一个基于.net core 3.1的可运行版本程序并集成了管理插件&#xff1b;只需下载程序即可以在linux或windows下部署一个HTTP网关部署。部署安装运行…

深度学习入门笔记(6)—— Logistic Regression

对比第三节中的 Adaline 和 Logistic Regression&#xff0c;可以发现它们只有两点不同&#xff1a;1、激活函数&#xff0c;Adaline 中的激活函数是恒等函数&#xff08;线性&#xff09;&#xff0c;而 Logistic Regression 中的激活函数是 Sigmoid 函数&#xff08;非线性&a…

微服务模式下,实现前后端多资源服务调用

MicroServices首先&#xff0c;我先解释下&#xff0c;文章标题的意思&#xff1a;咋看起来特别像是一个标题党????&#xff0c;可能是我没想好怎么表达&#xff0c;其实白话文就是&#xff1a;在微服务场景下&#xff0c;肯定会有很多子服务API&#xff0c;那多个前端项目…

leetcode54. 螺旋矩阵(详解)

一:题目 二:上码 class Solution { public:/**思路:1.1 2 3 45 6 7 89 10 11 1213 14 15 162.我们模拟顺时针的顺序,那么得分为4步 上面得一行 (1,2,3)左面得一行 (4,8,12)下面得一行 (16,15,14)右面得一行 (13,9,5)可以看到我们在取数字得时候,我们是每次只取…

深度学习入门笔记(7)—— Multinomial Logistic Regression / Softmax Regression

首先介绍一个非常著名的多分类数据集 MNIST&#xff0c;也就是 0 到 9 的手写数字数据集。每个图像都是 28 * 28&#xff0c;用于Pytorch 数据读取的格式是 NCHW&#xff0c;即 Number、Channel、Height、Weight。 读取图像之后&#xff0c;就能看到一个只有单通道的&#xff0…

[C#.NET 拾遗补漏]09:数据标注与数据校验

数据标注&#xff08;Data Annotation&#xff09;是类或类成员添加上下文信息的一种方式&#xff0c;在 C# 通常用特性&#xff08;Attribute&#xff09;类来描述。它的用途主要可以分为下面这三类&#xff1a;验证 Validation&#xff1a;向数据添加验证规则展现 Display&am…

2023届春招实习拉钩一面凉经

面完就当挂了 老想着其实自己其实还能回答的更好 可回不去了 计网的的ioc七层模型各层的作用 为什么是七层模型而不是两层模型 SpringBoot最核心的注解是什么 Spring中IOC原理以及相关注解 说说对Mysql数据库索引的了解 map有哪些实现 分别讲讲&#xff1f; 项目中数据库…

Pytorch中损失函数 NLLLOSS 和 CROSSENTROPYLOSS 的区别

NLLLOSS 是 negative log likelihood loss 负对数似然损失函数&#xff0c;CROSSENTROPYLOSS 是交叉熵损失函数&#xff0c;它们都是用于多分类任务的损失函数&#xff0c;正如我在笔记中提到的&#xff0c;它们实际上是一样的&#xff0c;在 Pytorch 中这两者的区别就只在于接…