記事ディレクトリ
1. データベースの分類とSQLの分類
-
关系型数据库
データベースは主にとの 2 つのカテゴリに分類されます非关系型数据库
。 -
リレーショナル データベース: MySQL、Oracle、DB2、SQL Server、Postgre SQLなど。
- リレーショナル データベースは通常、弊社によって作成されます
很多个二维数据表
。 - データテーブルは互いに関連付けられ、
一对一、一对多、多对多
対等な関係を形成します。 - その後、必要なデータを
SQL语句
使用できるようになります。多张表中查询
- リレーショナル データベースは通常、弊社によって作成されます
-
非リレーショナル データベース: MongoDB、Redis、Memcached、HBseなど。
- 非リレーショナル データベースの英語名は、実際には SQL だけでなく、
NoSQL
;とも呼ばれます。 - かなり言えます
非关系型数据库比较简单一些,存储数据也会更加自由
(複雑な json オブジェクトをデータベースに直接挿入することもできます)。
- 非リレーショナル データベースの英語名は、実際には SQL だけでなく、
-
NoSQL は対応する関係に基づいており
Key-Value
、クエリ プロセス中に渡す必要はありませんSQL解析
。
SQL文の分類
DDL
(データ定義言語): データ定義言語。- DDL ステートメントを使用して、データベースまたはテーブルに対して作成、削除、変更などの操作を実行できます。
DML
(データ操作言語): データ操作言語。- テーブル内のフィールドは、 DML ステートメントを通じて追加、削除、変更などを行うことができます。
DQL
(データ クエリ言語): データ クエリ言語。- DQL を介してデータベースからレコードをクエリできます (強調)
DCL
(データ制御言語): データ制御言語。- データベースおよびテーブルの権限に対して関連するアクセス制御操作を実行します。
2. SQL データ型
-
MySQL でサポートされるデータ型は次のとおりです
数字类型,日期和时间类型,字符串(字符和字节)类型,空间类型和 JSON数据类型
。 -
数値型
- 整数型: INTEGER、INT、SMALLINT、TINYINT、MEDIUMINT、BIGINT。
- 浮動小数点数型:FLOAT、DOUBLE(FLOATは4バイト、DOUBLEは8バイト)
- 正確な数値型: DECIMAL、NUMERIC (DECIMAL は NUMERIC の実装形式です)。
- 整数型が占めるバイト数
-
日付の種類:
YEAR
YYYY形式で値を表示します- 範囲は 1901 ~ 2155、および 0000。
DATE
Type は、日付部分を持つが時間部分を持たない値に使用されます。- DATE は、値を YYYY-MM-DD の形式で表示します。
- サポートされている範囲は「1000-01-01」から「9999-12-31」です。
DATETIME
日付と時刻の部分を含む値を入力します。- DATETIME は、値を「YYYY-MM-DD hh:mm:ss」の形式で表示します。
- サポートされている範囲は 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59 です。
TIMESTAMP
データ型は、日付と時刻の両方のコンポーネントを含む値に使用されます。- TIMESTAMP は値を「YYYY-MM-DD hh:mm:ss」の形式で表示します。
- ただし、その範囲は UTC 時間範囲です:「1970-01-01 00:00:01」から「2038-01-19 03:14:07」
- DATETIME または TIMESTAMP 値には、最大マイクロ秒 (6 桁) の精度の小数秒が含まれる場合があります。
- たとえば、DATETIME で表される範囲は、「1000-01-01 00:00:00.000000」から「9999-12-31 23:59:59.999999」になります。
-
文字列型
CHAR
テーブルの作成時に型は固定長になり、長さは 0 ~ 255 の任意の値にできます。- クエリを実行すると、次のスペースが削除されます。
VARCHAR
type の値は可变长度
文字列で、長さは 0 ~ 65535 の値として指定できます。- クエリの際、次のスペースは削除されません。
-
BLOBタイプ
- 大きなバイナリ型を格納するために使用されます。
-
テキストタイプ
- 大きな文字列型を格納するために使用されます。
3.DDL CRUD
3.1 ライブラリの操作
- すべてのデータベースを表示する
SHOW DATABASES
- データベースを使用する
USE 数据库
- 現在使用中のデータベースを表示する
SELECT DATABASE()
- データベースの作成
CREATE DATABASE IF NOT EXISTS 数据库名称
- データベースの削除
DROP DATABASE IF EXIT 数据库名称
- データベースの文字セットと照合順序を変更する
ALTER DATABASE bilibili CHARACTER SET = utf8 COLLATE = utf8_unicode_ci;
3.2 テーブルの制約
-
主キー制約
PRIMARY KEY
- テーブルでは、各レコードの一意性を区別するために、繰り返されず、空ではないフィールドが存在する必要があります。このフィールドは主キーです。
- 主キーはテーブル内の唯一のインデックスです。
NOT NULL
設定されていない場合はNOT NULL
、である必要があります。MySQL也会隐式的设置为NOT NULL
- 主キーは、
PRIMARY KEY(key_part, ...)
一般に結合主キーと呼ばれる複数列インデックスにすることもできます。
- テーブルでは、各レコードの一意性を区別するために、繰り返されず、空ではないフィールドが存在する必要があります。このフィールドは主キーです。
-
のみ:
UNIQUE
UNIQUE
制約を使用するフィールドはテーブル内で異なっている必要があり、重複してはなりませんUNIQUE
インデックスでは、NULL を含む列に複数の値 NULL を含めることができます。
-
空にすることはできません:
NOT NULL
- 一部のフィールドでは、ユーザーが値を挿入する必要があり、空にすることはできません。この場合、NOT NULL を使用して制約できます。
-
デフォルト値:
DEFAULT
- 一部のフィールドでは、値が設定されていない場合にデフォルト値を指定する必要があります。この場合、DEFAULT を使用して完了できます。
-
自動増加:
AUTO_INCREMENT
- ユーザーの など、一部のフィールドは値を設定せずにインクリメントできることを望みます
id
。この場合、 AUTO_INCREMENT を使用して完了できます。
- ユーザーの など、一部のフィールドは値を設定せずにインクリメントできることを望みます
-
外部キー制約
FOREIGN KEY(外键id) REFERENCES brand(被引用的id)
3.3 テーブル操作
- すべてのデータシートを表示
SHOW TABLES;
- テーブル構造を表示する
DESC user;
- データテーブルの作成
CREATE TABLE IF NOT EXISTS `user`(
name VARCHAR(10),
age INT,
height DOUBLE
);
- テーブルの削除
DROP TABLE IF EXISTS `user`
- テーブル名の変更
ALTER TABLE `user` RENAME TO `t_user`
- 作成したユーザーテーブルを最適化する
CREATE TABLE IF NOT EXISTS `user`(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20) UNIQUE NOT NULL,
sex INT DEFAULT(0),
tel VARCHAR(20)
);
- テーブルフィールドの操作
# 1.添加一个新的列
ALTER TABLE `user` ADD `publishTime` DATETIME;
# 2.删除一列数据
ALTER TABLE `user` DROP `updateTime`;
# 3.修改列的名称
ALTER TABLE `user` CHANGE `publishTime` `publishDate` DATE;
# 4.修改列的数据类型
ALTER TABLE `user` MODIFY `id` INT
4 DML CRUD
- 新しいテーブルを作成し、基本的な CURD を実装する
CREATE TABLE IF NOT EXISTS `t_products`(
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(20) UNIQUE NOT NULL,
description VARCHAR(200) DEFAULT '',
price DOUBLE DEFAULT 0,
publishTime DATETIME
);
-- 插入表数据
INSERT INTO `t_products` (title,description, price,publishTime) VALUES('huawei1000','描述华为',8000.0,'2012-11-9')
INSERT INTO `t_products` (title, description, price, publishTime) VALUES ('华为666', '华为666只要6666', 6666, '2166-06-06');
INSERT INTO `t_products` (title, description, price, publishTime) VALUES ('xiaomi666', 'xiaomi666只要6666', 6666, '2116-06-06');
-- 删除数据
-- 1. 删除表里面的所有数据
DELETE FROM `t_products`
-- 2. 根据条件来(id)删除语句
DELETE FROM `t_products` WHERE id=2
-- 修改数据表
-- 1. 修改表里面的所有数据
UPDATE `t_products` SET price=888;
-- 2.根据条件修改表里的数据
UPDATE `t_products` SET price=888 WHERE id=5;
-- 3.根据条件修改多个数据
UPDATE `t_products` SET price=999,description='xiaomi666只要999' WHERE id=5
-- 修改数据显示最新的更新时间,并把更新的时间也做一个记录
-- TIMESTAMP数据类型被用于同时包含日期和时间部分的值:
-- CURRENT_TIMESTAMP 记录当前的时间
ALTER TABLE `t_products` ADD `updataTime`
TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
5. DQL (データクエリ言語)
- SELECT は、1 つ以上のテーブルから選択された行 (レコード) を取得するために使用されます。
- クエリの形式は次のとおりです
5.1 単一テーブルクエリ
CREATE TABLE IF NOT EXISTS `products` (
id INT PRIMARY KEY AUTO_INCREMENT,
brand VARCHAR(20),
title VARCHAR(100) NOT NULL,
price DOUBLE NOT NULL,
score DECIMAL(2,1),
voteCnt INT,
url VARCHAR(100),
pid INT
);
-- 查询
-- 1.查询所有
SELECT * FROM `products`
-- 2. 查询指定的字段 price title brand
SELECT price, title,brand FROM `products`
-- 3 别名查询 as ,同时as关键字也是可以省略...
SELECT price as productsPrice, title productsTitle,brand FROM `products`
-- 条件查询-比较运算符
SELECT*FROM `products` WHERE price<1000
SELECT*FROM `products` WHERE price=939
SELECT*FROM `products` WHERE brand='小米'
-- 查询条件,逻辑运算符
-- 1. and 关键字与 && 一样
SELECT*FROM `products` WHERE brand='小米' AND price=939
-- 2. 逻辑或 or
SELECT*FROM `products` WHERE brand='华为' || price>=8000
-- 区间范围查询
-- 1. 关键字 BETWEEN AND
SELECT*FROM `products` WHERE price>=1000 && price<=2000
SELECT*FROM `products`WHERE price BETWEEN 1000 AND 2000
-- 枚举出多个结果,其中之一
SELECT*FROM `products` WHERE brand='小米' OR brand='华为'
SELECT*FROM `products` WHERE brand IN('小米','华为')
-- 模糊查询link 与特殊符号 % 与
-- 1. 查询title以v开头
SELECT * FROM `products` WHERE title LIKE 'v%';
-- 2.查询带M的title
SELECT * FROM `products` WHERE title LIKE '%M%';
-- 3.查询带M的title必须是第三个字符 (前面字符利用 _ )既下划线
SELECT * FROM `products` WHERE title LIKE '__M%';
-- 排序 ORDER BY
-- DESC:降序排列;
-- ASC:升序排列;
-- 1.价格小于1000 降序
SELECT * FROM `products` WHERE price < 1000 ORDER BY price ASC
-- 分页查询 用法[LIMIT {[offset,] row_count | row_count OFFSET offset}]
-- 1.limit 限制20条数据
SELECT * FROM `products` LIMIT 20
-- 2. OFFSET 偏移数据 (重第41条数据开始查询,查询20条)
SELECT * FROM `products` LIMIT 20 OFFSET 40
-- 另外一种写法:offset, row_count
SELECT * FROM `products` LIMIT 40, 20
5.2 集計クエリとグループクエリ
- グループ クエリでは、
Group By
クエリ結果にいくつかの制約が追加されている場合、次を使用できますHAVING
。
-- 1. 计算华为手机的平均价格
SELECT AVG(price) FROM `products` WHERE brand='华为'
-- 2.所有手机的平均分数
SELECT AVG(score) FROM `products`
-- 3.手机中最低和最高分数
SELECT MAX(score) FROM `products`;
SELECT MIN(score) FROM `products`;
-- 4.计算总投票人数
SELECT SUM(voteCnt) FROM `products`;
-- 5.计算 华为手机的个数
SELECT COUNT(*) FROM `products` WHERE brand = '华为'
-- 6. 分组 GROUP BY
-- 6.1 对品牌进行分组
SELECT brand FROM `products` GROUP BY brand
-- 6.2 分组后查看最低和最高的手机价格
-- ROUND 保留的小数ROUND(AVG(price),2)
SELECT brand,MAX(price),MIN(price) FROM `products` GROUP BY brand
-- 6.3 分组查询后进行价格最大值的约束 HAVING
SELECT brand,MAX(price) AS priceMAX,MIN(price) AS priceMin FROM `products` GROUP BY brand HAVING priceMAX > 4000
5.3 複数テーブルのクエリと外部キーの制約
- 外部キーが存在する場合のデータ解析の更新および削除
RESTRICT
(制約): 親テーブル (つまり、外部キーのソーステーブル) 内の対応するレコードを削除する場合、まずレコードに対応する外部キーがあるかどうかを確認し、ある場合は削除を許可しません。NO ACTION
: RESTRICT と一致します。つまり、スレーブ データが存在する場合、マスター データの削除は許可されません。CASCADE
: レコードが更新または削除されると、そのレコードに外部キー レコードが関連付けられているかどうかがチェックされます。- 更新: 対応するレコードが更新されます。
- 削除:関連付けられたレコードも一緒に削除されます。
SET NULL
: レコードが更新または削除されると、そのレコードに外部キー レコードが関連付けられているかどうかがチェックされ、関連付けられている場合は、対応する値が NULL に設定されます。
-- 多张表的查询
CREATE TABLE IF NOT EXISTS `t_song`(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20) NOT NULL,
duration INT DEFAULT 0,
singer VARCHAR(10)
-- 外键约束 这里的意思是singer_id 是外键约束 约束需要引入brand这个表里面的id
-- singer_id INT,
-- FOREIGN KEY(singer_id) REFERENCES brand(id)
);
INSERT INTO `t_song` (name,duration,singer) VALUES('爸爸妈妈',100,'李荣浩')
INSERT INTO `t_song` (name,duration,singer) VALUES('戒烟',120,'李荣浩')
INSERT INTO `t_song` (name,duration,singer) VALUES('从前的那个少年',100,'李荣浩')
-- 2.创建歌手表
CREATE TABLE IF NOT EXISTS `t_singer`(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(10),
intro VARCHAR(200)
)
-- 插入数据
INSERT INTO `t_singer` (name, intro) VALUES ('五月天', '五月天,全亚洲代表性摇滚乐团。演出足迹踏遍美国,澳洲以及全亚洲地区.')
INSERT INTO `t_singer` (name, intro) VALUES ('李荣浩', '李荣浩,全亚洲代表歌曲制作。')
-- 3.修改歌曲表
ALTER TABLE `t_song` DROP `singer`;
ALTER TABLE `t_song` ADD `singer_id` INT;
多表查询
-- 4.为了品牌单独创建一张表并插入数据
CREATE TABLE IF NOT EXISTS `brands`(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(10) UNIQUE NOT NULL,
website VARCHAR(100),
worldRank INT
);
INSERT INTO `brands` (name, website, worldRank) VALUES ('华为', 'www.huawei.com', 1);
INSERT INTO `brands` (name, website, worldRank) VALUES ('小米', 'www.mi.com', 10);
INSERT INTO `brands` (name, website, worldRank) VALUES ('苹果', 'www.apple.com', 5);
INSERT INTO `brands` (name, website, worldRank) VALUES ('oppo', 'www.oppo.com', 15);
INSERT INTO `brands` (name, website, worldRank) VALUES ('京东', 'www.jd.com', 3);
INSERT INTO `brands` (name, website, worldRank) VALUES ('Google', 'www.google.com', 8);
-- 4.1外键约束
-- 为products表添加brand_id
ALTER TABLE `products` ADD `brand_id` INT
-- 为外键添加约束 并引用表brand中的id字段 REFERENCES brand(id)=>引用brands中的id
ALTER TABLE `products` ADD FOREIGN KEY (brand_id) REFERENCES brands(id);
-- 4.2 将products中的brand_id关联到brand中的id的值
UPDATE `products` SET `brand_id` = 1 WHERE `brand` = '华为';
UPDATE `products` SET `brand_id` = 4 WHERE `brand` = 'OPPO';
UPDATE `products` SET `brand_id` = 3 WHERE `brand` = '苹果';
UPDATE `products` SET `brand_id` = 2 WHERE `brand` = '小米';
-- 5. 外键约束的情况下修改
UPDATE `brands` SET id=100 WHERE id=1
-- 1451 - Cannot delete or update a parent row: a foreign key constraint fails (`music_db`.`products`, CONSTRAINT `products_ibfk_1` FOREIGN KEY (`brand_id`) REFERENCES `brands` (`id`)) 报错误
-- 6. 查看表中的外键
SHOW CREATE TABLE `products`
-- 7. 删除外键
ALTER TABLE `products` DROP FOREIGN KEY products_ibfk_1;
-- 8 添加外键,当外键删除或者更新时 引用应该删除或者更新
ALTER TABLE `products` ADD FOREIGN KEY (brand_id) REFERENCES brands(id)
ON UPDATE CASCADE
ON DELETE CASCADE;
UPDATE `brands` SET id=100 WHERE id=1
5.4 複数テーブル間の接続クエリ
- データをクエリする場合、データは複数のテーブルに存在するため、複数のテーブルのクエリを組み合わせる必要があります。
- 例えば:
SELECT * FROM `products`, `brand`
- このとき、2 つのテーブルのすべてのデータがクエリされ、合計
648
のデータが取得されます。 - これにより、最初のテーブルの各データと 2 番目のテーブルの各データが結合されます。
- この結果を と呼び
笛卡尔乘积
、 とも呼び直积
、次のように表されますX*Y
。 - ただし、上記のクエリ結果のほとんどは無意味であり、必要なものではないため、
连接查询
5.4.1 左リンククエリ
- 左側のデータをすべて取得したい場合 (主に左側のテーブル)
- このとき、左側のテーブルに右側のテーブルの id に対応する brand_id 値があるかどうかに関係なく、左側のデータがクエリされることを意味します。
- 全文は ですが
LEFT [OUTER] JOIN
、OUTER可以省略
-- 3.左链接 LEFT [OUTER] JOIN "表" ON 连接条件
-- 这个时候就表示无论左边的表是否有对应的brand_id的值对应右边表的id,左边的数据都会被查询出来;
SELECT * FROM `products` LEFT JOIN `brands` ON products.brand_id=brands.id
-- 3.1 查询不为null有交集的数据
SELECT * FROM `products` LEFT JOIN `brands` ON products.brand_id = brands.id WHERE brands.id IS NOT NULL;
5.4.2 右結合クエリ
- 右側のすべてのデータ (主に右側のテーブル) を取得したい場合:
- このとき、左側のテーブルの brand_id が右側のテーブルの id に対応するかどうかに関係なく、右側のデータがクエリされることを意味します。
- 完全な記述方法は です
RIGHT [OUTER] JOIN
が、OUTER は省略できます。
SELECT * FROM `products` RIGHT JOIN `brands` ON products.brand_id=brands.id
5.4.3 内部結合
- 上部の内部結合は、左側のテーブルと右側のテーブルに対応するデータの関連付けがあることを意味します。
CROSS JOIN
どちらの方法でも記述できますJOIN
。
SELECT * FROM `products` JOIN `brands` ON `products`.brand_id = `brands`.id
- 内部接続と書かれた箇所
SELECT * FROM `products`, `brand` WHERE `products`.brand_id = `brand`.id
- 上記の SQL ステートメントの比較
- 内部結合とは、2 つのテーブルが接続されている場合、後続のクエリの結果を決定するためにデータ間の関係が制約されることを意味します。
- where 条件とは、まずデカルト積を計算し、デカルト積のデータに基づいて where 条件を選択することを意味します。
5.4.4 完全接続
- SQL 仕様では完全結合が使用されています
FULL JOIN
が、MySQL では完全結合がサポートされていないため、これをUNION
実現するには以下を使用する必要があります。
(SELECT * FROM `products` LEFT JOIN `brands` ON `products`.brand_id = `brands`.id)
UNION
(SELECT * FROM `products` RIGHT JOIN `brands` ON `products`.brand_id = `brands`.id)
(SELECT * FROM `products` LEFT JOIN `brands` ON products.brand_id = brands.id WHERE brands.id IS NULL)
UNION
(SELECT * FROM `products` RIGHT JOIN `brands` ON products.brand_id = brands.id WHERE products.id IS NULL)
- 結合クエリの概要
-- 在查询到产品的同时,显示对应的品牌相关的信息,因为数据是存放在两张表中,所以这个时候就需要进行多表查询
-- //1. 这种默认做法会发生这个表的数据与另一个表的数据会相乘 得到 M*N的数据
SELECT * FROM `products`, `brands`;
-- 2.过滤查询
SELECT * FROM `products`, `brands` WHERE products.brand_id=brands.id;
-- 3.左链接 LEFT [OUTER] JOIN "表" ON 连接条件
-- 这个时候就表示无论左边的表是否有对应的brand_id的值对应右边表的id,左边的数据都会被查询出来;
SELECT * FROM `products` LEFT JOIN `brands` ON products.brand_id=brands.id
-- 3.1 查询不为null有交集的数据
SELECT * FROM `products` LEFT JOIN `brands` ON products.brand_id = brands.id WHERE brands.id IS NOT NULL;
-- 4. 右连接 RIGHT [OUTER] JOIN "表" ON 连接条件
-- 这个时候就表示无论左边的表中的brand_id是否有和右边表中的id对应,右边的数据都会被查询出来
SELECT * FROM `products` RIGHT JOIN `brands` ON products.brand_id=brands.id
-- 5. 内连接 CROSS JOIN或者 JOIN;
-- 5.1内连接效果和下面where查询效果一样的,但是做法确是不一样的
-- 5.1.1SQL语句一:内连接,代表的是在两张表连接时就会约束数据之间的关系,来决定之后查询的结果;
-- 5.1.2SQL语句二:where条件,代表的是先计算出笛卡尔乘积,在笛卡尔乘积的数据基础之上进行where条件的帅选
SELECT * FROM `products` JOIN `brands` ON `products`.brand_id = `brands`.id
SELECT * FROM `products`, `brands` WHERE `products`.brand_id = `brands`.id;
-- 6. 全连接
-- 6.1 SQL规范中全连接是使用FULL JOIN,但是MySQL中并没有对它的支持,我们需要使用 UNION 来实现
(SELECT * FROM `products` LEFT JOIN `brands` ON `products`.brand_id = `brands`.id)
UNION
(SELECT * FROM `products` RIGHT JOIN `brands` ON `products`.brand_id = `brands`.id)
(SELECT * FROM `products` LEFT JOIN `brands` ON products.brand_id = brands.id WHERE brands.id IS NULL)
UNION
(SELECT * FROM `products` RIGHT JOIN `brands` ON products.brand_id = brands.id WHERE products.id IS NULL)
5.5 多対多のテーブルクエリ
-- 1.多对多关系
-- 1.1. 创建学生表
CREATE TABLE IF NOT EXISTS `students`(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20) NOT NULL,
age INT
);
INSERT INTO `students` (name, age) VALUES('why', 18);
INSERT INTO `students` (name, age) VALUES('tom', 22);
INSERT INTO `students` (name, age) VALUES('lilei', 25);
INSERT INTO `students` (name, age) VALUES('lucy', 16);
INSERT INTO `students` (name, age) VALUES('lily', 20);
-- 1.2. 创建课程表
CREATE TABLE IF NOT EXISTS `courses`(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20) NOT NULL,
price DOUBLE NOT NULL
);
INSERT INTO `courses` (name, price) VALUES ('英语', 100);
INSERT INTO `courses` (name, price) VALUES ('语文', 666);
INSERT INTO `courses` (name, price) VALUES ('数学', 888);
INSERT INTO `courses` (name, price) VALUES ('历史', 80);
INSERT INTO `courses` (name, price) VALUES ('物理', 100);
-- 1.3. 学生选择的课程关系表
CREATE TABLE IF NOT EXISTS `students_select_courses`(
id INT PRIMARY KEY AUTO_INCREMENT,
student_id INT NOT NULL,
course_id INT NOT NULL,
-- 外键约束
FOREIGN KEY (student_id) REFERENCES students(id) ON UPDATE CASCADE ON DELETE CASCADE,
FOREIGN KEY (course_id) REFERENCES courses(id) ON UPDATE CASCADE ON DELETE CASCADE
);
-- 2 选课情况
-- 2-1 why 选修了 英文和数学
INSERT INTO `students_select_courses` (student_id, course_id) VALUES (1, 1);
INSERT INTO `students_select_courses` (student_id, course_id) VALUES (1, 3);
-- 2-2 lilei选修了 语文和数学和历史
INSERT INTO `students_select_courses` (student_id, course_id) VALUES (3, 2);
INSERT INTO `students_select_courses` (student_id, course_id) VALUES (3, 3);
INSERT INTO `students_select_courses` (student_id, course_id) VALUES (3, 4);
-- 3查询数据
-- 3.1 所有学生的选课情况(内连接) students_select_courses(内连接属性)
SELECT * FROM `students`
JOIN `students_select_courses` ON students.id= students_select_courses.student_id
JOIN `courses` ON students_select_courses.course_id=courses.id
-- 3.2 别名查询名称
SELECT
stu.name stuName , cou.name couName
FROM `students` stu
JOIN `students_select_courses` ON stu.id= students_select_courses.student_id
JOIN `courses` cou ON students_select_courses.course_id=cou.id
-- 3.3左链接
SELECT
stu.name stuName , cou.name couName
FROM `students` stu
LEFT JOIN `students_select_courses` ON stu.id= students_select_courses.student_id
LEFT JOIN `courses` cou ON students_select_courses.course_id=cou.id
-- 3.4 单个学生选择课程情况 (左连接可以保证,在学生没有选择课的情况也可以显示)
SELECT
stu.name stuName , cou.name couName
FROM `students` stu
LEFT JOIN `students_select_courses` ON stu.id= students_select_courses.student_id
LEFT JOIN `courses` cou ON students_select_courses.course_id=cou.id WHERE stu.id=1
-- 3.5 查询哪些学生没有选择课程
SELECT
stu.name stuName , cou.name couName
FROM `students` stu
LEFT JOIN `students_select_courses` ON stu.id= students_select_courses.student_id
LEFT JOIN `courses` cou ON students_select_courses.course_id=cou.id WHERE cou.id is NULL
-- 3.6查询哪些课程没有被学生选择
SELECT
stu.name stuName , cou.name couName
FROM `students` stu
RIGHT JOIN `students_select_courses` ON stu.id= students_select_courses.student_id
RIGHT JOIN `courses` cou ON students_select_courses.course_id=cou.id WHERE cou.id is NULL
6 クエリオブジェクト配列
- 要件: 複数テーブルのクエリを実行する場合、テーブル 1 のデータはテーブル 2 のデータのサブセットとして扱われます。
- 要件 2: 複数のテーブルをクエリする場合、ブランド情報テーブルは別のオブジェクトに配置され、製品テーブルに表示されます。
- 要件 3: 複数のテーブルをクエリする場合、学習コースの選択情報は配列オブジェクトに配置されます。
JSON_OBJECT
転送オブジェクトJSON_ARRAYAGG和JSON_OBJECT
多対多から配列へ
-- 1. 单表查询
SELECT * FROM `products` WHERE price>5000
-- 2. 多表查询
SELECT * FROM `products` LEFT JOIN `brands` ON products.brand_id=brands.id
WHERE price>5000
-- 3. 多表查询:品牌信息放到一个单独的对象中
-- 格式 JSON_OBJECT([key, val[, key, val] ...])
SELECT
products.id as pid,products.title as title,products.price as price,
JSON_OBJECT('id',brands.id,'name',brands.name,'website',brands.website) as brand
FROM `products` LEFT JOIN `brands` ON products.brand_id=brands.id
WHERE price>5000
-- 多对多查询
SELECT * FROM `students` as stu
LEFT JOIN `students_select_courses` as ssc ON ssc.student_id=stu.id
LEFT JOIN `courses` as cu ON ssc.course_id =cu.id WHERE cu.id IS NOT NULL
-- 多对多查询分组合并
-- JSON_ARRAYAGG 转为数组对象
SELECT
stu.id as id, stu.name as name, stu.age as age,
JSON_ARRAYAGG(JSON_OBJECT('id',cs.id,'name',cs.name,'price',cs.price)) as course
FROM `students` as stu
LEFT JOIN `students_select_courses` as ssc ON ssc.student_id=stu.id
LEFT JOIN `courses` as cs ON ssc.course_id =cs.id WHERE cs.id IS NOT NULL
GROUP BY stu.id