SQL基础

本文介绍了SQL的基本语法,包括DDL(数据定义语言)如创建、查询和删除数据库及表,DML(数据操纵语言)如添加、修改和删除数据,DQL(数据查询语言)如查询操作,DCL(数据控制语言)涉及用户管理和权限控制。还讨论了函数、约束、事务处理以及多表查询的相关概念和操作实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一:SQL通用语法

1:SQL 语句可以单行或多行书写,以分号结尾。
2:可使用空格和缩进来增强语句的可读性。
3:MySQL 数据库的 SQL 语句不区分大小写,关键字建议使用大写。
4: 注释
* 单行注释: – 注释内容 或 # 注释内容(mysql 特有)
* 多行注释: /* 注释 */

二:SQL分类

在这里插入图片描述

三:DDL

1:数据库操作

A:创建数据库:
create database 【if not exists】 数据库名 【default charset 字符集】【collate 排序规则】;
B:查询数据库:
a:查询所有数据库:
show databases;
b:查询当前数据库:
select database();
C:使用数据库
use 数据库名称;
D:删除数据库
drop database 【if exists】数据库名称;
在这里插入图片描述

2:表操作

A:查询
a:查看当前数据库所有表
show tables;
b:查询表结构
desc 表名;
c:查询指定表的建表语句
show create table 表名;
B:创建
create table 表名(
字段1 字段1类型【comment 字段1注释】,
字段2 字段2类型【comment 字段2注释】,
字段3 字段3类型【comment 字段3注释】,
------
字段n 字段n类型【comment 字段n注释】
)【comment 表注释】;
在这里插入图片描述
C:修改
添加字段
alter table 表名 ADD 字段名 类型(长度) 【comment 注释】【约束】;
修改数据类型
alter table 表名 modify 字段名 新数据类型(长度);
修改字段名和字段类型
alter table 表名 change 旧字段名 新字段名 类型(长度) 【comment 注释】【约束];
修改表名
alter table 表名 rename to 新表名;
删除字段
alter table 表名 drop 字段名;
D:修改
删除表
drop table 【if exists】表名;
删除指定表。并重新创建该表(用得较少)
truncate table 表名;
在这里插入图片描述
在这里插入图片描述

3:数据类型

mysql中数据类型较多,主要分为三类:数值类型,字符串类型,日期时间类型。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

例如设计一张表,要求如下:
1:编号(纯数字)
2:员工工号(字符串类型,长度不超过10位)
3:员工姓名(字符串类型,长度不超过10位)
4:性别(男/女,存储一个汉字)
5:年龄(正常人年龄,不可能存储负数)
6:身份证号(二代身份证号均为18位,身份证中有x这样的字符)
7:入职时间(取值年月日即可)
create table emp(
	id int comment "编号",
	workid varchar(10) comment "工号",
	name varchar(10) comment "姓名",
	gender char(1) comment "性别",
	age tinyint unsigned comment "年龄",
	idcard char(18) comment "身份证号码",
	entrydate date comment "入职时间"
	) comment "员工表";

四:DML

(为了便于自己操作,可以直接使用相关的数据库管理工具,在此我是用的是DBeaver)

1:添加数据

A:给指定字段添加数据
insert into 表名(字段1,字段2,…)values (值1,值2,…);
B:给全部字段添加数据
insert into 表名 values (值1,值2,…);
C:批量添加数据
insert into 表名(字段1,字段2,…)values (值1,值2,…),(值1,值2,…),(值1,值2,…);
insert into 表名 values (值1,值2,…),(值1,值2,…);

注意:
	1:插入数据时,指定的字段顺序需要与值的顺序是一一对应的。
	2:字符串和日期型数据应该包含在引号中。
	3:插入的数据大小应该在字段的规定范围内。

2:修改数据

update 表名 set 字段名1=值1,字段名2=值2,…[where 条件];

 注意:如果不加条件,则表示更新整张对对应字段的值

3:删除数据

delete from 表名 [where 条件]

注意:
1:delete语句不能删除某一个字段的值(可以使用update)
2:delete语句的条件可以有,也可以没有,如果没有,则会删除整张表的所有数据。
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五:DQL

在这里插入图片描述

1:查询

A:查询多个字段
select 字段1,字段2,字段3… from 表名;
select * from 表名;(查询返回所有字段)
B:设置别名
select 字段1 【as 别名1】,字段2 【as 别名2】… from 表名;
C:去除重复记录
select distinct 字段列表 from 表名;
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
D:条件查询
select 字段列表 from 表名 where 条件列表
条件:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
补充:
聚合函数:将一列数据作为一个整体,进行纵向计算。
常见聚合函数:

在这里插入图片描述
注:所有的null值不参与聚合函数运算。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
E:分组查询
select 字段列表 from 表名 【where 条件】 group by 分组字段名 【having 分组后过滤条件】

注:
执行顺序:
where>聚合函数>having
分组之后,查询的字段一般为聚合函数或者分组字段,查询其他字段无意义(随机的)。
where与having的区别
where 是在分组前进行过滤,不满足where条件的不参与分组,having是在分组后对结果进行过滤,where不能对聚合函数进行判断,而having可以。

在这里插入图片描述
F:排序查询
select 字段列表 from 表名 order by 字段1 排序方式1,字段1,排序方式2;
排序方式:
默认升序(asc),降序(desc)
注:
如果是多字段排序,当第一个字段相同时,才会进行第二个字段排序
select
G:分页查询
select 字段列表 from 表名 limit 起始索引,查询记录数;
注:若起始索引从0开始可以省略,起始索引=(查询页码-1)*每页显示记录数,起始索引最小为0。
分页查询是数据库的方言,不同的数据库有不同的实现,mysql中是limit。
在这里插入图片描述
综合条件查询
在这里插入图片描述
在这里插入图片描述
DQL的执行顺序和编写顺序
在这里插入图片描述

六:DCL

1:管理用户

主要用于管理数据库用户,控制数据库的访问权限。(此节不做过多介绍)
A:查询用户
use mysql;
select * from user;
B:创建用户
create user "用户名"@"主机名" identified by "密码";  
C:修改用户密码
alter user "用户名"@"主机名" identified with mysql_native_password by "新密码";
D:删除用户
drop user "用户名"@"主机名";

注:
主机名可以使用%通配

2:权限控制

常见权限如下:
在这里插入图片描述
A:查询权限
show grants for “用户名”@“主机名”;
B:授予权限
grant 权限列表 on 数据库名.表名 to “用户名”@“主机名”;
C:撤销权限
revoke 权限列表 on 数据库名.表名 from “用户名”@“主机名”;

注:
1:多个权限之间使用逗号分隔
2:授权时,数据库名和表名可以使用*进行通配,代表所有。

三:函数

1:字符串函数

常见字符串函数:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如对下表的工号统一修改为5位数,不足5位的在前面补0;
在这里插入图片描述
在这里插入图片描述

2:数值函数

常见数值函数
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3:日期函数

常见日期函数:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4:流程函数

可以在SQL中实现条件筛选,从而提高语句的效率。
**常见流程函数**

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如下所示,如果地址为北京、上海、广州时返回“一线城市”,否则返回二线城市
在这里插入图片描述
在这里插入图片描述

四:约束

概念:

约束是作用在表中字段上的规则,用于限制存储在表中的数据,保证数据库中数据的正确、有效性和完整性。

分类:
在这里插入图片描述

在这里插入图片描述

1:外键约束

用来让两张表之间的数据建立连接,从而保证数据的一致性和完整性
A:添加外键:

create table 表名(
	字段名 数据类型,
	...
	[constraint] [外键名称]  foreign key  (外键字段名)references 主表(主表列名)
	);

或者:

alter table 表名 add constraint 外键名称 foreign key (外键字段名) references 主表(主表列名);

B:删除外键:

alter table 表名 drop foreign key 外键名称;

在这里插入图片描述
以此执行上述命令:
在这里插入图片描述
在这里插入图片描述

五:多表查询

1:多表关系

A:一对多
在多的一方建立外键,指向一的一方的主键
B:多对多
建立第三张中间表,中间表至少包含两个外键,分别关联两方主键
C:一对一
在任意一方加入外键,关联另外一方的主键,并且设置外键为唯一的(unique)。

2:多表查询

A:连接查询
a:内连接:相当于查询A、B交集部分数据
隐式内连接:
select 字段列表 from 表1,表2 where 条件 …;
显式内连接(只是表达形式上的差别,和隐式内连接效果差不多,可能有速度上的其别):
select 字段列表 from 表1 [inner] join 表2 on 连接条件 …;
b:外连接:
左外连接:查询左表所有数据,以及两张表交集部分数据。
select 字段列表 from 表1 left [outer] join 表2 on 条件…;
右外连接:查询右表所有数据,以及两张表交集部分数据
select 字段列表 from 表1 right [outer] join 表2 on 条件…;
自连接:当前表与自生的连接查询,自连接必须使用表别名
例如:查询emp表中员工及其所属领导的名字:
emp表:managerid中的数字为该员工所属领导的id在这里插入图片描述
查询语句及结果如下:
注意:因为是同一个表,所以一定要另外别名。
在这里插入图片描述
如要该员工没有对应领导(自己是领导)也需查询出来,可用下面语句:
在这里插入图片描述

B:联合查询-union,union all

对于union查询,就是将多次查询的结果合并起来,形成一个新的查询结果集

	select 字段列表 from 表A ...
	union [all]
	select 字段列表 from 表B ...;

注:对于联合查询的多张表的列数必须保持一致,字段类型也需要保持一致。union all会将全部数据直接合并在一起,union会对合并之后的数据去重。

emp:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注:union取得是并集而不是交集。
在这里插入图片描述
在这里插入图片描述
C:子查询
sql语句中嵌套select语句,称为嵌套语句,又称子查询
select * from t1 where column1 =(select column1 from t2);
子查询外部的语句可以是insert/update/delete/select的任何一个。

	(1):根据子查询位置,分为:where之后、from之后、select之后。

	(2):根据子查询结果不同,可分为:
		A:标量子查询(结果为单个值)
			常用操作符:=,<>,>,>=,<,<=

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

		B:列子查询(结果为一列)
				常用的操作符:
										 in:在指定的集合范围内,多选一
										 not in:不在指定的集合范围内
										 any:子查询返回列表中,有任意一个满足即可
										 some:与any等同,使用some的地方也可以使用any
										 all:子查询返回列表的所有值都必须满足

###查询销售部和财务部员工的信息
在这里插入图片描述
#####查询比研发部其中任意一人工资高的员工信息
在这里插入图片描述

		C:行子查询(结果为一行)
		常用操作符:=,<>,in,not in
insert into temp(id,name,age,job,salary,entrydate,dept_id) values(8,"吴十",29,"算法",19000,"2013-07-26",4);

在这里插入图片描述
在这里插入图片描述

		D:表子查询(结果为多行多列)
			常用操作符号:in,常出现在from之后
insert into temp(id,name,age,job,salary,entrydate,dept_id) values(9,"罗十一",30,"算法",19000,"2013-01-19",1),(10,"燕十二",27,"开发",22000,"2015-02-15",1);

在这里插入图片描述
select * from temp where (job,salary) in (select job,salary from temp where name=“王五” or name=“孙九”);
在这里插入图片描述
select t.,d. from (select * from temp where entrydate>“2015-03-02”) t left join dept d on t.dept_id=d.id;
在这里插入图片描述

练习如下

create table salgrade(
	grade int,
	losal int,
	hisal int
) comment "薪资等级表";

insert into salgrade values(1,0,3000);
insert into salgrade values(2,3001,5000);
insert into salgrade values(3,5001,8000);
insert into salgrade values(4,8001,10000);
insert into salgrade values(5,10001,15000);
insert into salgrade values(6,15001,20000);
insert into salgrade values(7,20001,25000);
insert into salgrade values(8,25001,30000);

薪资等级表
在这里插入图片描述

insert into temp(id,name,age,job,salary,entrydate,dept_id) values(11,"宋十三",28,null,27000,"2015-04-14",null);

员工信息表
在这里插入图片描述
部门表
在这里插入图片描述
(1)查询员工的姓名、年龄、职位、部门信息(隐式内连接)

select t.name,t.age,t.job,d.name from temp t,dept d where t.dept_id = d.id;

在这里插入图片描述
(2)查询年龄小于30岁的员工姓名、年龄、职位、部门信息(显示内连接)

-- select t.name,t.age,t.job,d.name from temp t inner join dept d where (t.dept_id = d.id) and (t.age<30);
select t.name,t.age,t.job,d.name from temp t inner join dept d on t.dept_id = d.id where (t.age<30);

在这里插入图片描述
(3) 查询拥有员工的部门ID、部门名称

select distinct t.dept_id ,d.name  from temp t , dept d where t.dept_id = d.id;
##distinct在此为去重##

在这里插入图片描述
(4)#查询所有年龄大于28的员工,及其所属的部门名称;如果没有分配部门。也需要展示出来

select t.name ,d.name  from temp t left join dept d  on t.dept_id = d.id where t.age > 27; 

在这里插入图片描述
(5)#查询所有员工的工资等级

select t.name,t.salary,s.grade,s.losal,s.hisal  from temp t,salgrade s where s.losal<=t.salary and t.salary <= s.hisal;

在这里插入图片描述

(6)查询"研发部"所有员工的信息及工资等级
注: N张表至少需要N-1个连接条件,多个连接条件之间用and相连

select t.*,s.grade ,s.losal ,s.hisal  from temp t, dept d ,salgrade s where (t.dept_id =d.id) and (t.salary between s.losal and s.hisal) and d.name ="研发部";

在这里插入图片描述
(7)查询"研发部"员工的平均工资

select avg(t.salary) from temp t,dept d where t.dept_id =d.id and d.name ="研发部";

在这里插入图片描述
(8)查询薪资比"王五"高的员工

select * from temp  where salary >(select salary from temp  where name="王五"); 

在这里插入图片描述
(9)查询比平均薪资高的员工信息

select * from temp where salary > (select avg(salary) from temp);

在这里插入图片描述
(10)查询低于本部门平均工资的员工信息

select t1.*,(select avg(t2.salary) from temp t2 where t2.dept_id =t1.dept_id) "平均薪资" from temp t1 where t1.salary < (select avg(t2.salary) from temp t2 where t2.dept_id =t1.dept_id);

在这里插入图片描述
(11)查询所有的部门信息,并统计部门的员工人数

select d.id,d.name,(select count(*) from temp t where t.dept_id=d.id) "人数" from dept d; 

在这里插入图片描述

六:事务

1:事务的简介:

事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求。即这些操作要么同时成功,要么同时失败。

2:事务的操作

如转账操作:
初始时,“张三”、"李四"各有2000元;执行张三给李四转账1000元。

create table account(
id int auto_increment primary key comment "主键ID",
name varchar(10) comment "姓名",
money int comment "余额"
) comment "账户表";
insert into account(id,name,money) values(null,"张三",2000),(null,"李四",2000);

在这里插入图片描述

(1)查询张三账户余额:

select * from account where name="张三";

(2)将张三账户余额-1000:

update account set money =money -1000 where name="张三";

(3)将李四账户的余额+1000:

update account set money =money + 1000 where name="李四";

正常执行结果如下:
在这里插入图片描述
但若在执行过程中,发生异常,则会导致转账失败。

#数据初始化
update account set money=2000 where name="张三" or name = "李四";
update account set money =money -1000 where name="张三";
#发生异常
程序异常---
update account set money =money + 1000 where name="李四";

结果如下,转账失败(张三的钱减少了,但李四的钱没有增加)。这在实际情况下是不允许发生的
在这里插入图片描述
在mysql中事务默认是自动提交的,要想避免上面这种情况出现,有下面两种方式:
A:改提交方式为手动提交

#查看提交方式,默认为1,自动提交,可将其设置为0变为手动提交。注意,手动设置的提交方式只对当前窗口有效
select @@autocommit;
#设置提交方式
select @@autocommit=0;
#提交事务
commit;
#回滚事务
rollback;

设置autocommit=0后,若不自动提交,则数据库中的数据不会变。

#数据初始化
update account set money=2000 where name="张三" or name = "李四";
#设置手动提交
set @@autocommit=0;
update account set money =money -1000 where name="张三";
update account set money =money + 1000 where name="李四";

在这里插入图片描述
需要手动提交commit

#数据初始化
update account set money=2000 where name="张三" or name = "李四";
#设置手动提交
set @@autocommit=0;
update account set money =money -1000 where name="张三";
update account set money =money + 1000 where name="李四";
commit;

在这里插入图片描述
依次执行下面语句:

-- 数据初始化
update account set money=2000 where name="张三" or name = "李四";
commit;
-- 设置手动提交
set @@autocommit=0;
update account set money =money -1000 where name="张三";
程序异常
update account set money =money + 1000 where name="李四";
#提交事务
-- commit;
#回滚事务
-- rollback;

执行完”张三“转账操作后,“程序异常”为非mysql而报错(转账失败),此时应回滚事务,而不是提交事务。若此时再单独执行commit,则会将当前”张三“的账户状态提交到数据库。则数据库情况如下:
在这里插入图片描述
B:通过开启事务、提交事务的方式
(a)开启事务

	start transaction; 或 begin;

(b)提交事务

    commit;

(c)回滚事务

	rollback;

依次执行下面语句:开启事务之前的操作被自动提交到数据库,当执行到”程序异常“时报错,此时应回滚事务而非提交事务,否则数据库会跟新"张三"账户的当前状态导致其结果如下,这在实际的转账过程中是不允许出现的:

set @@autocommit=1;
update account set money=2000 where name="张三" or name = "李四";
#开启事务
start transaction;
select * from account where name="张三";
update account set money =money - 1000 where name="张三";
程序异常
update account set money =money + 1000 where name="李四";
#提交事务
-- commit;
#回滚事务
-- rollback;

在这里插入图片描述

3:事务的四大特性

A、原子性:事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
B、一致性:事务完成时,必须使所有的数据都保持一直状态。
C、隔离性:数据库提高的隔离机制,保证事务在不受外界并发操作影响的独立环境下运行。
D、持久性:事务一旦提交或者回滚,它对数据库中的数据的改变是永久的

4:并发事务问题

在这里插入图片描述
在这里插入图片描述
事务A对数据库进行查询和更新后还未提交(即事务A还未执行完),事务B中读取到事务A更新后的数据。
在这里插入图片描述
在事务A第二次查询数据库中数据的时候,事务B对数据库中的数据进行了跟新并提交,导致事务A第一次查询和第二次查询所得到的记录不一样。
在这里插入图片描述
事务A对数据库中id=1(主键,唯一)的数据进行查询,显示没有该数据,事务A对其进行插入操作前事务B先对其进行了插入操作并提交到数据库,导致事务A插入操作失败(应该是显示已存在该数据),但在随后事务A的查询中依然显示没该数据(已经解决不可重复读问题之后)。

5:事务隔离级别

用来解决并发事务所带来的问题
在这里插入图片描述
四种事务隔离级别(安全性)从上到下依次增高,但相应的性能依次降低。

#查看事务的隔离级别
select @@transaction_isolation;
##设置事务隔离级别(若session则仅针对当前客户端的当前会话窗口有效,若global则针对所有客户端的所有会话窗口有效)
set [session | global] transaction isolation  level [read uncommitted | read committed | repeatable read | serializable];

设置及查看当前事务隔离级别

set session transaction isolation level read uncommitted;
select @@transaction_isolation;

在这里插入图片描述
(1)“read uncommitted”隔离级别状态下,脏读问题的验证(用两个命令窗口模拟两个并发事务)
在这里插入图片描述
(2)“read committed”隔离级别状态下,解决脏读(事务B中未提交前,事务A中查询到表的状态一致)和不可重复读(事务B中更改提交后,事务A中表的状态发生变法)问题的验证
在这里插入图片描述
(3)“repeatable read”隔离级别状态下,解决“不可重复读”问题验证
在这里插入图片描述

(3)“repeatable read”隔离级别状态下,“幻读”问题验证
在这里插入图片描述
(4)“serializable”隔离级别(串行化,一个事务完毕后,另一个事务才能被执行)状态下,解决“幻读”问题。
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值