网站建设的栏目内容是网站总体策划的内容有哪些
网站建设的栏目内容是,网站总体策划的内容有哪些,购物网站策划书,免费的公众号排版工具这篇文章是我观看 Mosh 的 MySQL 完整版课程进行题目练习的记录#xff0c;视频的话去 B 站搜索就能找到#xff0c;数据库文件的话可以从这里下载。 目录第二章2- SELECT 子句3- WHERE 子句4- 逻辑运算符5- IN 运算符6- BETWEEN 运算符7- LIKE 运算符8- REGEXP 运算符#…这篇文章是我观看 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 JOIN2- 跨数据库连接3- 自连接 SELF JOIN4- 多表连接5- 复合连接条件复合主键6- 隐式连接不建议使用7- 外连接 OUTER JOIN8- 多表外连接9- 自外连接10- USING 子句11- 自然连接不建议使用12- 交叉连接13- 联合 Unions第四章1- 列属性2- 插入单行3- 插入多行4- 插入分层行5- 创建表复制6- 更新单行7- 更新多行8- 在 Update 中使用子查询9- 删除行10- 恢复重建数据库第五章1- 聚合函数 Aggregate Functions2- 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 Procedures2- 创建存储过程3- 使用工作台创建存储过程4- 删除存储过程5- 参数 Parameters6- 处理为 NULL 和多个参数7- 验证参数8- 输出参数不建议使用9- 变量10- 函数第十一章1- 事务 Transaction2- 创建事务3- 并发和锁定 Concurrency and Locking4- 并发问题5- 事务隔离级别 Transaction Isolation Level6- 死锁 Deadlocks第二章
2- SELECT 子句
题目 解答
USE sql_store;SELECT name, unit_price, unit_price * 1.1 AS new_price
FROM products3- WHERE 子句
题目 注这是 2019 年的课程
解答
SELECT *
FROM orders
WHERE order_date 2019-01-014- 逻辑运算符
问题 解答
SELECT *
FROM order_items
WHERE order_id 6 AND (quantity * unit_price) 305- 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-017- LIKE 运算符
问题 解答
SELECT *
FROM customers
WHERE address LIKE %trail% OR address LIKE %avenue%SELECT *
FROM customers
WHERE phone LIKE %98- REGEXP 运算符正则表达式
问题 解答
SELECT *
FROM customers
WHERE first_name REGEXP ELKA|AMBURSELECT *
FROM customers
WHERE last_name REGEXP EY$|ON$SELECT *
FROM customers
WHERE last_name REGEXP ^MY|SESELECT *
FROM customers
WHERE last_name REGEXP B[RU]9- IS NULL 运算符
问题 解答
SELECT *
FROM orders
WHERE shipper_id IS NULL10- 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 DESC11- 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_id2- 跨数据库连接
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_idemployees 表当中的每一个员工都有员工编号而员工的直属上司也有编号可以通过自连接找到每一个编号员工的名字以及其直属上司的名字。自连接时要给表起不同的别名且要在查询的列前面加前缀。
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_id5- 复合连接条件复合主键
当表中存在复合主键时连接表就需要多个条件语句了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_id6- 隐式连接不建议使用
对于本章第一节的连接我们也可以用 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_id8- 多表外连接
问题 解答对于 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_id9- 自外连接
在自连接中我们可以找到每一个编号员工的名字以及其直属上司的名字但是缺少了直属上司的编号这是最高的直属上司自己没有任何的上司所以在自内连接中会被忽略改为使用自外连接就可以得到这个条目。
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_id10- 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_id11- 自然连接不建议使用
我们知道连接两个表的关联列如果名字相同就可以用 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 product13- 联合 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) 表示可变长的字符串最长为 50CHAR(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 NULL6- 更新单行
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-018- 在 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-312- 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 date3- 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 1004- 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注意如果使用了 ROLLUPGROUP 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 35- 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.7452- 字符串函数
# 求字符串长度
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 tree3- 日期函数 如图所示NOW 函数可返回当前的日期时间CURDATE 返回当前日期CURTIME 返回当前时间对日期使用 YEAR 可获得年使用 MONTH 可获得月以此类推。
4- 格式化日期函数 时间为 2022/5/5 16:58可以用格式化日期函数自定义时间的显示格式。
5- 计算日期与时间 DATE_ADD(NOW(), INTERVAL 1 YEAR) # 2023-05-05 17:08:53DATE_ADD(NOW(), INTERVAL 1 MONTH) # 2022-06-05 17:08:53DATE_ADD(NOW(), INTERVAL 1 DAY) # 2022-05-06 17:08:53DATE_SUB(NOW(), INTERVAL 1 YEAR) # 2021-05-05 17:08:53DATE_SUB(NOW(), INTERVAL 1 MONTH) # 2022-04-05 17:08:53DATE_SUB(NOW(), INTERVAL 1 DAY) # 2022-05-04 17:08:53DATEDIFF(NOW(), 2023-01-01) # 124DATE_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.name8- CASE 函数
问题生成以下查询最后一列是根据倒数第二列生成的。 解答
SELECTCONCAT(first_name, , last_name) AS customer,points,CASEWHEN points 3000 THEN GoldWHEN points BETWEEN 2000 AND 3000 THEN SilverWHEN points 2000 THEN BronzeEND 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 BYHAVING和 UNION 时视图就是可更新的。
4- WITH OPTION CHECK 子句
在生成视图的代码最后使用 WITH OPTION CHECK 子句可以阻止对视图中的一行进行更新或者删除。
5- 视图总结
视图是虚拟的表它包含的不是数据而是根据需要检索数据的查询。假设视图包含的查询十分复杂在生成视图之后我们就可以直接在视图上进行后续的操作更加简单但性能不变因为本质还是得先执行复杂查询。同时我们也可以保护基础数据增加安全性。
第九章
1- 什么是存储过程 Stored Procedures
存储过程是一个包含一堆 SQL 代码的数据库对象类似于函数应用程序通过调用存储过程来获取或保存数据因为 SQL 代码如果和应用程序代码放在一起会很麻烦难读、多次编译。 2- 创建存储过程
问题创建一个存储过程其中包含的 SQL 语句是返回所有 balanceinvoice_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后面写存储过程的名称和括号再然后就是在 BEGIN 和 END 的中间写查询语句之后再用一次分隔符 $$这样两个分隔符之间的内容就是 MySQL 需要执行的内容最后再把分隔符改回来。
调用创建好的存储过程可以通过工作台或者用 CALL 语句
CALL sql_invoicing.get_invoices_with_balance();3- 使用工作台创建存储过程
如果觉得创建存储过程需要定义新的分隔符太麻烦可以通过右键点击库中的 Stored Procedures选择创建存储过程就会弹出新的窗口在红色框直接写我们需要的查询语句然后点击右下角的 Apply 即可。 4- 删除存储过程
要删除我们前面创建过的存储过程用下面这一行代码即可
DROP PROCEDURE get_invoices_with_balance5- 参数 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/diannao/91541.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!