几个关键字
like
js
复制代码
1、
%:是一个通配符,代表零个、一个或多个字符
a. 查找,以特定字符串开头的值:SELECT * FROM 表名 WHERE 列名 LIKE '前缀%';
b. 查找,以特定字符串结尾的值:SELECT * FROM 表名 WHERE 列名 LIKE '%后缀';
c. 查找,包含特定字符串的值:SELECT * FROM 表名 WHERE 列名 LIKE '%子字符串%';
2、
_:是一个通配符,代表一个单一字符
a. 查找特定模式的值(例如,长度为 5 的字符串,其中第二个字符是 'a'),如下:
SELECT * FROM 表名 WHERE 列名 LIKE '_a___';
MAX
js
复制代码
使用MAX(),可以找到,指定列的最大值。
SELECT MAX(列名) FROM 表名;
MIN
js
复制代码
使用MIN(),可以找到,指定列的最小值。
SELECT MIN(列名) FROM 表名;
AVG
js
复制代码
使用AVG(),可以计算,指定列的平均值。
SELECT AVG(列名) FROM 表名;
SUM
js
复制代码
使用SUM(),可以计算,指定列的总和。
SELECT SUM(列名) FROM 表名;
主外键
js
复制代码
主键:
用来,唯一标识表中每一行数据的列,或列组合
主键的值,必须是唯一且非空的,用于确保表中的每一行都可以被唯一标识
主键,通常用于索引表中的数据,加快数据检索的速度
在SQL中,主键约束,可以通过'Primary Key'关键字定义
外键:
用来建立,表与表之间关系的一种约束,它定义了一个表中的列或者列组合,
这些列的值,必须是另一个表的主键或唯一键的值。
外键用于维护表与表之间的关联关系,确保数据的一致性和完整性
在SQL中,外键约束可以通过'FOREIGN KEY'关键字来定义,通常与另一个表中的主键或者唯一键关联起来
在数据库设计中,主键和外键的正确使用,可以帮助建立表与表之间的关联关系,确保数据的完整性和一致性
举例
js
复制代码
首先,有一个'students'表,包含以下列:
student_id:主键,用于唯一标识每个学生,
student_name:学生的姓名,
age:学生的年龄,
此时,'student_id列'被定义为主键,确保每个学生都有一个唯一的学生ID。
然后,有一个'courses'表,其中包含以下列:
course_id:主键,用于唯一标识每门课程,
course_name:课程的名称,
student_id:外键,关联到'students表'的student_id列。
此时,'student_id'列被定义为外键,确保每门课程关联到'students表'中存在的学生。
解释一下:
'students表'中的'student_id列'被定义为主键,
并且,'courses表'中的'student_id'列被定义为外键,
那么,这两个表中的'student_id'值是相关联的,
换句话说,
'courses表'中的'student_id值',必须是'students表中存在的student_id值',以确保每门课程都关联到一个已存在的学生。
举例
js
复制代码
CREATE TABLE products (
product_id INT PRIMARY KEY, * 主键,用于唯一标识每个产品
product_name VARCHAR(100) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
stock_quantity INT NOT NULL,
category VARCHAR(50) NOT NULL,
supplier_id INT,
FOREIGN KEY (supplier_id) REFERENCES suppliers(supplier_id)
);
product_id列,被定义为主键,用于唯一标识每个产品;
product_name、price、stock_quantity、category列,分别表示产品的名称、价格、库存数量、类别信息;
supplier_id列,用于存储供应商的ID;但是,表定义中,并没有直接指定该列为外键;
但是,
在最后一行,通过 FOREIGN KEY (supplier_id) REFERENCES suppliers(supplier_id)这一语句,
将'supplier_id列'设置为外键,
并且,将其关联到suppliers表中的supplier_id列。
CREATE TABLE suppliers (
supplier_id INT PRIMARY KEY,
supplier_name VARCHAR(100) NOT NULL,
contact_name VARCHAR(100) NOT NULL,
contact_email VARCHAR(100),
phone_number VARCHAR(20),
address VARCHAR(255)
);
supplier_id列,被定义为主键,用于唯一标识每个供应商;
supplier_name、contact_name、contact_email、phone_number、address列,分别表示,供应商名称、联系人姓名、联系人邮箱、联系电话、地址;
通过,在'products表'中定义'supplier_id列'为外键,
并且,将其关联到'suppliers表'中的'supplier_id列',
确保了,'产品表(products)中'的supplier_id值,必须是,'供应商表(suppliers)中'已存在的supplier_id值,
从而建立了产品表和供应商表之间的关联关系;
创建一张表
sql
复制代码
CREATE TABLE `my_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`pwd` varchar(255) DEFAULT NULL,
`plone` varchar(11) NOT NULL,
`reg_time` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
插入
插入完整的行
sql
复制代码
当给`表的每一列`都提供一个值时,不需要在 INSERT INTO 语句中指定列名,
但是,必须为每一列提供一个值,
并且,这些值的顺序必须与表中的列顺序相对应
语法:INSERT INTO 表名 VALUES (值1, 值2, 值3, ...);
如:
INSERT INTO my_user VALUES (NULL, '张三', 'password123', '123456789012345678', NOW());
因为,'id列是自动增长的',
所以,使用 NULL 来让数据库自动为它分配一个值,
NOW()函数,用于获取当前的日期和时间,并自动填充到reg_time列。
插入指定的列
sql
复制代码
当`只为表中的某些列`提供值时,需要在 INSERT INTO 语句中明确的指定这些列名。
INSERT INTO 表名 (列1, 列2, 列3, ...) VALUES (值1, 值2, 值3, ...);
如:
INSERT INTO my_user (name, pwd, plone, reg_time)
VALUES ('李四', 'password456', '15866669995', '2023-01-01 10:00:00');
这里,只为 name、pwd、plone、reg_time 列提供了值,而'id列由数据库自动填充'。
插入多行
sql
复制代码
INSERT INTO 表名 (列1, 列2, 列3, ...) VALUES
(值1a, 值2a, 值3a, ...),
(值1b, 值2b, 值3b, ...),
...;
如:
INSERT INTO my_user (name, pwd, plone, reg_time) VALUES
('王五', 'pwd789', '15866669996', '2023-01-02 15:30:00'),
('赵六', 'pwd111', '15866669997', '2023-01-03 09:15:00');
注意点:
js
复制代码
1、
如果,某列有默认值,或允许NULL值,你可以省略该列的值,
但是,在插入多行数据时,每一行的列数和数据类型必须与指定的列匹配。
2、
对于自动增长的列(如 id),通常不需要在插入数据时提供值,数据库会自动为其分配一个唯一的值。
3、
使用 NOW()函数可以自动插入当前的日期和时间,
如果,需要更精细的控制,也可以使用 CURDATE()(仅日期)或 CURTIME()(仅时间)函数。
修改
语法
sql
复制代码
UPDATE 表名
SET 列1 = 值1, 列2 = 值2, ...
WHERE 条件;
WHERE:关键字,后面跟条件表达式,用于指定哪些记录应该被更新,
如果省略 WHERE 子句,将更新表中的所有记录,
这可是大bug
修改指定列的值
sql
复制代码
将用户名为"张三"的用户的密码修改为"newpassword123":
UPDATE my_user SET pwd = 'newpassword123' WHERE name = '张三';
修改多个列的值
sql
复制代码
将用户名为"张三"的用户的密码修改为"newpassword123",phone修改为"12345678910"
UPDATE my_user SET pwd = 'updatedpassword', plone = '12345678910' WHERE name = '张三';
根据条件修改
sql
复制代码
将所有在2022年注册的用户的状态更新为"old_user"
UPDATE my_user SET status = 'old_user' WHERE YEAR(reg_time) = 2022;
与limit字句配合
sql
复制代码
MySQL允许在 UPDATE 语句中,使用 LIMIT 子句来限制更新的记录数。
如:
UPDATE my_user SET pwd = 'new_password' WHERE name LIKE '张%' LIMIT 1;
这条语句,将只更新 name 列以"张"开头的第一条记录的pwd列的值。
注意
js
复制代码
1、
WHERE 子句是 UPDATE 语句中非常重要的部分,因为它决定了哪些记录会被更新,
如果,没有正确地指定 WHERE 子句,
或者,完全省略了它,
那么,所有的记录都会被更新,这是一个严重的bug。
2、始终确保 SET 子句中的列名和值,与数据库中的实际情况相匹配。
删除
语法
sql
复制代码
语法:
DELETE FROM 表名 WHERE 条件;
解释:
DELETE FROM:表示要从哪个表中删除记录
WHERE:这是一个可选的子句,用于指定哪些记录应该被删除,
如果省略 WHERE 子句,将删除表中的所有记录
举例:
删除"my_user"表中,名为"张三"的用户记录,
DELETE FROM my_user WHERE name = '张三';
删除所有记录但不删除表
sql
复制代码
语法:
TRUNCATE TABLE 表名;
举例:
TRUNCATE TABLE my_user;
这条语句,会删除"my_user表"中的所有记录,但表结构本身及其定义(如列、索引等)会保留下来。
查询
基本语法
sql
复制代码
语法:
SELECT 列1, 列2, ...
FROM 表名
WHERE 条件;
解释:
SELECT:表示要执行查询操作;
列1, 列2, ...:指定要从表中检索的列的名称;如果要选择所有列,可以使用 "*"通配符;
FROM:关键字,后面跟要查询数据的表的名称;
WHERE:关键字,后面跟条件表达式,用于过滤记录,WHERE 子句是可选的;
举例:
查询,所有用户的,姓名和电话号码:SELECT name, plone FROM my_user;
如果,只想查询名为"张三"的用户的信息:SELECT * FROM my_user WHERE name = '张三';
order by
sql
复制代码
ORDER BY:用于对查询结果进行排序。
LIMIT:用于限制返回的记录数。
查询,my_user表中,前10个用户的姓名,并按姓名升序排序
SELECT name
FROM my_user
ORDER BY name ASC
LIMIT 10;
GROUP BY having
sql
复制代码
GROUP BY:用于将结果集按一个或多个列进行分组。
HAVING:与 GROUP BY 一起使用,用于过滤分组后的结果。
解释:
GROUP BY 是 SQL 语言中的一个子句,
用于,将'查询结果'按照一个或多个列进行分组,
在每个分组内,你可以使用聚合函数(如 COUNT(), SUM(), AVG(), MAX(), MIN() 等)来计算每个组的统计信息。
having,用于,在分组之后过滤数据
举例:
返回staff表中,员工数量大于3的城市及其员工数量
SELECT city, count(*) as num
FROM staff
GROUP BY city
HAVING num > 3;
join-内连接
sql
复制代码
1、
内连接,会返回,两个表中满足连接条件的行。
2、
内连接,通过'在ON子句中指定连接条件',来将两个表中的行连接起来,
只有当连接条件满足时,内连接才会返回匹配的行,
如果某个表中的行,在另一个表中没有匹配的行,则这些行不会出现在内连接的结果中。
语法:
SELECT *
FROM TableA
INNER JOIN TableB
ON TableA.column_name = TableB.column_name; -- column_name:列名
举例:
Students表:
| student_id | student_name | course_id |
|------------|--------------|-----------|
| 1 | Alice | 101 |
| 2 | Bob | 102 |
| 3 | Charlie | 103 |
Courses表:
| course_id | course_name |
|-----------|-------------|
| 101 | Math |
| 102 | Science |
| 104 | History |
通过内连接,查询学生的姓名和所选课程的名称:
select Students.student_name, Courses.course_name
from Students
inner join Courses
on Students.course_id = Courses.course_id
执行结果为:
| student_name | course_name |
|--------------|-------------|
| Alice | Math |
| Bob | Science |
join-左连接
sql
复制代码
1、
左连接(Left Join),
它会返回,左表中的所有行,以及右表中满足连接条件的行,
如果右表中没有匹配的行,那么结果集中将会包含 NULL 值。
2、
左连接,常用于,需要保留左表中所有行的情况,即使,右表中没有匹配的行也要显示左表中的数据
语法:
SELECT *
FROM TableA
LEFT JOIN TableB
ON TableA.column_name = TableB.column_name;
'LEFT JOIN'表示进行左连接操作,
'ON TableA.column_name = TableB.column_name'表示连接条件,
左连接,将返回左表TableA中的所有行,以及右表TableB中满足连接条件的行,
如果,右表中没有匹配的行,对应的列将会显示 NULL 值。
举例:
Employees表:
| employee_id | employee_name | department_id |
|-------------|---------------|--------------|
| 1 | Alice | 101 |
| 2 | Bob | 102 |
| 3 | Charlie | 103 |
| 4 | David | 102 |
Departments表:
| department_id | department_name |
|---------------|-----------------|
| 101 | HR |
| 102 | Marketing |
| 104 | Finance |
通过,左连接,查询员工的姓名和所属部门的名称:
select Employees.employee_name, Departments.department_name
from Employees
left join Departments
on Employees.department_id = Departments.department_id
执行结果为:
| employee_name | department_name |
|---------------|-----------------|
| Alice | HR |
| Bob | Marketing |
| Charlie | NULL |
| David | Marketing |
解释:
Alice属于HR部门,Bob和David都属于Marketing部门,
而,Charlie的部门在Departments表中找不到对应的记录,因此在左连接的结果中显示为NULL,
左连接操作保留了Employees表中的所有员工信息,并将其与Departments表中匹配的部门信息进行连接。
join-右连接
sql
复制代码
1、
右连接(Right Join),
它会返回右表中的所有行,以及左表中满足连接条件的行,
如果,左表中没有匹配的行,那么结果集中将会包含 NULL 值。
2、
右连接与左连接相反,
右连接,用于需要保留右表中所有数据的情况,即使,左表中没有匹配的数据也要显示右表中的数据
语法:
SELECT *
FROM TableA
RIGHT JOIN TableB
ON TableA.column_name = TableB.column_name;
'RIGHT JOIN'表示进行右连接操作,
'ON TableA.column_name = TableB.column_name'表示连接条件。
举例:
Students表:
| student_id | student_name | course_id |
|------------|--------------|-----------|
| 1 | Alice | 101 |
| 2 | Bob | 102 |
| 3 | Charlie | 103 |
| 4 | David | NULL |
Courses表:
| course_id | course_name |
|-----------|-------------|
| 101 | Math |
| 102 | English |
| 104 | History |
通过,右连接,查询学生的姓名和所选课程的名称:
select Students.student_name, Courses.course_name
from Students
right join Courses
on Students.course_id = Courses.course_id
执行结果为:
| student_name | course_name |
|--------------|-------------|
| Alice | Math |
| Bob | English |
| Charlie | NULL |
| NULL | History |
解释:
Alice选择了Math课程,Bob选择了English课程,
Charlie的课程在Courses表中找不到对应的记录,
而,David在Students表中的course_id为NULL,因此,在右连接的结果中显示为NULL,
右连接操作保留了Courses表中的所有课程信息,并将其与Students表中匹配的学生信息进行连接
join-全连接
sql
复制代码
1、
全连接(Full Join),
它会返回,左表和右表中的所有行,
同时,将满足连接条件的行,进行连接,
如果,某个表中没有匹配的行,对应的列将会显示 NULL 值。
2、
全连接,会返回左表和右表中的所有数据,无论是否有匹配的行,
如果,左表或右表中的某些行,在另一张表中没有匹配的行,那么对应的列将会显示 NULL 值。
语法:
SELECT *
FROM TableA
FULL JOIN TableB
ON TableA.column_name = TableB.column_name;
'FULL JOIN'表示进行全连接操作,
'ON TableA.column_name = TableB.column_name'表示连接条件,
全连接,将返回左表TableA和右表TableB中的所有行,并将满足连接条件的行进行连接,
如果,某个表中没有匹配的行,对应的列将会显示 NULL 值。
举例:
Employees表:
| employee_id | employee_name | department_id |
|-------------|---------------|---------------|
| 1 | Alice | 101 |
| 2 | Bob | 102 |
| 3 | Charlie | 103 |
| 4 | David | NULL |
Departments表:
| department_id | department_name |
|---------------|-----------------|
| 101 | HR |
| 102 | Finance |
| 104 | Marketing |
通过全连接,查询员工的姓名和所属部门的名称,即使有些员工的部门在Departments表中找不到对应的记录,或者有些部门没有员工。
select Employees.employee_name, Departments.department_name
from Employees
full join Departments
on Employees.department_id = Departments.department_id
执行结果:
| employee_name | department_name |
|---------------|-----------------|
| Alice | HR |
| Bob | Finance |
| Charlie | NULL |
| David | NULL |
| NULL | Marketing |
解释:
Alice属于HR部门,Bob属于Finance部门,
Charlie和David的部门,在Departments表中找不到对应的记录,
而,Marketing部门没有员工,
全连接操作,保留了Employees表 和 Departments表中的所有数据,并将其进行连接。
子查询
sql
复制代码
1、
子查询是指,在'SQL查询语句中嵌套另一个查询',
内部查询的结果,作为外部查询的条件之一,
子查询可以用于过滤数据、进行计算、比较值等各种操作。
举例:
Employees表:
| employee_id | employee_name | department_id | salary |
|-------------|---------------|---------------|--------|
| 1 | Alice | 101 | 60000 |
| 2 | Bob | 102 | 70000 |
| 3 | Charlie | 101 | 55000 |
| 4 | David | 103 | 75000 |
Departments表:
| department_id | department_name |
|---------------|-----------------|
| 101 | Sales |
| 102 | Marketing |
| 103 | Finance |
查询每个部门的平均工资,并找出,工资高于部门平均工资的员工
select Employees.salary, Employees.employee_name, Departments.department_name
from Employees e
join Departments d
on e.department_id = d.department_id
where e.salary > (
select AVG(salary)
from Employees e2
where e2.department_id = e.department_id
)
| salary | employee_name | department_name |
|--------|---------------|------------- --|
| 60000 | Alice | Sales |
| 70000 | Bob | Marketing |
例子
sql
复制代码
学生表Students:
| student_id | student_name | age |
|------------|--------------|-----------|
| 1 | Alice | 20 |
| 2 | Bob | 21 |
| 3 | Charlie | 19 |
成绩表Scores:
| student_id | subject | score |
|------------|--------------|-----------|
| 1 | Math | 85 |
| 1 | Science | 90 |
| 2 | Math | 75 |
| 2 | Science | 80 |
| 3 | Math | 95 |
| 3 | Science | 88 |
找出每个学生的平均分,并列出高于平均分的学生及其成绩:
select Students.student_id, Students.student_name, Scores.subject, Scores.score
from Students stu
join Scores s
on stu.student_id = s.student_id
where Scores.score > (
select AVG(score)
from Scores
where student_id = s.student_id
)