When the data is stored in the database, due to unreasonable data design, there will be data duplication, update and insertion exceptions, etc., so the design of the tables in the database follows the design specifications: three paradigms
1. First Normal Form (1NF)
Each column of the database is required to be an indivisible atomic data item, that is, atomicity. The emphasis is on the atomicity of the column, that is, the field of each column in the database is a single attribute and cannot be further divided. And this single attribute must be composed of basic data types, such as integers, strings, etc.
Example: users table
uid |
username |
password |
tel |
address |
u001 |
tmm |
111111 |
15891xxxxxx |
xxx, Hantai District, Hanzhong City, Shaanxi Province |
The address field in the above table can be divided by province, city, and district, so it does not satisfy the first normal form.
Solution: Split a field into multiple fields
uid |
username |
password |
tel |
province |
city |
area |
address |
u001 |
tmm |
111111 |
15891xxxxxx |
Shaanxi Province |
Hanzhong |
Hantai District |
xxxx |
2. Second Normal Form (2NF)
Under the premise of satisfying the first normal form, the non-key attribute must completely depend on the candidate key, and each table only describes one thing. A table must have a primary key; non-primary key classes must be fully dependent on the primary key.
Example: users table
uid |
username |
password |
tel |
role |
u001 |
mmm1 |
111111 |
15891xxxxxx |
administrator |
The uid in the above table can be used as the primary key of the users table, username, password, and tel all depend on uid, but the role field does not depend on uid.
Solution: Split a table into multiple tables (put the management relationship on multiple parties, a role has multiple users, so the foreign key of the user is rid)
User table users
uid |
username |
password |
tel |
r_id |
u001 |
mmm1 |
111111 |
15891xxxxxx |
r1001 |
u002 |
tmm2 |
111111 |
15891xxxxxx |
r1002 |
role table roles
rid |
username |
r001 |
administrator |
r002 |
general user |
3. Third Normal Form (3NF)
Under the premise of the second normal form, any non-primary attribute does not depend on other non-primary attributes (on the basis of 2NF, eliminating transitive dependencies), non-primary key columns must directly depend on the primary key, and there cannot be transitive dependencies. That is to ensure that each column of data in the data table is directly related to the primary key, not indirectly.
Example: class selection table sc
scid |
takes off |
cname |
tname |
credit |
score |
001 |
mmm1 |
js |
a teacher |
4 |
90 |
002 |
tmm2 |
css |
teacher b |
3 |
95 |
Since sname, cname, tname, credit, and score do not depend on scid, the table needs to be split
class list sc
scid |
sid |
cid |
tname |
score |
001 |
s01 |
c001 |
t01 |
90 |
002 |
s02 |
c002 |
t02 |
95 |
学生表 students
sid |
sname |
s01 |
tmm1 |
s02 |
tmm2 |
课程表 class
cid |
cname |
credit |
c001 |
js |
4 |
c002 |
css |
3 |
老师表 teachers
tid |
tname |
t01 |
a老师 |
t02 |
b老师 |
多对多的解决办法: 创建一张新表:teacher_class
tcid |
cid (课程编号) |
tid (老师id) |
tc001 |
c001 |
t01 |
tc002 |
c002 |
t02 |
各表关系如图所示:
注意:在数据库使用可视化工具建表时, 有时不添加外键, 避免数据处理时, 别处占用无法进行处理
4.多表查询
-- 单表查询
-- 查询所有书籍的作者信息
SELECT * FROM `books_author`;
-- 查询所有书籍的标题
SELECT title FROM books;
-- 给表起别名, b为别名, 作用:使用别名.的方式查找字段时更方便,不易出错
SELECT b.`content` FROM books b;
-- 给列(字段)起别名*/`books`
SELECT b.`imgUrl` AS `iu` FROM books b;
-- 1. 每本书涨价10%,保留两位小数, 涨价完成后更新到数据库中 价格不为空时, is not null,不能使用<>不等于
UPDATE books SET price = ROUND(price*(1.1),2) WHERE price IS NOT NULL;
-- 2. 查询书所对应的评论
-- 多表查询
SELECT b.bookname,c.comcontent FROM books_comment c,books b WHERE b.bid = c._bid;
-- 使用左外连接,主表内容会完全显示,包括NULL的情况 默认左的内容显示的多
SELECT b.`bid`,b.bookname,c.comcontent FROM books b LEFT JOIN books_comment c ON b.`bid` = c.`_bid`;
-- 使用内连接, 当内容为NULL时, 不显示
SELECT b.`bid`,b.bookname,c.comcontent FROM books b INNER JOIN books_comment c ON b.`bid` = c.`_bid`;
-- 3. 统计评分大于等于4.5的书的评论数,并显示书名 分组聚合 统计评分大于等于4.5的书, 统计评论数
-- 多表查询
SELECT b.bookname,c.`comcontent`, COUNT(c.`comcontent`) AS comnums
FROM books_comment c, books b
WHERE c._bid = b.bid AND c.score >= 4.5
GROUP BY b.bookname ;
-- 子查询 显示书名
SELECT b.bookname FROM books b
WHERE b.`bid` IN (
SELECT c.`_bid` FROM books_comment c
WHERE c.`score` >= 4.5
GROUP BY c.`_bid` = b.`bid`
)
-- 4. limit 起始索引,查询条数
/* 显示第三页的数据,每页10条, 当前页curPage=3, 每页条数pageSize=10
select * from books limit (curPage-1)*pageSize,10 */
SELECT * FROM books LIMIT 10,10;
-- 显示书籍评论信息 (books)书id,书名 (books_author) 作者 (books_comment)评论发布时间,评论内容 (users)评论者
-- (1)显示评论者信息 (books_comment, users表)
SELECT c.`_bid`,c.`comcontent`,c.`comtime`,u.`nickname` FROM books_comment c, users u
WHERE c.`_uid` = u.`uid`;
-- (2)显示作者信息 (books,books_author,books_books_category表)
SELECT b.`bid`,b.`bookname`,a.`aname` FROM books b, books_author a, books_books_author ba
WHERE ba.`ba_bid`= b.`bid` AND ba.`ba_aid`= a.`aid`
-- (3)结果综合
SELECT *
FROM
(SELECT b.`bid`,b.`bookname`,a.`aname` FROM books b, books_author a, books_books_author ba WHERE ba.`ba_bid`= b.`bid` AND ba.`ba_aid`= a.`aid`) t1
LEFT JOIN
(SELECT c.`_bid`,c.`comcontent`,c.`comtime`,u.`nickname` FROM books_comment c, users u WHERE c.`_uid` = u.`uid` ) t2
ON t1.bid = t2._bid
-- GROUP_CONCAT([DISTINCT] 要连接的字段 [Order BY ASC/DESC 排序字段] [Separator '分隔符'])
-- CONCAT_WS('分隔符', 要合并的字段) 合并列
SELECT t1.bid,t1.bookname,t1.aname,t2.`comtime`,t2.`nickname`,
-- group_concat(concat_Ws(',',t1.bookname,t2.`comcontent`,t2.`comtime`,t2.`nickname`) separator ';')
GROUP_CONCAT(t2.`comcontent` SEPARATOR '=====')
FROM
(SELECT b.`bid`,b.`bookname`,a.`aname` FROM books b, books_author a, books_books_author ba WHERE ba.`ba_bid`= b.`bid` AND ba.`ba_aid`= a.`aid`) t1
LEFT JOIN
(SELECT c.`_bid`,c.`comcontent`,c.`comtime`,u.`nickname` FROM books_comment c, users u WHERE c.`_uid` = u.`uid` ) t2
ON t1.bid = t2._bid
GROUP BY t1.bid,t1.bookname,t1.aname;