数据库就是存储数据的一种仓库!
数据库存储数据--->
1)存储空间非常大,可以存储百万条,千万条甚至上亿条数据,用户可以对数据库中数据进行新增,查询,更新,删除等操作
2)数据独立性高
3)实现数据共享
4)减少数据的冗余度
5)通过数据库里面"事务"--->实现数据的一致性以及维护性!
数据库分为两大类:
alter database 库名 default(省略) character set 字符集格式;
desc 表名;
show create table 表名;
alter table 表名 character set 字符集格式;
alter table 表名 modify 字段名称 修改后字段类型;
alter table 表名 change 以前的字段名称 现在的字段名称 以前的字段类型;
alter table 表名 add 字段名称 字段类型;
alter table 表名 drop 字段名称 ;
alter table 表名 rename to 新表名;
也可以用 rename table 以前表名 to 新表名;
drop table if exists 表名;
drop table 表名;
int
int()
varchar(字符长度)
字符串类型
date:日期类型
仅仅表示日期
datetime:日期+时间
timestap:时间戳
当前插入数据或则修改/删除数据的即时时间 :2022-12-3 11:30:00
double:小数类型
double(3,2): 这个小数一共有3个数字,小数点后保留2位
例:double(4,2);---->12.56
double(3,2);---->2.56
double(5,2);---->132.56
clob:大字符类型
某个表中某个字段, 使用clob来存储大文本!
blob
大字节类型:存储大图片文件,大字节类型
insert into 表名 values(值1,值2,值3,值3…值n);
一次插入一条数据
insert into 表名 values(值1,值2,值3,值3…值n),(值1,值2,…值n),(…) ;
一次插入多条数据
insert into 表名(字段名称1,字段名称2.,等部分字段)values(值1,值2,值3…),(值1,值2,值3…),(…);
插入部分字段,没有插入的字段值就是null(空值)
update 表名 set 字段名称= 值 where 字段名称= 值;
一次修改一个
update 表名 set 字段名称1= 值1,字段名称2=值2,… where 字段名称= 值;
一次修改多个
注意事项:修改的时候如果不带where条件,属于批量修改(很少用)
delete from 表名 where 字段名称 = 值;
条件一般使用非业务字段删除
– delete from 表名 where 字段名称1 = 值1 and 字段名称2 = 值2 …;
多个条件删除
删除全表数据
delete from 表名;
是删除全表数据,表结构还在
truncate table 表名;
删除全表
查询全表
select * from 表名;
代表全部字段 (实际开发中禁用*)
select 全部字段名称 from表名;
带条件查询
select 全部字段名称 from 表名 where 条件语句;
where
比较运算符
<=,>=,<,>,!=(在mysql使用 <>)
< 小于
<= 小于等于
>= 大于等于
>大于
!=或<> 不等于
between……and…… 在……和……之间
in 在……中
like 模糊查询
is null 查询某一列为null的值
-- 需求:查询年龄是20或者年龄是18或者年龄是45的学生所有信息
-- where条件可以使用 or 或者java语言||,in(值1,值2.....)
SELECT
*
FROM
student2
WHERE age = 20
OR age = 18
OR age = 45 ;
-- 另一种写法
SELECT
*
FROM
student2
WHERE age = 20 || age = 18 || age = 45 ;
-- 另一种写法:in(值1,值2.....)
SELECT
*
FROM
student2
WHERE age IN (20, 18, 45) ;
-- 需求:查询年龄不是20岁的学生所有信息
SELECT
*
FROM
student2
WHERE age != 20 ;
-- 另一种写法
SELECT
*
FROM
student2
WHERE age <> 20 ;
-- 需求:查询学生中所有姓马的学生信息
SELECT
*
FROM
student2
WHERE
NAME LIKE '%马%'
-- 查询学生的姓名是三个字符的人的信息
SELECT
*
FROM
student2
WHERE NAME LIKE '___' ;
-- 需求:按照性别分组,查询数学成绩平均分,
-- 条件:学生数学成绩大于70的人参与分组,同时筛选出人数大于2的一组!
SELECT
sex '性别',
AVG(math) '数学平均分',
COUNT(id) total
FROM
student2
WHERE math > 70
GROUP BY sex
HAVING total > 2 ;
select 字段列表 from 表名 limit 起始行数,每页显示的条数;
-- 起始行数= (当前页码数-1)*每页显示的条数;
-- 每页显示2条,
-- 查询第一页的数据
SELECT * FROM student2 LIMIT 0,2 ;
-- 查询第二页的数据
SELECT * FROM student2 LIMIT 2,2 ;
-- 查询第三页的数据
SELECT * FROM student2 LIMIT 4,2 ;
-- 查询第四页的数据
SELECT * FROM student2 LIMIT 6,2 ;
-- 查询第五页的数据
SELECT * FROM student2 LIMIT 8,2 ;
-- select 字段列表 from 表名 limit 值;
SELECT * FROM student2 LIMIT 3 ;
--如果复合查询:有where条件,还有limit,where在limit前面
SELECT * FROM student2 WHERE id > 2 LIMIT 4;
-- 创建一张表
CREATE TABLE test1(
id INT, -- 编号
NAME VARCHAR(10), -- 姓名
age INT, -- 年龄
gender VARCHAR(3) DEFAULT '女' -- 姓名
) ;
INSERT INTO test1 VALUES(1,'张三',35,'男'),(2,'张思',30,'女') ;
-- 插入部分字段
INSERT INTO test1(id,NAME,age) VALUES(3,'张武',29) ;
没有插入字段的值默认值null,为了防止这种数据出现,可以在创建表的时候
加入默认约束default,当没有插入这个字段,默认约束起作用!
sql添加,默认约束
ALTER TABLE 表名 MODIFY 字段名称 数据类型 DEFAULT 数据 ;
ALTER TABLE test1 MODIFY gender VARCHAR(3) DEFAULT '女' ;
当前这个值不能为null,不能直接添加数据给一个null
将默认约束删除了
alter table 表名 modify 字段名称 数据类型;
ALTER TABLE test1 MODIFY NAME VARCHAR(10) ;
添加非空约束
ALTER TABLE 表名 MODIFY 字段名称 数据类型 NOT NULL ;
ALTER TABLE test1 MODIFY NAME VARCHAR(10) NOT NULL ;
INSERT INTO test1 VALUES(3,NULL) ;
当前这个值不能重复
限制id字段/有效身份信息(邮箱/手机号/身份证…)
CREATE TABLE test1(
id INT ,
NAME VARCHAR(10),
telephone VARCHAR(11) UNIQUE -- 唯一约束:存在唯一索引inedex
) ;
INSERT INTO test1 VALUES(1,'张思','13366668888'),(2,'王五','13322226666') ;
添加手机号码重复
INSERT INTO test1 VALUES(3,'文章','13366668888'); -- 手机号重复,防止这些字段重复(有效身份信息,可以在创建表的时候添加唯一约束)
Duplicate entry '13366668888' for key 'telephone' 这个字段有多个重复值出现
删除唯一约束----(删除唯一索引的名称)
alter table 表名 drop index 索引名(索引名如果没有起名字默认是列的名称);
ALTER TABLE test1 DROP INDEX telephone ;
INSERT INTO test1 VALUES(3,'文章','13366668888');
添加唯一约束
alter table 表名
add constraint(声明)
唯一约束的索引名称
unique(列名);
ALTER TABLE test1 ADD CONSTRAINT index_telephone UNIQUE(telephone) ;
-- uplicate entry '13366668888' for key 'index_telephone'
DROP TABLE test1;
非空且唯一
通过sql删除主键
alter table 表名 drop primary key ;
ALTER TABLE test1 DROP PRIMARY KEY ;
通过sql添加主键
alter table 表名 add primary key (列名称) ;
ALTER TABLE test1 ADD PRIMARY KEY(id) ;
每一张表的id
自增长主键的值一定插入之后产生的而不是修改!
CREATE TABLE test1(
id INT PRIMARY KEY AUTO_INCREMENT, -- 主键约束 + 自增长
NAME VARCHAR(10),
gender VARCHAR(3)
);
问题:
1)查询员工的所有信息---部门名称字段 冗余度大(重复度高)
2)一张表描述了两个事情(员工信息,又有部门信息!)
解决方案:将这张表拆分两张表
一张表员工信息
一张表描述部门信息
CREATE TABLE employee(
id INT PRIMARY KEY AUTO_INCREMENT, -- 编号
NAME VARCHAR(10), -- 姓名
gender VARCHAR(3), -- 性别
dept_id INT ,-- 部门编号
CONSTRAINT -- 声明
dept_emp_fk -- 外键名称
FOREIGN KEY(dept_id) -- 作用在指定外键字段上
REFERENCES -- 关联
dept(id) -- 主表的主键字段
);
外键作用的表—从表,另一张表:主表
创建表的时候添加外键
constraint (声明)
外键名--->起名字 主表名_从表名_fk
foriegn key (从表的字段名称)
references -- (关联)
主表名(主键字段的名称)
有了外键之后,直接修改或者删除主表数据,前提需要让从表的数据跟主表没有关联,这个时候才能修改和删除主表数据!
有外键约束,修改–先修改从表,然后在修改主表
sql删除外键约束
alter table 表名 drop foreign key 外键名;
ALTER TABLE employee DROP FOREIGN KEY dept_emp_fk ;
sql 添加外键约束
alter table 表名 add constraint 外键名称 foreign key (从表字段名称) references 主表的(主键字段) ;
级联删除/级联修改 on delete cascade /on update casade
当修改/删除主表的数据,从表数据随之改动
将上面这个语句放在外键的后面
添加外键的同时—添加级联修改和级联删除
ALTER TABLE employee
ADD CONSTRAINT dept_emp_fk
FOREIGN KEY (dept_id)
REFERENCES dept(id)
ON UPDATE CASCADE
ON DELETE CASCADE ;
-- 直接修改主表数据,
-- 将1号部门改成2号部门,这个时候1号部门的员工,它部门编号变成2
UPDATE dept SET id = 2 WHERE id =1 ;
-- 直接删除主表数据,从表随之变化
-- 将3号部门解散
DELETE FROM dept WHERE id = 3 ;
设计一个库,满足数据库的范式(就是数据库设计的一种规范要求)
人和身份证
一个人对应一个身份证
一个身份证从属于某个人的
用户和订单的关系
一个用户可以有多个订单,
某个订单从属于某个用户
员工和部门的关系
一个部门有多个员工
一个员工属于某个部门的
订单表和商品表
一个订单包含多个商品
一个商品被多个订单包含
学生表和选课表
一个学生可以选多个课程
一个课程被多个学生选择
创建数据表
-- 设计部门表
CREATE TABLE dept(
id INT PRIMARY KEY AUTO_INCREMENT ,-- 部门编号
NAME VARCHAR(10) -- 部门名称
) ;
-- 添加部门表数据
INSERT INTO dept(NAME) VALUES('开发部'),('市场部'),("销售部") ;
-- 设计员工表
CREATE TABLE employee(
id INT PRIMARY KEY AUTO_INCREMENT, -- 员工编号
NAME VARCHAR(10), -- 姓名
gender VARCHAR(3), -- 性别
salary DOUBLE, -- 工资
join_date DATE, -- 入职日期
dept_id INT , -- 部门编号
-- 设置外键
CONSTRAINT -- 声明
dept_emp_fk -- 外键名
FOREIGN KEY (dept_id) -- 指定外键名作用从表的指定字段上
REFERENCES -- 关联
dept(id)
);
-- 添加员工数据
INSERT INTO employee(NAME,gender,salary,join_date,dept_id) VALUES
('张三','男',12000.0,'2021-11-11',1),
('李四','男',8000.0,'2022-05-28',1),
('王五','女',7000.0,'2021-12-31',2),
('赵六','女',8000.0,'2021-10-30',3) ,
('宋七','男',3000.0,'2022-10-15',3),
('钱八','男',15000.0,'2022-9-30',1),
('孙九','女',6000.0,'2021-10-10',3);
针对多表查询
1)查询哪张表!
2)查询指定表的哪些字段!
3)他们表和表之间的关系!
SELECT
e.*,
d.*
FROM
employee e,
dept d ;
上面查询的结果不符合实际要求,7个员工,现在出现了21个
这个就是笛卡尔乘积,针对A表的记录 和B的记录数,两个表的记录相乘
出现笛卡尔乘积的原因:没有设置连接条件!
隐式内连接
内连接
左外连接(通用)
右外连接
子主题 1
SELECT
e.*,
d.`name` "部门名称"
FROM
employee e
LEFT OUTER JOIN dept d -- outer可以省略
ON e.`dept_id` = d.`id` ;
select 嵌套 select……
情况1:单行单列数据
情况2:多行多列
情况3:通过俩个表的关系查询出结果集,当做虚表在和其他之间关联查询
在一个业务中执行多个sql(多张表的sql),这多个sql句要么同时执行成功,
要么同时执行失败!
举例
转账操作 多个账户同时操作,一个减钱,一个加钱
提交订单
订单表和订单项表 同时添加数据
原子性,一致性,隔离性,持久性!
原子性:在使用事务管理的时候,执行多个sql增删改,要么同时执行成功,要么同时失败
一致性:高并发的时候,需要保证事务多次读写,保证数据一致性!
隔离性:事务和事务是独立的,相互不影响!
举例
购物车业务--->购物车表和购物车项表同时添加数据
订单业务---->订单表和订单项表同时添加数据
持久性: 事务一旦提交,对数据的影响是永久性,即使关机了,数据还是要更新的!
四个级别:从小到大,安全性—从低到高,效率性:从高到低!
SELECT @@tx_isolation; – – 查看隔离级别:5.7以及5.7以前
select trasaction_isolation; – – mysql8.0以后的查看事务的隔离级别
设置隔离级别
set global transaction isoloation level 级别的名称;
第一种级别read uncommitted:读未提交 会造成问题"脏读"
“脏读”:是事务管理最严重的问题:一个事务读取到另一个没有提交的事务!
第二种级别:read committed; 读已提交 有效防止脏读,出现了一个问题"不可重复读"
事务(当前本身这个事务提交)多次读取另一个提交事务的前后到的数据不一致!
mysql的默认级别 repeatable read
可重复读,有效脏读,不可重复读,出现幻读!(一般有更新操作影响了数据)
最高级别:serializable:串行话 (一个事务读取到另一个没提交事务,数据查不到的,这个必须提交,才能操作数据!)
-- 创建一个账户表
CREATE TABLE account(
id INT PRIMARY KEY AUTO_INCREMENT , -- 账户id
NAME VARCHAR(10), -- 账户名称
balance INT -- 余额
);
INSERT INTO account (NAME,balance) VALUES('zhangsan',1000),('lisi',1000);
-- zhangsan给lis转账500
-- 没有数据库事务管理转账操作
/*
update account set balance = balance - 500 where id = 1 ;
-- 转账出问题了 -- 这块不执行了,前面执行了!
update account set balance = balance + 500 where id = 2;
*/
-- 使用数据库事务管理整个转账的业务操作
-- 开启事务
START TRANSACTION ;
-- 操作多个sql语句或多张表的sql(同时增删改)
UPDATE account SET balance = balance - 500 WHERE id = 1;
-- 出问题了
UPDATE account SET balance = balance + 500 WHERE id = 2 ;
-- 事务回滚
ROLLBACK ;
-- 提交事务
COMMIT;
UPDATE account SET balance = 1000 ;
-- 查询账户
SELECT * FROM account ;
CREATE DATABASE 2211_test;
USE 2211_test ;
CREATE TABLE exam(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(10),
math INT,
chinese INT,
english INT
) ;
INSERT INTO exam(NAME,math,chinese,english)
VALUES
('小毛',88,78,70),
('小邓',90,91,92),
('小江',65,66,98),
('小胡',88,77,66);
-- 1)查询表中所有的学生,需要给表以及字段起别名
SELECT
e.`id` '学号',
e.`name` '姓名',
e.`math` '数学',
e.`chinese` '语文',
e.`english` '英语'
FROM
exam e; -- 表的别名
-- 2)查询表中所有学生的姓名和对应的英语成绩
SELECT
NAME '姓名',
english '英语成绩'
FROM
exam ;
-- 3)统计每个学生的总分
SELECT
NAME '姓名',
(math+chinese+english) '总分'
FROM exam ;
-- 查询姓名为小江的学生成绩
SELECT
math '数学',
chinese '语文',
english '英语'
FROM
exam
WHERE NAME = '小江' ;
-- 5)查询英语成绩大于90分的同学
SELECT
*
FROM
exam
WHERE english > 90 ;
-- 6)查询总分大于200分的所有同学
SELECT
*
FROM
exam
WHERE (math + chinese + english) > 200 ;
-- 查询英语分数在80-90的同学
SELECT
*
FROM
exam
WHERE english BETWEEN 70
AND 80;
-- 查询数学分数为89,90,91的同学
SELECT
*
FROM
exam
WHERE math IN (89, 90, 91) ;
-- )查询数学>80,语文>80的同学
SELECT
*
FROM
exam
WHERE math > 80
AND chinese > 80 ;
-- 对总分排序按从高到底的顺序输出
SELECT
(math + chinese + english) '总分'
FROM
exam
ORDER BY (math + chinese + english) DESC ;
-- )对学生成绩按照英语降序,英语相同学员按照数学降序
SELECT
*
FROM
exam
ORDER BY english DESC,
math DESC ;
-- 统计一个班级共有多少学生
SELECT
COUNT(id) 'total'
FROM exam ;
-- 查询数学成绩最高分的同学
SELECT
*
FROM
exam
WHERE math =
(SELECT
MAX(math)
FROM
exam) ;
-- 统计数学成绩大于90分的学生有多少个
SELECT
COUNT(id) 'total'
FROM
exam
WHERE
english > 90;
-- 统计一个班级数学总成绩
SELECT SUM(math) '数学总成绩' FROM exam ;
-- 统计班级语文,英语,数学的各科的总成绩
SELECT
SUM(chinese),
SUM(english),
SUM(math)
FROM
exam ;
SELECT * FROM exam ;
1.delete from 表名和truncate table 表名的区别?
where…group by…having…