公告

微信

欢迎大家私信交流

Skip to content

mysql

创建数据库

卸载了mysql@5.7

安装了mysql@8.0

理解一下创建数据库,以及表与表之间的关联。

选择语句 select

算术

AS别名

唯一列表 DISTINCT

where使用

=

ANDORNOT

比较运算符

算术表达式

IN

BETWEEN

LIKE

LIKE '%y%':匹配任何字符

_ 单个字符

REGEXP

  • ^ 开始
  • $ 结束
  • | 逻辑或
  • [abcd] 包含abcd
  • [a-h] 包含a-h的字母

NULL

ORDER BY

列排序

LIMIT

偏移量 + 最大行数

连接 JOIN

JOIN

跨数据库连接

当前数据库和想使用的表不同库时使用数据库名.表名

SELF JOIN

自连接,谁是谁的经理。

sql
SELECT 
    e.employee_id,
    e.first_name,
    m.first_name AD manager_name
         FROM employee e
         Join employee m
         ON e.reports_to = m.employee_id;

多表链接

sql
SELECT 
       o.order_id,
       o.order_date,
       c.first_name,
       c.last_name,
       os.name AS status
  FROM orders o
  JOIN customers c
    ON o.customer_id = c.customer_id
  JOIN order_statuses os
    ON o.status = os.order_status_id;
sql
SELECT 
       p.date,
       p.invoice_id,
       p.amount,
       c.name,
       pm.name AS method_name
  FROM payments p
  JOIN clients c
    ON p.client_id = c.client_id
  JOIN payment_methods pm
    ON p.payment_method = pm.payment_method_id;

复合链接条件

复合主键

sql
SELECT *
  FROM order_items oi
  JOIN order_items_notes oit
   ON oi.product_id = oit.product_id AND oi.order_id = oit.order_id;

隐式链接

JOIN 写成 表,表 WHERE 条件

容易忘记写条件,形成笛卡尔积

外连接

sql
-- 内连接,只能看到有order_id的
SELECT 
       c.customer_id,
       c.first_name,
       o.order_id
  FROM customers c
  JOIN orders o
    ON c.customer_id = o.customer_id
  ORDER BY c.customer_id;

当你的用户没有订单id,但是你也想看到用户的信息。你可以使用外连接。

sql
-- 外连接,能看见没有order_id的
-- LEFT JOIN 留下左表的数据
-- 或者 RIGHT JOIN 具体要看两张表的位置
SELECT 
       c.customer_id,
       c.first_name,
       o.order_id
  FROM customers c
  LEFT JOIN orders o
    ON c.customer_id = o.customer_id
  ORDER BY c.customer_id;

不写就是内连接,写了就是左右连接,可能出现相同的结果。

sql
SELECT 
       p.product_id,
       p.name,
       oi.quantity
  FROM products p
  LEFT JOIN order_items od
    ON p.customer_id = oi.customer_id;

多表外连接

sql
SELECT 
       c.customer_id,
       c.first_name, 
       o.order_id,
       sh.name AS shipper,
  FROM customers c
  LEFT JOIN orders o
    ON c.customer_id = o.customer_id
  LEFT JOIN shippers sh
    ON o.shipper_id = sh.shipper_id
  ORDER BY c.customer_id;

尽量不用右连接。

先JOIN,看看是否按照我们所想展示出数据。

自外连接

sql
SELECT 
    e.employee_id,
    e.first_name,
    m.first_name AD manager_name
         FROM employee e
         LEFT Join employee m
         ON e.reports_to = m.employee_id;

USING子句

必须两列的名字都一样的。

sql
SELECT 
       o.order_id,
       c.first_name,
       sh.name AS shipper
  FROM orders p
  JOIN customers c
    USING (customer_id)
  LEFT JOIN shippers sj
    USING (shipper_id)
sql
SELECT *
  FROM order_items oi
  JOIN order_item_notes oin
    USING (product_id,order_id)
sql
USE sql_invoicing;

SELECT 
       p.date,
       c.name AS client,
       p.amount,
       pm.name AS payment_method
  FROM payments p
   JOIN clients c
    USING (client_id)
   JOIN payment_methods pm
    ON p.payment_method = pm.payment_method_id;

自然连接

不推荐~

交叉连接

组合~

sql
SELECT 
       sh.name AS shipper,
       p.name AS product,
  FROM shippers sh
    CROSS JOIN products p
    ORDER BY sh.name

联合

sql
SELECT first_name 
  FROM archived_orders
UNION
SELECT name
  FROM shippers

列需要相同数量。

sql
SELECT 
       c.customer_id,
       c.first_name,
       c.points,
       'Bronze' AS type
  FROM customers c
  WHERE c.points <= 2000
UNION
SELECT 
       c.customer_id,
       c.first_name,
       c.points,
       'Sliver' AS type
  FROM customers c
  WHERE c.points < 2000 AND c.points <= 3000
UNION
SELECT 
       c.customer_id,
       c.first_name,
       c.points,
       'Gold' AS type
  FROM customers c
  WHERE c.points > 3000 AND c.points < 3000
ORDER BY first_name;

列属性

Datatype:varchar和char的区别

PK:primary key

NN:not null

AI:auto increment

Default:默认值

INSERT

基础语句

sql
-- 列和值一一对应
INSERT INTO `表名` ([列集合]) VALUES ([值集合]);

插入多行

sql
INSERT INTO `表名` ([列集合]) VALUES ([值集合]), ([值集合]), ...;

插入分层行

LAST_INSERT_ID

创建表复制

sql
CREATE TABLE order_archived AS 
SELECT * FROM orders;
sql
CREATE TABLE invoices_archived AS
SELECT 
  i.invoice_id,
  c.name,
  i.invoice_date
  FROM invoices i
  JOIN clients c
   ON i.client_id = c.client_id
  WHERE i.payment_date IS NOT NULL;

更新单行

sql
UPDATE `表名` SET ([列名 = 值]) WHERE `条件`

更新多行

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

在Updates中用子查询

sql
UPDATE orders
SET comments = 'GOLDEN'
WHERE customer_id 
  IN (SELECT customer_id FROM customers WHERE points > 3000);

删除行

sql
DELETE FROM invoices WHERE invoice_id = 1;

恢复数据库

sql
-- 重新执行命令~

聚合函数

sql
-- 最大值 最小值 平均值 总和 只运行非空值
SELECT MAX(invoice_total) AS highest,
       MIN(invoice_total) AS lowest,
       AVG(invoice_total) AS average,
       SUM(invoice_total * 1.1) AS total_of_invoices,
       COUNT(payment_date) AS count_of_payments,
       COUNT(*) AS total_records
  FROM invoices;

-- DISTINCT 保证不重复

GROUP BY子句

sql
-- 关键字有一定的顺序
SELECT 
  client_id,
  SUM(invoice_total) AS total_sales
FROM invoices
JOIN clients USING (client_id)
WHERE invoice_date >= '2019-07-01'
-- GROUP BY client_id
GROUP BY state, city
ORDER BY total_sales DESC;

HAVING子句

在分组之后筛选数据

ROLLUP运算符

汇聚总和

编写复杂查询 子查询

子查询

子查询的条件 为在表中查询

IN运算符

NOT IN 不在订单列表里面

子查询vs连接

可读性和查询的摩擦

ALL关键字

ALL和MAX可以相互切换

ANY关键字

大于括号的最小值

相关子查询

没懂

EXISTS运算符

并不会把真正的结果集返回,而是返回是否有没有。

EXISTS 操作符用来判断一个子查询是否返回数据行。

SELECT 子句的子查询

套娃

FROM 子句的子查询

套娃

事务

多次数据库修改为一个原子,要么成功要么失败

原子性、一致性、隔离性、持久性。

创建事务

开启事务,提交事务。

没有提交的事物,会阻塞其他sql的执行。

并发和锁定

表锁/行锁

事务的隔离级别

lost updates

脏读

一个事务读取了尚未被提交的数据。

解决方案:读已提交。

不可重复读 不一致读

读取了两次数据,但是两次数据不一样。

首次读取的是快照。

解决方案:可重复读。

幻读

突然出现的数据没有被查询到。

解决方案,序列化。

读未提交隔离级别

读已提交隔离级别

可重复读隔离级别

序列化隔离级别

上次更新于: