欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

MySQL必備的常見(jiàn)知識(shí)點(diǎn)匯總整理

 更新時(shí)間:2020年05月06日 09:12:08   作者:Eno_Yao  
這篇文章主要介紹了MySQL必備的常見(jiàn)知識(shí)點(diǎn),結(jié)合實(shí)例形式匯總整理了mysql各種常見(jiàn)知識(shí)點(diǎn),包括登錄、退出、創(chuàng)建、增刪改查、事務(wù)等知識(shí)點(diǎn)與操作注意事項(xiàng),需要的朋友可以參考下

本文實(shí)例總結(jié)了MySQL必備的常見(jiàn)知識(shí)點(diǎn)。分享給大家供大家參考,具體如下:

最近在整理 sql 的時(shí)候發(fā)現(xiàn)一份優(yōu)秀的筆記,是原作者學(xué)習(xí) sql 所做的筆記,分享這份總結(jié)給大家,對(duì)大家對(duì) sql 的可以來(lái)一次全方位的檢漏和排查,感謝原作者 hjzCy 的付出,原文鏈接放在文章最下方,如果出現(xiàn)錯(cuò)誤,希望大家共同指出!

登錄和退出 MySQL 服務(wù)器

# 登錄MySQL
$ mysql -u root -p12345612

# 退出MySQL數(shù)據(jù)庫(kù)服務(wù)器
exit;

基本語(yǔ)法

-- 顯示所有數(shù)據(jù)庫(kù)
show databases;

-- 創(chuàng)建數(shù)據(jù)庫(kù)
CREATE DATABASE test;

-- 切換數(shù)據(jù)庫(kù)
use test;

-- 顯示數(shù)據(jù)庫(kù)中的所有表
show tables;

-- 創(chuàng)建數(shù)據(jù)表
CREATE TABLE pet (
  name VARCHAR(20),
  owner VARCHAR(20),
  species VARCHAR(20),
  sex CHAR(1),
  birth DATE,
  death DATE
);

-- 查看數(shù)據(jù)表結(jié)構(gòu)
-- describe pet;
desc pet;

-- 查詢(xún)表
SELECT * from pet;

-- 插入數(shù)據(jù)
INSERT INTO pet VALUES ('puffball', 'Diane', 'hamster', 'f', '1990-03-30', NULL);

-- 修改數(shù)據(jù)
UPDATE pet SET name = 'squirrel' where owner = 'Diane';

-- 刪除數(shù)據(jù)
DELETE FROM pet where name = 'squirrel';

-- 刪除表
DROP TABLE myorder;

建表約束

主鍵約束

-- 主鍵約束
-- 使某個(gè)字段不重復(fù)且不得為空,確保表內(nèi)所有數(shù)據(jù)的唯一性。
CREATE TABLE user (
  id INT PRIMARY KEY,
  name VARCHAR(20)
);

-- 聯(lián)合主鍵
-- 聯(lián)合主鍵中的每個(gè)字段都不能為空,并且加起來(lái)不能和已設(shè)置的聯(lián)合主鍵重復(fù)。
CREATE TABLE user (
  id INT,
  name VARCHAR(20),
  password VARCHAR(20),
  PRIMARY KEY(id, name)
);

-- 自增約束
-- 自增約束的主鍵由系統(tǒng)自動(dòng)遞增分配。
CREATE TABLE user (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(20)
);

-- 添加主鍵約束
-- 如果忘記設(shè)置主鍵,還可以通過(guò)SQL語(yǔ)句設(shè)置(兩種方式):
ALTER TABLE user ADD PRIMARY KEY(id);
ALTER TABLE user MODIFY id INT PRIMARY KEY;

-- 刪除主鍵
ALTER TABLE user drop PRIMARY KEY;

唯一主鍵

-- 建表時(shí)創(chuàng)建唯一主鍵
CREATE TABLE user (
  id INT,
  name VARCHAR(20),
  UNIQUE(name)
);

-- 添加唯一主鍵
-- 如果建表時(shí)沒(méi)有設(shè)置唯一建,還可以通過(guò)SQL語(yǔ)句設(shè)置(兩種方式):
ALTER TABLE user ADD UNIQUE(name);
ALTER TABLE user MODIFY name VARCHAR(20) UNIQUE;

-- 刪除唯一主鍵
ALTER TABLE user DROP INDEX name;

非空約束

-- 建表時(shí)添加非空約束
-- 約束某個(gè)字段不能為空
CREATE TABLE user (
  id INT,
  name VARCHAR(20) NOT NULL
);

-- 移除非空約束
ALTER TABLE user MODIFY name VARCHAR(20);

默認(rèn)約束

-- 建表時(shí)添加默認(rèn)約束
-- 約束某個(gè)字段的默認(rèn)值
CREATE TABLE user2 (
  id INT,
  name VARCHAR(20),
  age INT DEFAULT 10
);

-- 移除非空約束
ALTER TABLE user MODIFY age INT;

外鍵約束

-- 班級(jí)
CREATE TABLE classes (
  id INT PRIMARY KEY,
  name VARCHAR(20)
);

-- 學(xué)生表
CREATE TABLE students (
  id INT PRIMARY KEY,
  name VARCHAR(20),
  -- 這里的 class_id 要和 classes 中的 id 字段相關(guān)聯(lián)
  class_id INT,
  -- 表示 class_id 的值必須來(lái)自于 classes 中的 id 字段值
  FOREIGN KEY(class_id) REFERENCES classes(id)
);

-- 1. 主表(父表)classes 中沒(méi)有的數(shù)據(jù)值,在副表(子表)students 中,是不可以使用的;
-- 2. 主表中的記錄被副表引用時(shí),主表不可以被刪除。

數(shù)據(jù)庫(kù)的三大設(shè)計(jì)范式

1NF

只要字段值還可以繼續(xù)拆分,就不滿(mǎn)足第一范式。

范式設(shè)計(jì)得越詳細(xì),對(duì)某些實(shí)際操作可能會(huì)更好,但并非都有好處,需要對(duì)項(xiàng)目的實(shí)際情況進(jìn)行設(shè)定。

2NF

在滿(mǎn)足第一范式的前提下,其他列都必須完全依賴(lài)于主鍵列。如果出現(xiàn)不完全依賴(lài),只可能發(fā)生在聯(lián)合主鍵的情況下:

-- 訂單表
CREATE TABLE myorder (
  product_id INT,
  customer_id INT,
  product_name VARCHAR(20),
  customer_name VARCHAR(20),
  PRIMARY KEY (product_id, customer_id)
);

實(shí)際上,在這張訂單表中,product_name 只依賴(lài)于 product_id ,customer_name 只依賴(lài)于 customer_id 。也就是說(shuō),product_namecustomer_id 是沒(méi)用關(guān)系的,customer_nameproduct_id 也是沒(méi)有關(guān)系的。

這就不滿(mǎn)足第二范式:其他列都必須完全依賴(lài)于主鍵列!

CREATE TABLE myorder (
  order_id INT PRIMARY KEY,
  product_id INT,
  customer_id INT
);

CREATE TABLE product (
  id INT PRIMARY KEY,
  name VARCHAR(20)
);

CREATE TABLE customer (
  id INT PRIMARY KEY,
  name VARCHAR(20)
);

拆分之后,myorder 表中的 product_idcustomer_id 完全依賴(lài)于 order_id 主鍵,而 productcustomer 表中的其他字段又完全依賴(lài)于主鍵。滿(mǎn)足了第二范式的設(shè)計(jì)!

3NF

在滿(mǎn)足第二范式的前提下,除了主鍵列之外,其他列之間不能有傳遞依賴(lài)關(guān)系。

CREATE TABLE myorder (
  order_id INT PRIMARY KEY,
  product_id INT,
  customer_id INT,
  customer_phone VARCHAR(15)
);

表中的 customer_phone 有可能依賴(lài)于 order_idcustomer_id 兩列,也就不滿(mǎn)足了第三范式的設(shè)計(jì):其他列之間不能有傳遞依賴(lài)關(guān)系。

CREATE TABLE myorder (
  order_id INT PRIMARY KEY,
  product_id INT,
  customer_id INT
);

CREATE TABLE customer (
  id INT PRIMARY KEY,
  name VARCHAR(20),
  phone VARCHAR(15)
);

修改后就不存在其他列之間的傳遞依賴(lài)關(guān)系,其他列都只依賴(lài)于主鍵列,滿(mǎn)足了第三范式的設(shè)計(jì)!

查詢(xún)練習(xí)

準(zhǔn)備數(shù)據(jù)

-- 創(chuàng)建數(shù)據(jù)庫(kù)
CREATE DATABASE select_test;
-- 切換數(shù)據(jù)庫(kù)
USE select_test;

-- 創(chuàng)建學(xué)生表
CREATE TABLE student (
  no VARCHAR(20) PRIMARY KEY,
  name VARCHAR(20) NOT NULL,
  sex VARCHAR(10) NOT NULL,
  birthday DATE, -- 生日
  class VARCHAR(20) -- 所在班級(jí)
);

-- 創(chuàng)建教師表
CREATE TABLE teacher (
  no VARCHAR(20) PRIMARY KEY,
  name VARCHAR(20) NOT NULL,
  sex VARCHAR(10) NOT NULL,
  birthday DATE,
  profession VARCHAR(20) NOT NULL, -- 職稱(chēng)
  department VARCHAR(20) NOT NULL -- 部門(mén)
);

-- 創(chuàng)建課程表
CREATE TABLE course (
  no VARCHAR(20) PRIMARY KEY,
  name VARCHAR(20) NOT NULL,
  t_no VARCHAR(20) NOT NULL, -- 教師編號(hào)
  -- 表示該 tno 來(lái)自于 teacher 表中的 no 字段值
  FOREIGN KEY(t_no) REFERENCES teacher(no)
);

-- 成績(jī)表
CREATE TABLE score (
  s_no VARCHAR(20) NOT NULL, -- 學(xué)生編號(hào)
  c_no VARCHAR(20) NOT NULL, -- 課程號(hào)
  degree DECIMAL,  -- 成績(jī)
  -- 表示該 s_no, c_no 分別來(lái)自于 student, course 表中的 no 字段值
  FOREIGN KEY(s_no) REFERENCES student(no),
  FOREIGN KEY(c_no) REFERENCES course(no),
  -- 設(shè)置 s_no, c_no 為聯(lián)合主鍵
  PRIMARY KEY(s_no, c_no)
);

-- 查看所有表
SHOW TABLES;

-- 添加學(xué)生表數(shù)據(jù)
INSERT INTO student VALUES('101', '曾華', '男', '1977-09-01', '95033');
INSERT INTO student VALUES('102', '匡明', '男', '1975-10-02', '95031');
INSERT INTO student VALUES('103', '王麗', '女', '1976-01-23', '95033');
INSERT INTO student VALUES('104', '李軍', '男', '1976-02-20', '95033');
INSERT INTO student VALUES('105', '王芳', '女', '1975-02-10', '95031');
INSERT INTO student VALUES('106', '陸軍', '男', '1974-06-03', '95031');
INSERT INTO student VALUES('107', '王尼瑪', '男', '1976-02-20', '95033');
INSERT INTO student VALUES('108', '張全蛋', '男', '1975-02-10', '95031');
INSERT INTO student VALUES('109', '趙鐵柱', '男', '1974-06-03', '95031');

-- 添加教師表數(shù)據(jù)
INSERT INTO teacher VALUES('804', '李誠(chéng)', '男', '1958-12-02', '副教授', '計(jì)算機(jī)系');
INSERT INTO teacher VALUES('856', '張旭', '男', '1969-03-12', '講師', '電子工程系');
INSERT INTO teacher VALUES('825', '王萍', '女', '1972-05-05', '助教', '計(jì)算機(jī)系');
INSERT INTO teacher VALUES('831', '劉冰', '女', '1977-08-14', '助教', '電子工程系');

-- 添加課程表數(shù)據(jù)
INSERT INTO course VALUES('3-105', '計(jì)算機(jī)導(dǎo)論', '825');
INSERT INTO course VALUES('3-245', '操作系統(tǒng)', '804');
INSERT INTO course VALUES('6-166', '數(shù)字電路', '856');
INSERT INTO course VALUES('9-888', '高等數(shù)學(xué)', '831');

-- 添加添加成績(jī)表數(shù)據(jù)
INSERT INTO score VALUES('103', '3-105', '92');
INSERT INTO score VALUES('103', '3-245', '86');
INSERT INTO score VALUES('103', '6-166', '85');
INSERT INTO score VALUES('105', '3-105', '88');
INSERT INTO score VALUES('105', '3-245', '75');
INSERT INTO score VALUES('105', '6-166', '79');
INSERT INTO score VALUES('109', '3-105', '76');
INSERT INTO score VALUES('109', '3-245', '68');
INSERT INTO score VALUES('109', '6-166', '81');

-- 查看表結(jié)構(gòu)
SELECT * FROM course;
SELECT * FROM score;
SELECT * FROM student;
SELECT * FROM teacher;

1 到 10

-- 查詢(xún) student 表的所有行
SELECT * FROM student;

-- 查詢(xún) student 表中的 name、sex 和 class 字段的所有行
SELECT name, sex, class FROM student;

-- 查詢(xún) teacher 表中不重復(fù)的 department 列
-- department: 去重查詢(xún)
SELECT DISTINCT department FROM teacher;

-- 查詢(xún) score 表中成績(jī)?cè)?0-80之間的所有行(區(qū)間查詢(xún)和運(yùn)算符查詢(xún))
-- BETWEEN xx AND xx: 查詢(xún)區(qū)間, AND 表示 "并且"
SELECT * FROM score WHERE degree BETWEEN 60 AND 80;
SELECT * FROM score WHERE degree > 60 AND degree < 80;

-- 查詢(xún) score 表中成績(jī)?yōu)?85, 86 或 88 的行
-- IN: 查詢(xún)規(guī)定中的多個(gè)值
SELECT * FROM score WHERE degree IN (85, 86, 88);

-- 查詢(xún) student 表中 '95031' 班或性別為 '女' 的所有行
-- or: 表示或者關(guān)系
SELECT * FROM student WHERE class = '95031' or sex = '女';

-- 以 class 降序的方式查詢(xún) student 表的所有行
-- DESC: 降序,從高到低
-- ASC(默認(rèn)): 升序,從低到高
SELECT * FROM student ORDER BY class DESC;
SELECT * FROM student ORDER BY class ASC;

-- 以 c_no 升序、degree 降序查詢(xún) score 表的所有行
SELECT * FROM score ORDER BY c_no ASC, degree DESC;

-- 查詢(xún) "95031" 班的學(xué)生人數(shù)
-- COUNT: 統(tǒng)計(jì)
SELECT COUNT(*) FROM student WHERE class = '95031';

-- 查詢(xún) score 表中的最高分的學(xué)生學(xué)號(hào)和課程編號(hào)(子查詢(xún)或排序查詢(xún))。
-- (SELECT MAX(degree) FROM score): 子查詢(xún),算出最高分
SELECT s_no, c_no FROM score WHERE degree = (SELECT MAX(degree) FROM score);

-- 排序查詢(xún)
-- LIMIT r, n: 表示從第r行開(kāi)始,查詢(xún)n條數(shù)據(jù)
SELECT s_no, c_no, degree FROM score ORDER BY degree DESC LIMIT 0, 1;

分組計(jì)算平均成績(jī)

查詢(xún)每門(mén)課的平均成績(jī)。

-- AVG: 平均值
SELECT AVG(degree) FROM score WHERE c_no = '3-105';
SELECT AVG(degree) FROM score WHERE c_no = '3-245';
SELECT AVG(degree) FROM score WHERE c_no = '6-166';

-- GROUP BY: 分組查詢(xún)
SELECT c_no, AVG(degree) FROM score GROUP BY c_no;

分組條件與模糊查詢(xún)

查詢(xún) score 表中至少有 2 名學(xué)生選修,并以 3 開(kāi)頭的課程的平均分?jǐn)?shù)。

SELECT * FROM score;
-- c_no 課程編號(hào)
+------+-------+--------+
| s_no | c_no | degree |
+------+-------+--------+
| 103 | 3-105 |   92 |
| 103 | 3-245 |   86 |
| 103 | 6-166 |   85 |
| 105 | 3-105 |   88 |
| 105 | 3-245 |   75 |
| 105 | 6-166 |   79 |
| 109 | 3-105 |   76 |
| 109 | 3-245 |   68 |
| 109 | 6-166 |   81 |
+------+-------+--------+

分析表發(fā)現(xiàn),至少有 2 名學(xué)生選修的課程是 3-1053-245 、6-166 ,以 3 開(kāi)頭的課程是 3-1053-245 。也就是說(shuō),我們要查詢(xún)所有 3-1053-245degree 平均分。

-- 首先把 c_no, AVG(degree) 通過(guò)分組查詢(xún)出來(lái)
SELECT c_no, AVG(degree) FROM score GROUP BY c_no
+-------+-------------+
| c_no | AVG(degree) |
+-------+-------------+
| 3-105 |   85.3333 |
| 3-245 |   76.3333 |
| 6-166 |   81.6667 |
+-------+-------------+

-- 再查詢(xún)出至少有 2 名學(xué)生選修的課程
-- HAVING: 表示持有
HAVING COUNT(c_no) >= 2

-- 并且是以 3 開(kāi)頭的課程
-- LIKE 表示模糊查詢(xún),"%" 是一個(gè)通配符,匹配 "3" 后面的任意字符。
AND c_no LIKE '3%';

-- 把前面的SQL語(yǔ)句拼接起來(lái),
-- 后面加上一個(gè) COUNT(*),表示將每個(gè)分組的個(gè)數(shù)也查詢(xún)出來(lái)。
SELECT c_no, AVG(degree), COUNT(*) FROM score GROUP BY c_no
HAVING COUNT(c_no) >= 2 AND c_no LIKE '3%';
+-------+-------------+----------+
| c_no | AVG(degree) | COUNT(*) |
+-------+-------------+----------+
| 3-105 |   85.3333 |    3 |
| 3-245 |   76.3333 |    3 |
+-------+-------------+----------+

多表查詢(xún) - 1

查詢(xún)所有學(xué)生的 name,以及該學(xué)生在 score 表中對(duì)應(yīng)的 c_nodegree

SELECT no, name FROM student;
+-----+-----------+
| no | name   |
+-----+-----------+
| 101 | 曾華   |
| 102 | 匡明   |
| 103 | 王麗   |
| 104 | 李軍   |
| 105 | 王芳   |
| 106 | 陸軍   |
| 107 | 王尼瑪  |
| 108 | 張全蛋  |
| 109 | 趙鐵柱  |
+-----+-----------+

SELECT s_no, c_no, degree FROM score;
+------+-------+--------+
| s_no | c_no | degree |
+------+-------+--------+
| 103 | 3-105 |   92 |
| 103 | 3-245 |   86 |
| 103 | 6-166 |   85 |
| 105 | 3-105 |   88 |
| 105 | 3-245 |   75 |
| 105 | 6-166 |   79 |
| 109 | 3-105 |   76 |
| 109 | 3-245 |   68 |
| 109 | 6-166 |   81 |
+------+-------+--------+

通過(guò)分析可以發(fā)現(xiàn),只要把 score 表中的 s_no 字段值替換成 student 表中對(duì)應(yīng)的 name 字段值就可以了,如何做呢?

-- FROM...: 表示從 student, score 表中查詢(xún)
-- WHERE 的條件表示為,只有在 student.no 和 score.s_no 相等時(shí)才顯示出來(lái)。
SELECT name, c_no, degree FROM student, score
WHERE student.no = score.s_no;
+-----------+-------+--------+
| name   | c_no | degree |
+-----------+-------+--------+
| 王麗   | 3-105 |   92 |
| 王麗   | 3-245 |   86 |
| 王麗   | 6-166 |   85 |
| 王芳   | 3-105 |   88 |
| 王芳   | 3-245 |   75 |
| 王芳   | 6-166 |   79 |
| 趙鐵柱  | 3-105 |   76 |
| 趙鐵柱  | 3-245 |   68 |
| 趙鐵柱  | 6-166 |   81 |
+-----------+-------+--------+

多表查詢(xún) - 2

查詢(xún)所有學(xué)生的 no 、課程名稱(chēng) ( course 表中的 name ) 和成績(jī) ( score 表中的 degree ) 列。

只有 score 關(guān)聯(lián)學(xué)生的 no ,因此只要查詢(xún) score 表,就能找出所有和學(xué)生相關(guān)的 nodegree

SELECT s_no, c_no, degree FROM score;
+------+-------+--------+
| s_no | c_no | degree |
+------+-------+--------+
| 103 | 3-105 |   92 |
| 103 | 3-245 |   86 |
| 103 | 6-166 |   85 |
| 105 | 3-105 |   88 |
| 105 | 3-245 |   75 |
| 105 | 6-166 |   79 |
| 109 | 3-105 |   76 |
| 109 | 3-245 |   68 |
| 109 | 6-166 |   81 |
+------+-------+--------+

然后查詢(xún) course 表:

+-------+-----------------+
| no  | name      |
+-------+-----------------+
| 3-105 | 計(jì)算機(jī)導(dǎo)論   |
| 3-245 | 操作系統(tǒng)    |
| 6-166 | 數(shù)字電路    |
| 9-888 | 高等數(shù)學(xué)    |
+-------+-----------------+

只要把 score 表中的 c_no 替換成 course 表中對(duì)應(yīng)的 name 字段值就可以了。

-- 增加一個(gè)查詢(xún)字段 name,分別從 score、course 這兩個(gè)表中查詢(xún)。
-- as 表示取一個(gè)該字段的別名。
SELECT s_no, name as c_name, degree FROM score, course
WHERE score.c_no = course.no;
+------+-----------------+--------+
| s_no | c_name     | degree |
+------+-----------------+--------+
| 103 | 計(jì)算機(jī)導(dǎo)論   |   92 |
| 105 | 計(jì)算機(jī)導(dǎo)論   |   88 |
| 109 | 計(jì)算機(jī)導(dǎo)論   |   76 |
| 103 | 操作系統(tǒng)    |   86 |
| 105 | 操作系統(tǒng)    |   75 |
| 109 | 操作系統(tǒng)    |   68 |
| 103 | 數(shù)字電路    |   85 |
| 105 | 數(shù)字電路    |   79 |
| 109 | 數(shù)字電路    |   81 |
+------+-----------------+--------+

三表關(guān)聯(lián)查詢(xún)

查詢(xún)所有學(xué)生的 name 、課程名 ( course 表中的 name ) 和 degree 。

只有 score 表中關(guān)聯(lián)學(xué)生的學(xué)號(hào)和課堂號(hào),我們只要圍繞著 score 這張表查詢(xún)就好了。

SELECT * FROM score;
+------+-------+--------+
| s_no | c_no | degree |
+------+-------+--------+
| 103 | 3-105 |   92 |
| 103 | 3-245 |   86 |
| 103 | 6-166 |   85 |
| 105 | 3-105 |   88 |
| 105 | 3-245 |   75 |
| 105 | 6-166 |   79 |
| 109 | 3-105 |   76 |
| 109 | 3-245 |   68 |
| 109 | 6-166 |   81 |
+------+-------+--------+

只要把 s_noc_no 替換成 studentsrouse 表中對(duì)應(yīng)的 name 字段值就好了。

首先把 s_no 替換成 student 表中的 name 字段:

SELECT name, c_no, degree FROM student, score WHERE student.no = score.s_no;
+-----------+-------+--------+
| name   | c_no | degree |
+-----------+-------+--------+
| 王麗   | 3-105 |   92 |
| 王麗   | 3-245 |   86 |
| 王麗   | 6-166 |   85 |
| 王芳   | 3-105 |   88 |
| 王芳   | 3-245 |   75 |
| 王芳   | 6-166 |   79 |
| 趙鐵柱  | 3-105 |   76 |
| 趙鐵柱  | 3-245 |   68 |
| 趙鐵柱  | 6-166 |   81 |
+-----------+-------+--------+

再把 c_no 替換成 course 表中的 name 字段:

-- 課程表
SELECT no, name FROM course;
+-------+-----------------+
| no  | name      |
+-------+-----------------+
| 3-105 | 計(jì)算機(jī)導(dǎo)論   |
| 3-245 | 操作系統(tǒng)    |
| 6-166 | 數(shù)字電路    |
| 9-888 | 高等數(shù)學(xué)    |
+-------+-----------------+

-- 由于字段名存在重復(fù),使用 "表名.字段名 as 別名" 代替。
SELECT student.name as s_name, course.name as c_name, degree
FROM student, score, course
WHERE student.NO = score.s_no
AND score.c_no = course.no;

子查詢(xún)加分組求平均分

查詢(xún) 95031 班學(xué)生每門(mén)課程的平均成績(jī)。

score 表中根據(jù) student 表的學(xué)生編號(hào)篩選出學(xué)生的課堂號(hào)和成績(jī):

-- IN (..): 將篩選出的學(xué)生號(hào)當(dāng)做 s_no 的條件查詢(xún)
SELECT s_no, c_no, degree FROM score
WHERE s_no IN (SELECT no FROM student WHERE class = '95031');
+------+-------+--------+
| s_no | c_no | degree |
+------+-------+--------+
| 105 | 3-105 |   88 |
| 105 | 3-245 |   75 |
| 105 | 6-166 |   79 |
| 109 | 3-105 |   76 |
| 109 | 3-245 |   68 |
| 109 | 6-166 |   81 |
+------+-------+--------+

這時(shí)只要將 c_no 分組一下就能得出 95031 班學(xué)生每門(mén)課的平均成績(jī):

SELECT c_no, AVG(degree) FROM score
WHERE s_no IN (SELECT no FROM student WHERE class = '95031')
GROUP BY c_no;
+-------+-------------+
| c_no | AVG(degree) |
+-------+-------------+
| 3-105 |   82.0000 |
| 3-245 |   71.5000 |
| 6-166 |   80.0000 |
+-------+-------------+

子查詢(xún) - 1

查詢(xún)?cè)?3-105 課程中,所有成績(jī)高于 109 號(hào)同學(xué)的記錄。

首先篩選出課堂號(hào)為 3-105 ,在找出所有成績(jī)高于 109 號(hào)同學(xué)的的行。

SELECT * FROM score
WHERE c_no = '3-105'
AND degree > (SELECT degree FROM score WHERE s_no = '109' AND c_no = '3-105');

子查詢(xún) - 2

查詢(xún)所有成績(jī)高于 109 號(hào)同學(xué)的 3-105 課程成績(jī)記錄。

-- 不限制課程號(hào),只要成績(jī)大于109號(hào)同學(xué)的3-105課程成績(jī)就可以。
SELECT * FROM score
WHERE degree > (SELECT degree FROM score WHERE s_no = '109' AND c_no = '3-105');

YEAR 函數(shù)與帶 IN 關(guān)鍵字查詢(xún)

查詢(xún)所有和 101 、108 號(hào)學(xué)生同年出生的 no 、name 、birthday 列。

-- YEAR(..): 取出日期中的年份
SELECT no, name, birthday FROM student
WHERE YEAR(birthday) IN (SELECT YEAR(birthday) FROM student WHERE no IN (101, 108));

多層嵌套子查詢(xún)

查詢(xún) '張旭' 教師任課的學(xué)生成績(jī)表。

首先找到教師編號(hào):

SELECT NO FROM teacher WHERE NAME = '張旭'

通過(guò) sourse 表找到該教師課程號(hào):

SELECT NO FROM course WHERE t_no = ( SELECT NO FROM teacher WHERE NAME = '張旭' );

通過(guò)篩選出的課程號(hào)查詢(xún)成績(jī)表:

SELECT * FROM score WHERE c_no = (
  SELECT no FROM course WHERE t_no = (
    SELECT no FROM teacher WHERE NAME = '張旭'
  )
);

多表查詢(xún)

查詢(xún)某選修課程多于 5 個(gè)同學(xué)的教師姓名。

首先在 teacher 表中,根據(jù) no 字段來(lái)判斷該教師的同一門(mén)課程是否有至少 5 名學(xué)員選修:

-- 查詢(xún) teacher 表
SELECT no, name FROM teacher;
+-----+--------+
| no | name  |
+-----+--------+
| 804 | 李誠(chéng)  |
| 825 | 王萍  |
| 831 | 劉冰  |
| 856 | 張旭  |
+-----+--------+

SELECT name FROM teacher WHERE no IN (
  -- 在這里找到對(duì)應(yīng)的條件
);

查看和教師編號(hào)有有關(guān)的表的信息:

SELECT * FROM course;
-- t_no: 教師編號(hào)
+-------+-----------------+------+
| no  | name      | t_no |
+-------+-----------------+------+
| 3-105 | 計(jì)算機(jī)導(dǎo)論   | 825 |
| 3-245 | 操作系統(tǒng)    | 804 |
| 6-166 | 數(shù)字電路    | 856 |
| 9-888 | 高等數(shù)學(xué)    | 831 |
+-------+-----------------+------+

我們已經(jīng)找到和教師編號(hào)有關(guān)的字段就在 course 表中,但是還無(wú)法知道哪門(mén)課程至少有 5 名學(xué)生選修,所以還需要根據(jù) score 表來(lái)查詢(xún):

-- 在此之前向 score 插入一些數(shù)據(jù),以便豐富查詢(xún)條件。
INSERT INTO score VALUES ('101', '3-105', '90');
INSERT INTO score VALUES ('102', '3-105', '91');
INSERT INTO score VALUES ('104', '3-105', '89');

-- 查詢(xún) score 表
SELECT * FROM score;
+------+-------+--------+
| s_no | c_no | degree |
+------+-------+--------+
| 101 | 3-105 |   90 |
| 102 | 3-105 |   91 |
| 103 | 3-105 |   92 |
| 103 | 3-245 |   86 |
| 103 | 6-166 |   85 |
| 104 | 3-105 |   89 |
| 105 | 3-105 |   88 |
| 105 | 3-245 |   75 |
| 105 | 6-166 |   79 |
| 109 | 3-105 |   76 |
| 109 | 3-245 |   68 |
| 109 | 6-166 |   81 |
+------+-------+--------+

-- 在 score 表中將 c_no 作為分組,并且限制 c_no 持有至少 5 條數(shù)據(jù)。
SELECT c_no FROM score GROUP BY c_no HAVING COUNT(*) > 5;
+-------+
| c_no |
+-------+
| 3-105 |
+-------+

根據(jù)篩選出來(lái)的課程號(hào),找出在某課程中,擁有至少 5 名學(xué)員的教師編號(hào):

SELECT t_no FROM course WHERE no IN (
  SELECT c_no FROM score GROUP BY c_no HAVING COUNT(*) > 5
);
+------+
| t_no |
+------+
| 825 |
+------+

teacher 表中,根據(jù)篩選出來(lái)的教師編號(hào)找到教師姓名:

SELECT name FROM teacher WHERE no IN (
  -- 最終條件
  SELECT t_no FROM course WHERE no IN (
    SELECT c_no FROM score GROUP BY c_no HAVING COUNT(*) > 5
  )
);

子查詢(xún) - 3

查詢(xún) “計(jì)算機(jī)系” 課程的成績(jī)表。

思路是,先找出 course 表中所有 計(jì)算機(jī)系 課程的編號(hào),然后根據(jù)這個(gè)編號(hào)查詢(xún) score 表。

-- 通過(guò) teacher 表查詢(xún)所有 `計(jì)算機(jī)系` 的教師編號(hào)
SELECT no, name, department FROM teacher WHERE department = '計(jì)算機(jī)系'
+-----+--------+--------------+
| no | name  | department  |
+-----+--------+--------------+
| 804 | 李誠(chéng)  | 計(jì)算機(jī)系   |
| 825 | 王萍  | 計(jì)算機(jī)系   |
+-----+--------+--------------+

-- 通過(guò) course 表查詢(xún)?cè)摻處煹恼n程編號(hào)
SELECT no FROM course WHERE t_no IN (
  SELECT no FROM teacher WHERE department = '計(jì)算機(jī)系'
);
+-------+
| no  |
+-------+
| 3-245 |
| 3-105 |
+-------+

-- 根據(jù)篩選出來(lái)的課程號(hào)查詢(xún)成績(jī)表
SELECT * FROM score WHERE c_no IN (
  SELECT no FROM course WHERE t_no IN (
    SELECT no FROM teacher WHERE department = '計(jì)算機(jī)系'
  )
);
+------+-------+--------+
| s_no | c_no | degree |
+------+-------+--------+
| 103 | 3-245 |   86 |
| 105 | 3-245 |   75 |
| 109 | 3-245 |   68 |
| 101 | 3-105 |   90 |
| 102 | 3-105 |   91 |
| 103 | 3-105 |   92 |
| 104 | 3-105 |   89 |
| 105 | 3-105 |   88 |
| 109 | 3-105 |   76 |
+------+-------+--------+

UNION 和 NOTIN 的使用

查詢(xún) 計(jì)算機(jī)系電子工程系 中的不同職稱(chēng)的教師。

-- NOT: 代表邏輯非
SELECT * FROM teacher WHERE department = '計(jì)算機(jī)系' AND profession NOT IN (
  SELECT profession FROM teacher WHERE department = '電子工程系'
)
-- 合并兩個(gè)集
UNION
SELECT * FROM teacher WHERE department = '電子工程系' AND profession NOT IN (
  SELECT profession FROM teacher WHERE department = '計(jì)算機(jī)系'
);

ANY 表示至少一個(gè) - DESC ( 降序 )

查詢(xún)課程 3-105 且成績(jī) <u>至少</u> 高于 3-245score 表。

SELECT * FROM score WHERE c_no = '3-105';
+------+-------+--------+
| s_no | c_no | degree |
+------+-------+--------+
| 101 | 3-105 |   90 |
| 102 | 3-105 |   91 |
| 103 | 3-105 |   92 |
| 104 | 3-105 |   89 |
| 105 | 3-105 |   88 |
| 109 | 3-105 |   76 |
+------+-------+--------+

SELECT * FROM score WHERE c_no = '3-245';
+------+-------+--------+
| s_no | c_no | degree |
+------+-------+--------+
| 103 | 3-245 |   86 |
| 105 | 3-245 |   75 |
| 109 | 3-245 |   68 |
+------+-------+--------+

-- ANY: 符合SQL語(yǔ)句中的任意條件。
-- 也就是說(shuō),在 3-105 成績(jī)中,只要有一個(gè)大于從 3-245 篩選出來(lái)的任意行就符合條件,
-- 最后根據(jù)降序查詢(xún)結(jié)果。
SELECT * FROM score WHERE c_no = '3-105' AND degree > ANY(
  SELECT degree FROM score WHERE c_no = '3-245'
) ORDER BY degree DESC;
+------+-------+--------+
| s_no | c_no | degree |
+------+-------+--------+
| 103 | 3-105 |   92 |
| 102 | 3-105 |   91 |
| 101 | 3-105 |   90 |
| 104 | 3-105 |   89 |
| 105 | 3-105 |   88 |
| 109 | 3-105 |   76 |
+------+-------+--------+

表示所有的 ALL

查詢(xún)課程 3-105 且成績(jī)高于 3-245score 表。

-- 只需對(duì)上一道題稍作修改。
-- ALL: 符合SQL語(yǔ)句中的所有條件。
-- 也就是說(shuō),在 3-105 每一行成績(jī)中,都要大于從 3-245 篩選出來(lái)全部行才算符合條件。
SELECT * FROM score WHERE c_no = '3-105' AND degree > ALL(
  SELECT degree FROM score WHERE c_no = '3-245'
);
+------+-------+--------+
| s_no | c_no | degree |
+------+-------+--------+
| 101 | 3-105 |   90 |
| 102 | 3-105 |   91 |
| 103 | 3-105 |   92 |
| 104 | 3-105 |   89 |
| 105 | 3-105 |   88 |
+------+-------+--------+

復(fù)制表的數(shù)據(jù)作為條件查詢(xún)

查詢(xún)某課程成績(jī)比該課程平均成績(jī)低的 score 表。

-- 查詢(xún)平均分
SELECT c_no, AVG(degree) FROM score GROUP BY c_no;
+-------+-------------+
| c_no | AVG(degree) |
+-------+-------------+
| 3-105 |   87.6667 |
| 3-245 |   76.3333 |
| 6-166 |   81.6667 |
+-------+-------------+

-- 查詢(xún) score 表
SELECT degree FROM score;
+--------+
| degree |
+--------+
|   90 |
|   91 |
|   92 |
|   86 |
|   85 |
|   89 |
|   88 |
|   75 |
|   79 |
|   76 |
|   68 |
|   81 |
+--------+

-- 將表 b 作用于表 a 中查詢(xún)數(shù)據(jù)
-- score a (b): 將表聲明為 a (b),
-- 如此就能用 a.c_no = b.c_no 作為條件執(zhí)行查詢(xún)了。
SELECT * FROM score a WHERE degree < (
  (SELECT AVG(degree) FROM score b WHERE a.c_no = b.c_no)
);
+------+-------+--------+
| s_no | c_no | degree |
+------+-------+--------+
| 105 | 3-245 |   75 |
| 105 | 6-166 |   79 |
| 109 | 3-105 |   76 |
| 109 | 3-245 |   68 |
| 109 | 6-166 |   81 |
+------+-------+--------+

子查詢(xún) - 4

查詢(xún)所有任課 ( 在 course 表里有課程 ) 教師的 namedepartment

SELECT name, department FROM teacher WHERE no IN (SELECT t_no FROM course);
+--------+-----------------+
| name  | department   |
+--------+-----------------+
| 李誠(chéng)  | 計(jì)算機(jī)系    |
| 王萍  | 計(jì)算機(jī)系    |
| 劉冰  | 電子工程系   |
| 張旭  | 電子工程系   |
+--------+-----------------+

條件加組篩選

查詢(xún) student 表中至少有 2 名男生的 class 。

-- 查看學(xué)生表信息
SELECT * FROM student;
+-----+-----------+-----+------------+-------+
| no | name   | sex | birthday  | class |
+-----+-----------+-----+------------+-------+
| 101 | 曾華   | 男 | 1977-09-01 | 95033 |
| 102 | 匡明   | 男 | 1975-10-02 | 95031 |
| 103 | 王麗   | 女 | 1976-01-23 | 95033 |
| 104 | 李軍   | 男 | 1976-02-20 | 95033 |
| 105 | 王芳   | 女 | 1975-02-10 | 95031 |
| 106 | 陸軍   | 男 | 1974-06-03 | 95031 |
| 107 | 王尼瑪  | 男 | 1976-02-20 | 95033 |
| 108 | 張全蛋  | 男 | 1975-02-10 | 95031 |
| 109 | 趙鐵柱  | 男 | 1974-06-03 | 95031 |
| 110 | 張飛   | 男 | 1974-06-03 | 95038 |
+-----+-----------+-----+------------+-------+

-- 只查詢(xún)性別為男,然后按 class 分組,并限制 class 行大于 1。
SELECT class FROM student WHERE sex = '男' GROUP BY class HAVING COUNT(*) > 1;
+-------+
| class |
+-------+
| 95033 |
| 95031 |
+-------+

NOTLIKE 模糊查詢(xún)?nèi)》?/h2>

查詢(xún) student 表中不姓 "王" 的同學(xué)記錄。

-- NOT: 取反
-- LIKE: 模糊查詢(xún)
mysql> SELECT * FROM student WHERE name NOT LIKE '王%';
+-----+-----------+-----+------------+-------+
| no | name   | sex | birthday  | class |
+-----+-----------+-----+------------+-------+
| 101 | 曾華   | 男 | 1977-09-01 | 95033 |
| 102 | 匡明   | 男 | 1975-10-02 | 95031 |
| 104 | 李軍   | 男 | 1976-02-20 | 95033 |
| 106 | 陸軍   | 男 | 1974-06-03 | 95031 |
| 108 | 張全蛋  | 男 | 1975-02-10 | 95031 |
| 109 | 趙鐵柱  | 男 | 1974-06-03 | 95031 |
| 110 | 張飛   | 男 | 1974-06-03 | 95038 |
+-----+-----------+-----+------------+-------+

YEAR 與 NOW 函數(shù)

查詢(xún) student 表中每個(gè)學(xué)生的姓名和年齡。

-- 使用函數(shù) YEAR(NOW()) 計(jì)算出當(dāng)前年份,減去出生年份后得出年齡。
SELECT name, YEAR(NOW()) - YEAR(birthday) as age FROM student;
+-----------+------+
| name   | age |
+-----------+------+
| 曾華   |  42 |
| 匡明   |  44 |
| 王麗   |  43 |
| 李軍   |  43 |
| 王芳   |  44 |
| 陸軍   |  45 |
| 王尼瑪  |  43 |
| 張全蛋  |  44 |
| 趙鐵柱  |  45 |
| 張飛   |  45 |
+-----------+------+

MAX 與 MIN 函數(shù)

查詢(xún) student 表中最大和最小的 birthday 值。

SELECT MAX(birthday), MIN(birthday) FROM student;
+---------------+---------------+
| MAX(birthday) | MIN(birthday) |
+---------------+---------------+
| 1977-09-01  | 1974-06-03  |
+---------------+---------------+

多段排序

classbirthday 從大到小的順序查詢(xún) student 表。

SELECT * FROM student ORDER BY class DESC, birthday;
+-----+-----------+-----+------------+-------+
| no | name   | sex | birthday  | class |
+-----+-----------+-----+------------+-------+
| 110 | 張飛   | 男 | 1974-06-03 | 95038 |
| 103 | 王麗   | 女 | 1976-01-23 | 95033 |
| 104 | 李軍   | 男 | 1976-02-20 | 95033 |
| 107 | 王尼瑪  | 男 | 1976-02-20 | 95033 |
| 101 | 曾華   | 男 | 1977-09-01 | 95033 |
| 106 | 陸軍   | 男 | 1974-06-03 | 95031 |
| 109 | 趙鐵柱  | 男 | 1974-06-03 | 95031 |
| 105 | 王芳   | 女 | 1975-02-10 | 95031 |
| 108 | 張全蛋  | 男 | 1975-02-10 | 95031 |
| 102 | 匡明   | 男 | 1975-10-02 | 95031 |
+-----+-----------+-----+------------+-------+

子查詢(xún) - 5

查詢(xún) "男" 教師及其所上的課程。

SELECT * FROM course WHERE t_no in (SELECT no FROM teacher WHERE sex = '男');
+-------+--------------+------+
| no  | name     | t_no |
+-------+--------------+------+
| 3-245 | 操作系統(tǒng)   | 804 |
| 6-166 | 數(shù)字電路   | 856 |
+-------+--------------+------+

MAX 函數(shù)與子查詢(xún)

查詢(xún)最高分同學(xué)的 score 表。

-- 找出最高成績(jī)(該查詢(xún)只能有一個(gè)結(jié)果)
SELECT MAX(degree) FROM score;

-- 根據(jù)上面的條件篩選出所有最高成績(jī)表,
-- 該查詢(xún)可能有多個(gè)結(jié)果,假設(shè) degree 值多次符合條件。
SELECT * FROM score WHERE degree = (SELECT MAX(degree) FROM score);
+------+-------+--------+
| s_no | c_no | degree |
+------+-------+--------+
| 103 | 3-105 |   92 |
+------+-------+--------+

子查詢(xún) - 6

查詢(xún)和 "李軍" 同性別的所有同學(xué) name 。

-- 首先將李軍的性別作為條件取出來(lái)
SELECT sex FROM student WHERE name = '李軍';
+-----+
| sex |
+-----+
| 男 |
+-----+

-- 根據(jù)性別查詢(xún) name 和 sex
SELECT name, sex FROM student WHERE sex = (
  SELECT sex FROM student WHERE name = '李軍'
);
+-----------+-----+
| name   | sex |
+-----------+-----+
| 曾華   | 男 |
| 匡明   | 男 |
| 李軍   | 男 |
| 陸軍   | 男 |
| 王尼瑪  | 男 |
| 張全蛋  | 男 |
| 趙鐵柱  | 男 |
| 張飛   | 男 |
+-----------+-----+

子查詢(xún) - 7

查詢(xún)和 "李軍" 同性別且同班的同學(xué) name 。

SELECT name, sex, class FROM student WHERE sex = (
  SELECT sex FROM student WHERE name = '李軍'
) AND class = (
  SELECT class FROM student WHERE name = '李軍'
);
+-----------+-----+-------+
| name   | sex | class |
+-----------+-----+-------+
| 曾華   | 男 | 95033 |
| 李軍   | 男 | 95033 |
| 王尼瑪  | 男 | 95033 |
+-----------+-----+-------+

子查詢(xún) - 8

查詢(xún)所有選修 "計(jì)算機(jī)導(dǎo)論" 課程的 "男" 同學(xué)成績(jī)表。

需要的 "計(jì)算機(jī)導(dǎo)論" 和性別為 "男" 的編號(hào)可以在 coursestudent 表中找到。

SELECT * FROM score WHERE c_no = (
  SELECT no FROM course WHERE name = '計(jì)算機(jī)導(dǎo)論'
) AND s_no IN (
  SELECT no FROM student WHERE sex = '男'
);
+------+-------+--------+
| s_no | c_no | degree |
+------+-------+--------+
| 101 | 3-105 |   90 |
| 102 | 3-105 |   91 |
| 104 | 3-105 |   89 |
| 109 | 3-105 |   76 |
+------+-------+--------+

按等級(jí)查詢(xún)

建立一個(gè) grade 表代表學(xué)生的成績(jī)等級(jí),并插入數(shù)據(jù):

CREATE TABLE grade (
  low INT(3),
  upp INT(3),
  grade char(1)
);

INSERT INTO grade VALUES (90, 100, 'A');
INSERT INTO grade VALUES (80, 89, 'B');
INSERT INTO grade VALUES (70, 79, 'C');
INSERT INTO grade VALUES (60, 69, 'D');
INSERT INTO grade VALUES (0, 59, 'E');

SELECT * FROM grade;
+------+------+-------+
| low | upp | grade |
+------+------+-------+
|  90 | 100 | A   |
|  80 |  89 | B   |
|  70 |  79 | C   |
|  60 |  69 | D   |
|  0 |  59 | E   |
+------+------+-------+

查詢(xún)所有學(xué)生的 s_no 、c_nograde 列。

思路是,使用區(qū)間 ( BETWEEN ) 查詢(xún),判斷學(xué)生的成績(jī) ( degree ) 在 grade 表的 lowupp 之間。

SELECT s_no, c_no, grade FROM score, grade
WHERE degree BETWEEN low AND upp;
+------+-------+-------+
| s_no | c_no | grade |
+------+-------+-------+
| 101 | 3-105 | A   |
| 102 | 3-105 | A   |
| 103 | 3-105 | A   |
| 103 | 3-245 | B   |
| 103 | 6-166 | B   |
| 104 | 3-105 | B   |
| 105 | 3-105 | B   |
| 105 | 3-245 | C   |
| 105 | 6-166 | C   |
| 109 | 3-105 | C   |
| 109 | 3-245 | D   |
| 109 | 6-166 | B   |
+------+-------+-------+

連接查詢(xún)

準(zhǔn)備用于測(cè)試連接查詢(xún)的數(shù)據(jù):

CREATE DATABASE testJoin;

CREATE TABLE person (
  id INT,
  name VARCHAR(20),
  cardId INT
);

CREATE TABLE card (
  id INT,
  name VARCHAR(20)
);

INSERT INTO card VALUES (1, '飯卡'), (2, '建行卡'), (3, '農(nóng)行卡'), (4, '工商卡'), (5, '郵政卡');
SELECT * FROM card;
+------+-----------+
| id  | name   |
+------+-----------+
|  1 | 飯卡   |
|  2 | 建行卡  |
|  3 | 農(nóng)行卡  |
|  4 | 工商卡  |
|  5 | 郵政卡  |
+------+-----------+

INSERT INTO person VALUES (1, '張三', 1), (2, '李四', 3), (3, '王五', 6);
SELECT * FROM person;
+------+--------+--------+
| id  | name  | cardId |
+------+--------+--------+
|  1 | 張三  |   1 |
|  2 | 李四  |   3 |
|  3 | 王五  |   6 |
+------+--------+--------+

分析兩張表發(fā)現(xiàn),person 表并沒(méi)有為 cardId 字段設(shè)置一個(gè)在 card 表中對(duì)應(yīng)的 id 外鍵。如果設(shè)置了的話(huà),personcardId 字段值為 6 的行就插不進(jìn)去,因?yàn)樵?cardId 值在 card 表中并沒(méi)有。

內(nèi)連接

要查詢(xún)這兩張表中有關(guān)系的數(shù)據(jù),可以使用 INNER JOIN ( 內(nèi)連接 ) 將它們連接在一起。

-- INNER JOIN: 表示為內(nèi)連接,將兩張表拼接在一起。
-- on: 表示要執(zhí)行某個(gè)條件。
SELECT * FROM person INNER JOIN card on person.cardId = card.id;
+------+--------+--------+------+-----------+
| id  | name  | cardId | id  | name   |
+------+--------+--------+------+-----------+
|  1 | 張三  |   1 |  1 | 飯卡   |
|  2 | 李四  |   3 |  3 | 農(nóng)行卡  |
+------+--------+--------+------+-----------+

-- 將 INNER 關(guān)鍵字省略掉,結(jié)果也是一樣的。
-- SELECT * FROM person JOIN card on person.cardId = card.id;
注意:card 的整張表被連接到了右邊。

左外連接

完整顯示左邊的表 ( person ) ,右邊的表如果符合條件就顯示,不符合則補(bǔ) NULL 。

-- LEFT JOIN 也叫做 LEFT OUTER JOIN,用這兩種方式的查詢(xún)結(jié)果是一樣的。
SELECT * FROM person LEFT JOIN card on person.cardId = card.id;
+------+--------+--------+------+-----------+
| id  | name  | cardId | id  | name   |
+------+--------+--------+------+-----------+
|  1 | 張三  |   1 |  1 | 飯卡   |
|  2 | 李四  |   3 |  3 | 農(nóng)行卡  |
|  3 | 王五  |   6 | NULL | NULL   |
+------+--------+--------+------+-----------+

右外鏈接

完整顯示右邊的表 ( card ) ,左邊的表如果符合條件就顯示,不符合則補(bǔ) NULL 。

SELECT * FROM person RIGHT JOIN card on person.cardId = card.id;
+------+--------+--------+------+-----------+
| id  | name  | cardId | id  | name   |
+------+--------+--------+------+-----------+
|  1 | 張三  |   1 |  1 | 飯卡   |
|  2 | 李四  |   3 |  3 | 農(nóng)行卡  |
| NULL | NULL  |  NULL |  2 | 建行卡  |
| NULL | NULL  |  NULL |  4 | 工商卡  |
| NULL | NULL  |  NULL |  5 | 郵政卡  |
+------+--------+--------+------+-----------+

全外鏈接

完整顯示兩張表的全部數(shù)據(jù)。

-- MySQL 不支持這種語(yǔ)法的全外連接
-- SELECT * FROM person FULL JOIN card on person.cardId = card.id;
-- 出現(xiàn)錯(cuò)誤:
-- ERROR 1054 (42S22): Unknown column 'person.cardId' in 'on clause'

-- MySQL全連接語(yǔ)法,使用 UNION 將兩張表合并在一起。
SELECT * FROM person LEFT JOIN card on person.cardId = card.id
UNION
SELECT * FROM person RIGHT JOIN card on person.cardId = card.id;
+------+--------+--------+------+-----------+
| id  | name  | cardId | id  | name   |
+------+--------+--------+------+-----------+
|  1 | 張三  |   1 |  1 | 飯卡   |
|  2 | 李四  |   3 |  3 | 農(nóng)行卡  |
|  3 | 王五  |   6 | NULL | NULL   |
| NULL | NULL  |  NULL |  2 | 建行卡  |
| NULL | NULL  |  NULL |  4 | 工商卡  |
| NULL | NULL  |  NULL |  5 | 郵政卡  |
+------+--------+--------+------+-----------+

事務(wù)

在 MySQL 中,事務(wù)其實(shí)是一個(gè)最小的不可分割的工作單元。事務(wù)能夠保證一個(gè)業(yè)務(wù)的完整性。

比如我們的銀行轉(zhuǎn)賬:

-- a -> -100
UPDATE user set money = money - 100 WHERE name = 'a';

-- b -> +100
UPDATE user set money = money + 100 WHERE name = 'b';

在實(shí)際項(xiàng)目中,假設(shè)只有一條 SQL 語(yǔ)句執(zhí)行成功,而另外一條執(zhí)行失敗了,就會(huì)出現(xiàn)數(shù)據(jù)前后不一致。

因此,在執(zhí)行多條有關(guān)聯(lián) SQL 語(yǔ)句時(shí),事務(wù)可能會(huì)要求這些 SQL 語(yǔ)句要么同時(shí)執(zhí)行成功,要么就都執(zhí)行失敗。

如何控制事務(wù) - COMMIT / ROLLBACK

在 MySQL 中,事務(wù)的自動(dòng)提交狀態(tài)默認(rèn)是開(kāi)啟的。

-- 查詢(xún)事務(wù)的自動(dòng)提交狀態(tài)
SELECT @@AUTOCOMMIT;
+--------------+
| @@AUTOCOMMIT |
+--------------+
|      1 |
+--------------+

自動(dòng)提交的作用:當(dāng)我們執(zhí)行一條 SQL 語(yǔ)句的時(shí)候,其產(chǎn)生的效果就會(huì)立即體現(xiàn)出來(lái),且不能回滾。

什么是回滾?舉個(gè)例子:

CREATE DATABASE bank;

USE bank;

CREATE TABLE user (
  id INT PRIMARY KEY,
  name VARCHAR(20),
  money INT
);

INSERT INTO user VALUES (1, 'a', 1000);

SELECT * FROM user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a  | 1000 |
+----+------+-------+

可以看到,在執(zhí)行插入語(yǔ)句后數(shù)據(jù)立刻生效,原因是 MySQL 中的事務(wù)自動(dòng)將它提交到了數(shù)據(jù)庫(kù)中。那么所謂回滾的意思就是,撤銷(xiāo)執(zhí)行過(guò)的所有 SQL 語(yǔ)句,使其回滾到最后一次提交數(shù)據(jù)時(shí)的狀態(tài)。

在 MySQL 中使用 ROLLBACK 執(zhí)行回滾:

-- 回滾到最后一次提交
ROLLBACK;

SELECT * FROM user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a  | 1000 |
+----+------+-------+

由于所有執(zhí)行過(guò)的 SQL 語(yǔ)句都已經(jīng)被提交過(guò)了,所以數(shù)據(jù)并沒(méi)有發(fā)生回滾。那如何讓數(shù)據(jù)可以發(fā)生回滾?

-- 關(guān)閉自動(dòng)提交
SET AUTOCOMMIT = 0;

-- 查詢(xún)自動(dòng)提交狀態(tài)
SELECT @@AUTOCOMMIT;
+--------------+
| @@AUTOCOMMIT |
+--------------+
|      0 |
+--------------+

將自動(dòng)提交關(guān)閉后,測(cè)試數(shù)據(jù)回滾:

INSERT INTO user VALUES (2, 'b', 1000);

-- 關(guān)閉 AUTOCOMMIT 后,數(shù)據(jù)的變化是在一張?zhí)摂M的臨時(shí)數(shù)據(jù)表中展示,
-- 發(fā)生變化的數(shù)據(jù)并沒(méi)有真正插入到數(shù)據(jù)表中。
SELECT * FROM user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a  | 1000 |
| 2 | b  | 1000 |
+----+------+-------+

-- 數(shù)據(jù)表中的真實(shí)數(shù)據(jù)其實(shí)還是:
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a  | 1000 |
+----+------+-------+

-- 由于數(shù)據(jù)還沒(méi)有真正提交,可以使用回滾
ROLLBACK;

-- 再次查詢(xún)
SELECT * FROM user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a  | 1000 |
+----+------+-------+

那如何將虛擬的數(shù)據(jù)真正提交到數(shù)據(jù)庫(kù)中?使用 COMMIT :

INSERT INTO user VALUES (2, 'b', 1000);
-- 手動(dòng)提交數(shù)據(jù)(持久性),
-- 將數(shù)據(jù)真正提交到數(shù)據(jù)庫(kù)中,執(zhí)行后不能再回滾提交過(guò)的數(shù)據(jù)。
COMMIT;

-- 提交后測(cè)試回滾
ROLLBACK;

-- 再次查詢(xún)(回滾無(wú)效了)
SELECT * FROM user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a  | 1000 |
| 2 | b  | 1000 |
+----+------+-------+

總結(jié)

  1. 自動(dòng)提交

    • 查看自動(dòng)提交狀態(tài):SELECT @@AUTOCOMMIT ;
    • 設(shè)置自動(dòng)提交狀態(tài):SET AUTOCOMMIT = 0
  2. 手動(dòng)提交

    @@AUTOCOMMIT = 0 時(shí),使用 COMMIT 命令提交事務(wù)。

  3. 事務(wù)回滾

    @@AUTOCOMMIT = 0 時(shí),使用 ROLLBACK 命令回滾事務(wù)。

事務(wù)的實(shí)際應(yīng)用,讓我們?cè)倩氐姐y行轉(zhuǎn)賬項(xiàng)目:

-- 轉(zhuǎn)賬
UPDATE user set money = money - 100 WHERE name = 'a';

-- 到賬
UPDATE user set money = money + 100 WHERE name = 'b';

SELECT * FROM user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a  |  900 |
| 2 | b  | 1100 |
+----+------+-------+

這時(shí)假設(shè)在轉(zhuǎn)賬時(shí)發(fā)生了意外,就可以使用 ROLLBACK 回滾到最后一次提交的狀態(tài):

-- 假設(shè)轉(zhuǎn)賬發(fā)生了意外,需要回滾。
ROLLBACK;

SELECT * FROM user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a  | 1000 |
| 2 | b  | 1000 |
+----+------+-------+

這時(shí)我們又回到了發(fā)生意外之前的狀態(tài),也就是說(shuō),事務(wù)給我們提供了一個(gè)可以反悔的機(jī)會(huì)。假設(shè)數(shù)據(jù)沒(méi)有發(fā)生意外,這時(shí)可以手動(dòng)將數(shù)據(jù)真正提交到數(shù)據(jù)表中:COMMIT

手動(dòng)開(kāi)啟事務(wù) - BEGIN / START TRANSACTION

事務(wù)的默認(rèn)提交被開(kāi)啟 ( @@AUTOCOMMIT = 1 ) 后,此時(shí)就不能使用事務(wù)回滾了。但是我們還可以手動(dòng)開(kāi)啟一個(gè)事務(wù)處理事件,使其可以發(fā)生回滾:

-- 使用 BEGIN 或者 START TRANSACTION 手動(dòng)開(kāi)啟一個(gè)事務(wù)
-- START TRANSACTION;
BEGIN;
UPDATE user set money = money - 100 WHERE name = 'a';
UPDATE user set money = money + 100 WHERE name = 'b';

-- 由于手動(dòng)開(kāi)啟的事務(wù)沒(méi)有開(kāi)啟自動(dòng)提交,
-- 此時(shí)發(fā)生變化的數(shù)據(jù)仍然是被保存在一張臨時(shí)表中。
SELECT * FROM user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a  |  900 |
| 2 | b  | 1100 |
+----+------+-------+

-- 測(cè)試回滾
ROLLBACK;

SELECT * FROM user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a  | 1000 |
| 2 | b  | 1000 |
+----+------+-------+

仍然使用 COMMIT 提交數(shù)據(jù),提交后無(wú)法再發(fā)生本次事務(wù)的回滾。

BEGIN;
UPDATE user set money = money - 100 WHERE name = 'a';
UPDATE user set money = money + 100 WHERE name = 'b';

SELECT * FROM user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a  |  900 |
| 2 | b  | 1100 |
+----+------+-------+

-- 提交數(shù)據(jù)
COMMIT;

-- 測(cè)試回滾(無(wú)效,因?yàn)楸淼臄?shù)據(jù)已經(jīng)被提交)
ROLLBACK;

事務(wù)的 ACID 特征與使用

事務(wù)的四大特征:

  • A 原子性:事務(wù)是最小的單位,不可以再分割;
  • C 一致性:要求同一事務(wù)中的 SQL 語(yǔ)句,必須保證同時(shí)成功或者失敗;
  • I 隔離性:事務(wù) 1 和 事務(wù) 2 之間是具有隔離性的;
  • D 持久性:事務(wù)一旦結(jié)束 ( COMMIT ) ,就不可以再返回了 ( ROLLBACK ) 。

事務(wù)的隔離性

事務(wù)的隔離性可分為四種 ( 性能從低到高 )

  1. READ UNCOMMITTED ( 讀取未提交 )

    如果有多個(gè)事務(wù),那么任意事務(wù)都可以看見(jiàn)其他事務(wù)的未提交數(shù)據(jù)。

  2. READ COMMITTED ( 讀取已提交 )

    只能讀取到其他事務(wù)已經(jīng)提交的數(shù)據(jù)。

  3. REPEATABLE READ ( 可被重復(fù)讀 )

    如果有多個(gè)連接都開(kāi)啟了事務(wù),那么事務(wù)之間不能共享數(shù)據(jù)記錄,否則只能共享已提交的記錄。

  4. SERIALIZABLE ( 串行化 )

    所有的事務(wù)都會(huì)按照固定順序執(zhí)行,執(zhí)行完一個(gè)事務(wù)后再繼續(xù)執(zhí)行下一個(gè)事務(wù)的寫(xiě)入操作。

查看當(dāng)前數(shù)據(jù)庫(kù)的默認(rèn)隔離級(jí)別:

-- MySQL 8.x, GLOBAL 表示系統(tǒng)級(jí)別,不加表示會(huì)話(huà)級(jí)別。
SELECT @@GLOBAL.TRANSACTION_ISOLATION;
SELECT @@TRANSACTION_ISOLATION;
+--------------------------------+
| @@GLOBAL.TRANSACTION_ISOLATION |
+--------------------------------+
| REPEATABLE-READ        | -- MySQL的默認(rèn)隔離級(jí)別,可以重復(fù)讀。
+--------------------------------+

-- MySQL 5.x
SELECT @@GLOBAL.TX_ISOLATION;
SELECT @@TX_ISOLATION;

修改隔離級(jí)別:

-- 設(shè)置系統(tǒng)隔離級(jí)別,LEVEL 后面表示要設(shè)置的隔離級(jí)別 (READ UNCOMMITTED)。
SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

-- 查詢(xún)系統(tǒng)隔離級(jí)別,發(fā)現(xiàn)已經(jīng)被修改。
SELECT @@GLOBAL.TRANSACTION_ISOLATION;
+--------------------------------+
| @@GLOBAL.TRANSACTION_ISOLATION |
+--------------------------------+
| READ-UNCOMMITTED        |
+--------------------------------+

臟讀

測(cè)試 READ UNCOMMITTED ( 讀取未提交 ) 的隔離性:

INSERT INTO user VALUES (3, '小明', 1000);
INSERT INTO user VALUES (4, '淘寶店', 1000);

SELECT * FROM user;
+----+-----------+-------+
| id | name   | money |
+----+-----------+-------+
| 1 | a     |  900 |
| 2 | b     | 1100 |
| 3 | 小明   | 1000 |
| 4 | 淘寶店  | 1000 |
+----+-----------+-------+

-- 開(kāi)啟一個(gè)事務(wù)操作數(shù)據(jù)
-- 假設(shè)小明在淘寶店買(mǎi)了一雙800塊錢(qián)的鞋子:
START TRANSACTION;
UPDATE user SET money = money - 800 WHERE name = '小明';
UPDATE user SET money = money + 800 WHERE name = '淘寶店';

-- 然后淘寶店在另一方查詢(xún)結(jié)果,發(fā)現(xiàn)錢(qián)已到賬。
SELECT * FROM user;
+----+-----------+-------+
| id | name   | money |
+----+-----------+-------+
| 1 | a     |  900 |
| 2 | b     | 1100 |
| 3 | 小明   |  200 |
| 4 | 淘寶店  | 1800 |
+----+-----------+-------+

由于小明的轉(zhuǎn)賬是在新開(kāi)啟的事務(wù)上進(jìn)行操作的,而該操作的結(jié)果是可以被其他事務(wù)(另一方的淘寶店)看見(jiàn)的,因此淘寶店的查詢(xún)結(jié)果是正確的,淘寶店確認(rèn)到賬。但就在這時(shí),如果小明在它所處的事務(wù)上又執(zhí)行了 ROLLBACK 命令,會(huì)發(fā)生什么?

-- 小明所處的事務(wù)
ROLLBACK;

-- 此時(shí)無(wú)論對(duì)方是誰(shuí),如果再去查詢(xún)結(jié)果就會(huì)發(fā)現(xiàn):
SELECT * FROM user;
+----+-----------+-------+
| id | name   | money |
+----+-----------+-------+
| 1 | a     |  900 |
| 2 | b     | 1100 |
| 3 | 小明   | 1000 |
| 4 | 淘寶店  | 1000 |
+----+-----------+-------+

這就是所謂的臟讀,一個(gè)事務(wù)讀取到另外一個(gè)事務(wù)還未提交的數(shù)據(jù)。這在實(shí)際開(kāi)發(fā)中是不允許出現(xiàn)的。

讀取已提交

把隔離級(jí)別設(shè)置為 READ COMMITTED

SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
SELECT @@GLOBAL.TRANSACTION_ISOLATION;
+--------------------------------+
| @@GLOBAL.TRANSACTION_ISOLATION |
+--------------------------------+
| READ-COMMITTED         |
+--------------------------------+

這樣,再有新的事務(wù)連接進(jìn)來(lái)時(shí),它們就只能查詢(xún)到已經(jīng)提交過(guò)的事務(wù)數(shù)據(jù)了。但是對(duì)于當(dāng)前事務(wù)來(lái)說(shuō),它們看到的還是未提交的數(shù)據(jù),例如:

-- 正在操作數(shù)據(jù)事務(wù)(當(dāng)前事務(wù))
START TRANSACTION;
UPDATE user SET money = money - 800 WHERE name = '小明';
UPDATE user SET money = money + 800 WHERE name = '淘寶店';

-- 雖然隔離級(jí)別被設(shè)置為了 READ COMMITTED,但在當(dāng)前事務(wù)中,
-- 它看到的仍然是數(shù)據(jù)表中臨時(shí)改變數(shù)據(jù),而不是真正提交過(guò)的數(shù)據(jù)。
SELECT * FROM user;
+----+-----------+-------+
| id | name   | money |
+----+-----------+-------+
| 1 | a     |  900 |
| 2 | b     | 1100 |
| 3 | 小明   |  200 |
| 4 | 淘寶店  | 1800 |
+----+-----------+-------+


-- 假設(shè)此時(shí)在遠(yuǎn)程開(kāi)啟了一個(gè)新事務(wù),連接到數(shù)據(jù)庫(kù)。
$ mysql -u root -p12345612

-- 此時(shí)遠(yuǎn)程連接查詢(xún)到的數(shù)據(jù)只能是已經(jīng)提交過(guò)的
SELECT * FROM user;
+----+-----------+-------+
| id | name   | money |
+----+-----------+-------+
| 1 | a     |  900 |
| 2 | b     | 1100 |
| 3 | 小明   | 1000 |
| 4 | 淘寶店  | 1000 |
+----+-----------+-------+

但是這樣還有問(wèn)題,那就是假設(shè)一個(gè)事務(wù)在操作數(shù)據(jù)時(shí),其他事務(wù)干擾了這個(gè)事務(wù)的數(shù)據(jù)。例如:

-- 小張?jiān)诓樵?xún)數(shù)據(jù)的時(shí)候發(fā)現(xiàn):
SELECT * FROM user;
+----+-----------+-------+
| id | name   | money |
+----+-----------+-------+
| 1 | a     |  900 |
| 2 | b     | 1100 |
| 3 | 小明   |  200 |
| 4 | 淘寶店  | 1800 |
+----+-----------+-------+

-- 在小張求表的 money 平均值之前,小王做了一個(gè)操作:
START TRANSACTION;
INSERT INTO user VALUES (5, 'c', 100);
COMMIT;

-- 此時(shí)表的真實(shí)數(shù)據(jù)是:
SELECT * FROM user;
+----+-----------+-------+
| id | name   | money |
+----+-----------+-------+
| 1 | a     |  900 |
| 2 | b     | 1100 |
| 3 | 小明   | 1000 |
| 4 | 淘寶店  | 1000 |
| 5 | c     |  100 |
+----+-----------+-------+

-- 這時(shí)小張?jiān)偾笃骄档臅r(shí)候,就會(huì)出現(xiàn)計(jì)算不相符合的情況:
SELECT AVG(money) FROM user;
+------------+
| AVG(money) |
+------------+
| 820.0000 |
+------------+

雖然 READ COMMITTED 讓我們只能讀取到其他事務(wù)已經(jīng)提交的數(shù)據(jù),但還是會(huì)出現(xiàn)問(wèn)題,就是在讀取同一個(gè)表的數(shù)據(jù)時(shí),可能會(huì)發(fā)生前后不一致的情況。這被稱(chēng)為不可重復(fù)讀現(xiàn)象 ( READ COMMITTED )

幻讀

將隔離級(jí)別設(shè)置為 REPEATABLE READ ( 可被重復(fù)讀取 ) :

SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT @@GLOBAL.TRANSACTION_ISOLATION;
+--------------------------------+
| @@GLOBAL.TRANSACTION_ISOLATION |
+--------------------------------+
| REPEATABLE-READ        |
+--------------------------------+

測(cè)試 REPEATABLE READ ,假設(shè)在兩個(gè)不同的連接上分別執(zhí)行 START TRANSACTION :

-- 小張 - 成都
START TRANSACTION;
INSERT INTO user VALUES (6, 'd', 1000);

-- 小王 - 北京
START TRANSACTION;

-- 小張 - 成都
COMMIT;

當(dāng)前事務(wù)開(kāi)啟后,沒(méi)提交之前,查詢(xún)不到,提交后可以被查詢(xún)到。但是,在提交之前其他事務(wù)被開(kāi)啟了,那么在這條事務(wù)線(xiàn)上,就不會(huì)查詢(xún)到當(dāng)前有操作事務(wù)的連接。相當(dāng)于開(kāi)辟出一條單獨(dú)的線(xiàn)程。

無(wú)論小張是否執(zhí)行過(guò) COMMIT ,在小王這邊,都不會(huì)查詢(xún)到小張的事務(wù)記錄,而是只會(huì)查詢(xún)到自己所處事務(wù)的記錄:

SELECT * FROM user;
+----+-----------+-------+
| id | name   | money |
+----+-----------+-------+
| 1 | a     |  900 |
| 2 | b     | 1100 |
| 3 | 小明   | 1000 |
| 4 | 淘寶店  | 1000 |
| 5 | c     |  100 |
+----+-----------+-------+

這是因?yàn)樾⊥踉诖酥伴_(kāi)啟了一個(gè)新的事務(wù) ( START TRANSACTION ) ,那么在他的這條新事務(wù)的線(xiàn)上,跟其他事務(wù)是沒(méi)有聯(lián)系的,也就是說(shuō),此時(shí)如果其他事務(wù)正在操作數(shù)據(jù),它是不知道的。

然而事實(shí)是,在真實(shí)的數(shù)據(jù)表中,小張已經(jīng)插入了一條數(shù)據(jù)。但是小王此時(shí)并不知道,也插入了同一條數(shù)據(jù),會(huì)發(fā)生什么呢?

INSERT INTO user VALUES (6, 'd', 1000);
-- ERROR 1062 (23000): Duplicate entry '6' for key 'PRIMARY'

報(bào)錯(cuò)了,操作被告知已存在主鍵為 6 的字段。這種現(xiàn)象也被稱(chēng)為幻讀,一個(gè)事務(wù)提交的數(shù)據(jù),不能被其他事務(wù)讀取到

串行化

顧名思義,就是所有事務(wù)的寫(xiě)入操作全都是串行化的。什么意思?把隔離級(jí)別修改成 SERIALIZABLE :

SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT @@GLOBAL.TRANSACTION_ISOLATION;
+--------------------------------+
| @@GLOBAL.TRANSACTION_ISOLATION |
+--------------------------------+
| SERIALIZABLE          |
+--------------------------------+

還是拿小張和小王來(lái)舉例:

-- 小張 - 成都
START TRANSACTION;

-- 小王 - 北京
START TRANSACTION;

-- 開(kāi)啟事務(wù)之前先查詢(xún)表,準(zhǔn)備操作數(shù)據(jù)。
SELECT * FROM user;
+----+-----------+-------+
| id | name   | money |
+----+-----------+-------+
| 1 | a     |  900 |
| 2 | b     | 1100 |
| 3 | 小明   | 1000 |
| 4 | 淘寶店  | 1000 |
| 5 | c     |  100 |
| 6 | d     | 1000 |
+----+-----------+-------+

-- 發(fā)現(xiàn)沒(méi)有 7 號(hào)王小花,于是插入一條數(shù)據(jù):
INSERT INTO user VALUES (7, '王小花', 1000);

此時(shí)會(huì)發(fā)生什么呢?由于現(xiàn)在的隔離級(jí)別是 SERIALIZABLE ( 串行化 ) ,串行化的意思就是:假設(shè)把所有的事務(wù)都放在一個(gè)串行的隊(duì)列中,那么所有的事務(wù)都會(huì)按照固定順序執(zhí)行,執(zhí)行完一個(gè)事務(wù)后再繼續(xù)執(zhí)行下一個(gè)事務(wù)的寫(xiě)入操作 ( 這意味著隊(duì)列中同時(shí)只能執(zhí)行一個(gè)事務(wù)的寫(xiě)入操作 ) 。

根據(jù)這個(gè)解釋?zhuān)⊥踉诓迦霐?shù)據(jù)時(shí),會(huì)出現(xiàn)等待狀態(tài),直到小張執(zhí)行 COMMIT 結(jié)束它所處的事務(wù),或者出現(xiàn)等待超時(shí)。

更多關(guān)于MySQL相關(guān)內(nèi)容感興趣的讀者可查看本站專(zhuān)題:《MySQL查詢(xún)技巧大全》、《MySQL常用函數(shù)大匯總》、《MySQL日志操作技巧大全》、《MySQL事務(wù)操作技巧匯總》、《MySQL存儲(chǔ)過(guò)程技巧大全》及《MySQL數(shù)據(jù)庫(kù)鎖相關(guān)技巧匯總

希望本文所述對(duì)大家MySQL數(shù)據(jù)庫(kù)計(jì)有所幫助。

相關(guān)文章

  • getdata table表格數(shù)據(jù)join mysql方法

    getdata table表格數(shù)據(jù)join mysql方法

    今天小編就為大家分享一篇關(guān)于getdata table表格數(shù)據(jù)join mysql方法,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-02-02
  • 深入了解mysql的4種常用、重要的數(shù)據(jù)類(lèi)型

    深入了解mysql的4種常用、重要的數(shù)據(jù)類(lèi)型

    對(duì)于在開(kāi)發(fā)大型電子商務(wù)網(wǎng)站時(shí),如果碰到有限的硬件和系統(tǒng)環(huán)境情況下,合理的數(shù)據(jù)庫(kù)表結(jié)構(gòu)的設(shè)計(jì)是必不可少的
    2014-05-05
  • MySQL派生表聯(lián)表查詢(xún)實(shí)戰(zhàn)過(guò)程

    MySQL派生表聯(lián)表查詢(xún)實(shí)戰(zhàn)過(guò)程

    派生表是查詢(xún)結(jié)果組成的虛擬表,派生表是在外部查詢(xún)的FROM子句中定義的,不需要手動(dòng)創(chuàng)建,下面這篇文章主要給大家介紹了關(guān)于MySQL派生表聯(lián)表查詢(xún)的相關(guān)資料,需要的朋友可以參考下
    2022-03-03
  • MySQL order by與group by查詢(xún)優(yōu)化實(shí)現(xiàn)詳解

    MySQL order by與group by查詢(xún)優(yōu)化實(shí)現(xiàn)詳解

    order by 子句盡量使用index方式排序(即using index),避免使用filesort方式排序(即using filesort)。Index方式效率高,它指MySQL掃描索引本身完成排序,filesort則效率低
    2022-11-11
  • 用Jena將本體文件存入MySQL數(shù)據(jù)庫(kù)的實(shí)現(xiàn)方法

    用Jena將本體文件存入MySQL數(shù)據(jù)庫(kù)的實(shí)現(xiàn)方法

    以下的文章主要介紹的是使用Jena,將本體文件存入MySQL數(shù)據(jù)庫(kù)的實(shí)際操作步驟
    2010-06-06
  • 快速增加MYSQL數(shù)據(jù)庫(kù)連接數(shù)負(fù)載能力的方法分享

    快速增加MYSQL數(shù)據(jù)庫(kù)連接數(shù)負(fù)載能力的方法分享

    mysql數(shù)據(jù)庫(kù)的負(fù)載能力除了和你機(jī)器硬件有關(guān),還有一個(gè)重要參數(shù)就是你系統(tǒng)的配置有關(guān),下面我來(lái)給大家介紹幾種提高M(jìn)YSQL數(shù)據(jù)庫(kù)連接數(shù)負(fù)載能力方法總結(jié),有需要的朋友可以參考一下
    2013-08-08
  • Mysql的DQL查詢(xún)操作全面分析講解

    Mysql的DQL查詢(xún)操作全面分析講解

    DQL(Data Query Language 數(shù)據(jù)查詢(xún)語(yǔ)言):用于查詢(xún)數(shù)據(jù)庫(kù)對(duì)象中所包含的數(shù)據(jù)。DQL語(yǔ)言主要的語(yǔ)句:SELECT語(yǔ)句。DQL語(yǔ)言是數(shù)據(jù)庫(kù)語(yǔ)言中最核心、最重要的語(yǔ)句,也是使用頻率最高的語(yǔ)句
    2022-12-12
  • 一文詳解MySQL?Join使用原理

    一文詳解MySQL?Join使用原理

    JOIN是一種非常常見(jiàn)的操作,用于將兩個(gè)或多個(gè)表中的數(shù)據(jù)合并到一個(gè)結(jié)果集中。MySQL支持多種JOIN類(lèi)型,本文通過(guò)代碼示例詳細(xì)介紹了Join的使用優(yōu)化,有需要的小伙伴可以參考閱讀
    2023-04-04
  • MySQL索引的5種應(yīng)用

    MySQL索引的5種應(yīng)用

    本文主要介紹了MySQL索引的5種應(yīng)用,包含聚集索引,唯一索引,非唯一(普通)索引,全文索引,組合索引等,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-03-03
  • mysql中如何去除小數(shù)點(diǎn)后面多余的0

    mysql中如何去除小數(shù)點(diǎn)后面多余的0

    這篇文章主要介紹了mysql 中去除小數(shù)點(diǎn)后面多余的0的方法 ,需要的朋友可以參考下
    2014-03-03

最新評(píng)論