DDL:数据定义语言
作用 : 用于完成对数据库对象(数据库、数据表、视图、索引等)的创建、删除、修改
数据库操作
查询数据库
- > 显示当前 mysql 中的数据库列表
> show databases;
- > 显示指定名称的数据的创建的 SQL 指令
> show create database 库名 ;
创建数据库
- > 创建数据库
> create database 库名 ;
- > 创建数据库,当指定名称的数据库不存在时执行创建
> create database if not exists 库名 ;
- > 在创建数据库的同时指定数据库的字符集(字符集:数据存储在数据库中采用的编码格式 utf8 、 gbk )
> CREATE DATABASE IF NOT EXISTS 库名 CHARSET 'utf8';
修改数据库字符集
- > 修改数据库的字符集
> alter database 库名 CHARSET 字符集 ;
删除数据库
- > 删除数据库
> drop database 库名 ;
- > 如果数据库存在则删除数据库
> drop database if exists 库名 ;
使用/切换数据库
use 库名 ;
数据表操作
创建完数据库之后,接下来就是在数据库中创建数据表。在MySQL 中,数据表以二维表格的形式展示,表格中的一行代表一条完整的数据记录,表格中的一列代表数据的某个特定属性。
需要注意:
在数据库中创建表之前,需要查看当前使用的数据库
语法:
select database();
然后切换到你需要操作的数据库
use db_name;
建表
create table 表名 ( 字段 1 字段类型 , 字段 2 字段类型 , ... 字段 n 字段类型 );
字段类型 :
int:整型
double:浮点型,例如 double(5,2) 表示最多 5 位,其中必须有 2 位小数,即最大值为 999.99;
char:固定长度字符串类型;
char(10): 'aaa ' 占 10 位
varchar:可变长度字符串类型;
varchar(10): 'aaa' 占 3 为
text:字符串类型;
blob:字节类型;
date:日期类型,格式为: yyyy-MM-dd ;
time:时间类型,格式为: hh:mm:ss
timestamp:时间戳类型 yyyy-MM-dd hh:mm:ss 会自动赋值
datetime:日期时间类型 yyyy-MM-dd hh:mm:ss
boolean:mysql不支持 ,oracle 支持
示例 :
创建一张存储学员信息的表 :stu
表中的字段有 :
s_id 一条数据的唯一标识符 int primary key auto_increment
s_name 学员姓名 varchar(30)
s_sex 学员性别 varchar(10)
s_age 学员年龄 int
s_class 学员所在班级 varchar(50)
s_num 学号 varchar(16)
s_type 学员专业 varchar(50)
sql 语句
create table stu(
s_id int primary key auto_increment,
s_name varchar(30),
s_sex varchar(10),
s_age int,
s_class varchar(50),
s_num varchar(16),
s_type varchar(50)
);
查看所有表
SHOW TABLES;
重命名表
rename table 原表名 to 新表名 ;
查看创建表语句信息
SHOW CREATE TABLE 表名 ;
修改字符集
ALTER TABLE 表名 CHARACTER SET 修改后的字符集 ;
注意: 一般使用 utf8( 就是 utf-8)
查表字段信息
DESC 表名 ;
备份表
create table 新表名 as select * from 要备份的表的名称 ;
如 :
create table tname2 as select * from tname1;
备份表结构
create table 新表名 like 要备份的表的名称 ;
如 :
create table tname2 like tname1;
删除表
DROP TABLE 表名 ;
添加列
ALTER TABLE 表名 ADD 添加的列名 填加的列字段类型 ;
修改列
alter table 表名 modify 要修改的列名 修改后的字段类型;
删除列
alter table 表名 drop 列名 ;
注意: 一次只能删一列
列重命名
ALTER TABLE 表名 CHANGE 原列名 新列名 新字段类型;
DML:数据操作语言
插入数据
作用 : 给表中添加数据
insert into 表名 ( 列名 1, 列名 2....) values ( 值 1, 值 2....);
示例:
insert into stus(stu_num,stu_name,stu_gender,stu_age,stu_tel)
values ( '20210101' , ' 张三 ' , ' 男 ' , 21 , '13030303300' );
# 数据表名后的字段名列表顺序可以不与表中一致,但是 values 中值的顺序必须与表名 后字段名顺序对应
insert into stus(stu_num,stu_name,stu_age,stu_tel,stu_gender)
values ( '20210103' , ' 王五 ' , 20 , '13030303302' , ' 女 ' );
# 当要向表中的所有列添加数据时,数据表名后面的字段列表可以省略,
#但是 values 中的值的顺序要与数据表定义的字段保持一致 ;
insert into stus values ( '20210105' , ' 孙 琦' , ' 男 ' , 21 , '13030303304' , '666666' );
# 不过在项目开发中,即使要向所有列添加数据 , 也建议将列名的列表显式写出来 ( 增强 SQL的稳定性 )
insert into stus(stu_num,stu_name,stu_gender,stu_age,stu_tel,stu_qq)
values ( '20210105' , ' 孙琦 ' , ' 男 ' , 21 , '13030303304' , '666666' );
修改数据
update 表名 set 列名 1= 值 1 ,列名 2= 值 2 [ where 条件 ];
示例:
# 将学号为 20210105 的学生姓名修改为 “ 孙七 ” (只修改一列)
update stus set stu_name= ' 孙七 ' where stu_num= '20210105' ;
# 将学号为 20210103 的学生 性别修改为 “ 男 ”, 同时将 QQ 修改为 777777 (修改多列)
update stus set stu_gender= ' 男 ' ,stu_qq= '777777' where stu_num= '20210103' ;
# 根据主键修改其他所有列
update stus set stu_name= ' 韩梅梅' ,stu_gender= ' 女 ' ,stu_age= 18 ,stu_tel= '13131313311' ,stu_qq= '999999' where stu_num= '20210102' ;
# 如果 update 语句没有 where 子句,则表示修改当前表中所有行(记录)
update stus set stu_name= 'Tom' ;
删除数据
delete from 表名 [where 条件 ];
示例:
# 删除学号为 20210102 的学生信息
delete from stus where stu_num= '20210102' ;
# 删除年龄大于 20 岁的学生信息 ( 如果满足 where 子句的记录有多条,则删除多条记录 )
delete from stus where stu_age> 20 ;
# 如果删除语句没有 where 子句,则表示删除当前数据表中的所有记录 ( 敏感操作 )
delete from stus;
DQL:数据查询语言
查询全表
select * from 表名 ;
查询指定列
select 列名1,列名2,… from 表名;
条件查询
select * from 表名 where 条件;
注意:
条件查询就是在查询时给出 WHERE 子句,在 WHERE 子句中可以使用如下运算符及关键 字:
=、 != 、 > 、 < 、 <= 、 > 、 >=
BETWEEN…AND (等价 <= 和 >=)
IN(set) (包含 )
IS NULL (非空 )
AND (逻辑与 )
OR (逻辑或 )
NOT (逻辑非 )
XOR (逻辑异或 )
示例:
-- 查询成绩小于 80 的学员
select * from stu where score < 80 ;
-- 查询成绩等于 100 的学员
select * from stu where score = 100 ;
-- 查询成绩在 85~100 的学员
select * from stu where math between 80 and 100 ;
-- 查询姓名叫做 “ 张三 ” 或者 “ 李四 ” 的所有学生信息。
select * from stu where name beteween " 张三 " and " 李四 " ;
-- 查询成绩不小于 80 的学员
select * from stu where not score < 80 ;
-- 查询姓名不叫做 “ 张三 ” 或者 “ 李四 ” 的所有学生信息。
select * from stu where name not beteween " 张三 " and " 李四 " ;
-- 查询姓名叫做 “ 张三 ” 或者 “ 李四 ” 的所有学生信息。
select * from stu where name in ( " 张三 " , " 李四 " );
-- 查询成绩小于 0 或大于 100 的学员
select * from stu where score < 0 or score > 100 ;
-- 查询性别为空的学员
select * from stu where sex IS NULL ;
模糊查询
当想查询姓名中包含 a 字母的学生时就需要使用模糊查询了。模糊查询需要使用关键字 LIKE。
_:任意一个字母
%:任意 0~n 个字母 ' 张 %'
示例:
-- 查找姓名为 3 个字母的学生信息
select * from stu where name like '___' ;// 注意是 3 个 _ ,表示匹配 3 个字符
-- 查找以字母 b 开头的学生信息
select * from stu where name like 'b%' ;
MySQL 同样也支持其他正则表达式的匹配, MySQL 中使用 REGEXP 操作符来进行正则 表达式匹配。
示例:
-- 查找姓名以 l 开头且以 y 结尾的学生信息
select * from stu where name regexp '^l' and name regexp 'y$' ;
去重
关键字 :distinct
示例
-- 查询 stu 表中 age 字段,剔除重复行
select distinct age from stu;
计算列
对从数据表中查询的记录的列进行一定的运算之后显示出来
+,-,*,/,%
例
-- 出生年份 = 当前年份 - 年龄
select stu_name, 2021 -stu_age from stus;
别名
如果在连接查询的多张表中存在相同名字的字段,我们可以使用 表名 . 字段名 来进行区 分,如果表名或字段名太长则不便于SQL 语句的编写,我们可以使用数据表别名
示例
-- 字段起别名
select name AS 姓名 from stu;
-- 表名起别名
select s .name ,s .sex from stu AS s;
-- AS 可以省略
select name 姓名 from stu;
select s .name ,s .sex from stu s;
排序order by
将查询到的满足条件的记录按照指定的列的值升序 / 降序排列
语法:
select * from 表名 where 条件 order by 列名 asc|desc;
order by 列名 表示将查询结果按照指定的列排序
asc 按照指定的列升序(默认)
desc 按照指定的列降序
# 单字段排序
select * from stu where age> 15 order by score desc ;
# 多字段排序 : 先满足第一个排序规则 , 当第一个排序的列的值相同时再按照第二个列的
规则排序
select * from stus where age> 15 order by score asc ,age desc ;
聚合函数
聚合函数是用来做纵向运算的函数:
COUNT() :统计指定列不为 NULL 的记录行数;
MAX() :计算指定列的最大值,如果指定列是字符串类型,那么使用字符串排序运算;
MIN() :计算指定列的最小值,如果指定列是字符串类型,那么使用字符串排序运算;
SUM() :计算指定列的数值和,如果指定列类型不是数值类型,那么计算结果为 0 ;
AVG() :计算指定列的平均值,如果指定列类型不是数值类型,那么计算结果为 0 ;
例:
-- 统计年龄大于 20 的学员人数
select count (*) as cnt from stu where age> 20 ;
-- 统计学员的总年龄
select sum(age) from stu;
-- 统计学员的平均年龄以及总年龄
select sum(age),avg(age) from stu;
-- 统计学员的最低年龄以及最高年龄
select max(age),min(age) from stu;
-- 计算班级平均分
select avg(score) from stu;
分组查询
分组:就是将数据表中的记录按指定的列进行分组
语法
select 分组字段 / 聚合函数
from 表名
[ where 条件 ]
group by 分组列名 [ having 条件 ]
[ order by 排序字段 ]
注意:
语句执行顺序:
1, 先根据 where 条件从数据库查询记录
2,group by 对查询记录进行分组
3, 执行 having 对分组后的数据进行筛选
4, 排序
例:
-- 先对查询的学生信息按性别进行分组(分成了男、女两组),然后再分别统计每组 学生的个数
select stu_gender, count (stu_num) from stus group by stu_gender;
-- 先对查询的学生信息按性别进行分组(分成了男、女两组),然后再计算每组的平 均年龄
select stu_gender,avg(stu_age) from stus group by stu_gender;
-- 先对学生按年龄进行分组,然后统计各组的学生数量,还可以对最终的结果排序
select stu_age, count (stu_num) from stus group by stu_age order by stu_age;
-- 查询所有学生,按年龄进行分组,然后分别统计每组的人数,再筛选当前组人数 >1 的组,再按年龄升序显示出来
select stu_age, count (stu_num)
from stus
group by stu_age
having count (stu_num)> 1
order by stu_age;
-- 查询性别为 ' 男 ' 的学生 , 按年龄进行分组 , 然后分别统计每组的人数 , 再筛选当前组人 数>1 的组 , 再按年龄升序显示出来
mysql> select stu_age, count (stu_num)
-> from stus
-> where stu_gender= ' 男 '
-> group by stu_age
-> having count (stu_num)> 1
-> order by stu_age;
分页查询
语法:
select 查询的字段
from 表名
where 条件
limit param1,param2;
注意 :
- param1:表示获取查询语句的结果中的第一条数据的索引(索引从 0 开始)
- param2:表示获取的查询记录的条数(如果剩下的数据条数 <param2 ,则返回剩下的 所有记录)
注意:
-- 示例
-- 假如 : 对数据表中的学生信息进行分页显示,总共有 10 条数据,我们每页显示 3 条
-- 总记录数: `count 10`
-- 每页显示: `pageSize 3
-- 总页数: `pageCount=count%pageSize==0?
count/pageSize:count/pageSize+1`
-- 查询第一页:
select * from stus [ where ...] limit 0 , 3 ; ( 1 - 1 )* 3
-- 查询第二页:
select * from stus [ where ...] limit 3 , 3 ; ( 2 - 1 )* 3
-- 查询第三页:
select * from stus [ where ...] limit 6 , 3 ; ( 3 - 1 )* 3
-- 查询第四页:
select * from stus [ where ...] limit 9 , 3 ; ( 4 - 1 )* 3
-- 如果在一张数据表中:
-- pageNum 表示查询的页码
-- pageSize 表示每页显示的条数
-- 通用分页语句如下:
select * from stus [ where ...] limit (pageNum- 1 )*pageSize,pageSize;
约束
- 保证数据的有效性
- 保证数据的完整性
- 保证数据的正确性
- 非空约束( not null ):限制此列的值必须提供,不能为 null
- 唯一约束( unique ):在表中的多条数据,此列的值不能重复
- 主键约束( primary key ):非空 + 唯一,能够唯一标识数据表中的一条数据
- 自增长约束 (auto_increment): 每次 +1, 从 1 起
- 检查约束( check ):保证列中的值满足某一条件
- 默认约束( default ):保存数据时 , 未指定值则采用默认值
- 外键约束( foreign key ):建立不同表之间的关联关系
多表查询
语法: select 列名 1, 列名 2,.. from 表 1, 表 2,.. where 判断语句 ;
示例
-- 查看 stu 和 grade 表中的学生学号、姓名、班级、成绩信息
select s.*,g.* from stu s,grade g where s .id = g .stu_id ;
注意: 没有条件会出现笛卡尔积
视图:虚拟表
视图,就是由数据库中一张表或者多张表根据特定的条件查询出得数据构造成得虚拟表
优点:
安全性:
如果我们直接将数据表授权给用户操作,那么用户可以CRUD 数据表中所有数据,加 入我们想要对数据表中的部分数据进行保护,可以将公开的数据生成视图,授权用户访 问视图;用户通过查询视图可以获取数据表中公开的数据,从而达到将数据表中的部分 数据对用户隐藏。
简单性:
如果我们需要查询的数据来源于多张数据表,可以使用多表连接查询来实现;我们 通过视图将这些连表查询的结果对用户开放,用户则可以直接通过查询视图获取多表数 据,操作更便捷。
数据独立:
一旦视图的结构确定了,可以屏蔽表结构变化对用户的影响,源表增加列对视图没 有影响;源表修改列名,则可以通过修改视图来解决,不会造成对访问者的影响。
创建视图
CREATE VIEW 视图名称 AS <SELECT 语句 >
create view view_test1
AS
select * from students
查询视图结构
desc 视图名称 ;
修改视图
create OR REPLACE view 视图名称
AS 查询语句
# 或
alter view 视图名称
AS 查询语句
例:
# 方式 1
create OR REPLACE view view_test1
AS
select * from students where stu_gender= ' 女 ' ;
# 方式 2
alter view view_test1
AS
select * from students where stu_gender= ' 男 ' ;
特性
视图是虚拟表,查询视图的数据是来源于数据表的。当对视图进行操作时,对原数据表中
的数据是否由影响呢?
查询操作 :如果在数据表中添加了新的数据,而且这个数据满足创建视图时查询语句的条
件,通过查询视图也可以查询出新增的数据;当删除原表中满足查询条件的数据时,也会
从视图中删除。
新增数据: 如果在视图中添加数据,数据会被添加到原数据表
删除数据: 如果从视图删除数据,数据也将从原表中删除
修改操作: 如果通过修改数据,则也将修改原数据表中的数据
视图的使用建议 : 对复杂查询简化操作,并且不会对数据进行修改的情况下可以使用视图。
触发器
触发器是数据库的回调函数,它会在指定的数据库事件发生时自动执行调用
1、只有每当执行 delete , insert 或 update 操作时,才会触发,并执行指定的一 条或多条SQL 语句。
例如 :
可以设置触发器,当删除persons 表中 lucy 的信息时,自动删除 grade 表中与 lucy相关的信息
2、触发器常用于保证数据一致,以及每当更新或删除表时,将记录写入日志表
创建触发器
-- 语法 :
-- 修改 sql 语句结束符为 ||
delimiter ||
-- 创建触发器
create trigger 触发器名 [after|before] [ delete |update|delete] on 表名
for each row
begin
语句 ;
end ||
delimiter ;
old: 老数据
new: 新数据
查看触发器
语法: show triggers;
删除触发器
drop trigger 触发器名 ;
练习
-- 准备工作 , 建库 , 切库
CREATE DATABASE IF NOT EXISTS lx CHARSET 'UTF8' ;
USE lx;
-- 1 、创建 persons 表 ,id 设置为主键 , 表的格式 (id integer primary key,name text,addr text,class text)
CREATE TABLE person(
id integer primary key auto_increment ,
name text ,
addr text ,
class text
);
-- 2 、创建 grade 表 , 设置约束条件 (score>0) ,表的格式 (id integer, score integer, year text)
create table grade(
id integer , score integer , year text
);
-- 3 、追加相应的数据 , 见下页
insert into person (name, addr, class) value
( 'lucy' , 'beijing' , 'class_A' );
insert into person (name, addr, class) value
( 'peter' , 'tianjing' , 'class_B' );
insert into person (name, addr, class) value
( 'bob' , 'hebei' , 'class_A' );
insert into grade (id, score, year ) value ( 1 , 78 , '2013' );
insert into grade (id, score, year ) value ( 2 , 98 , '2013' );
insert into grade (id, score, year ) value ( 3 , 80 , '2013' );
insert into grade (id, score, year ) value ( 1 , 88 , '2014' );
-- 4 、打印所有学生的信息 : 包括 name,addr,class,score,year
select p.*,g .score ,g .year from person p,grade g where p .id = g .id ;
-- 5 、将打印所以学生信息的语句 , 创建视图 PersonsGrade, 方便后面使用
create view persongrade as select p.*,g .score ,g .year from person
p,grade g where p .id = g .id ;
-- 6 、查看最高分数是多少?
select max (score) from persongrade;
-- 7 、查看每个班的平均分,以及对应的班级名称和班级人数
select class 班级 , count ( distinct id) 人数 , avg (score) from
persongrade group by class;
-- 8 、在 persons 表中 id 列创建一个索引 persons_id_index
create index person_id_index on person (id);
-- 9 、查看 lucy 在 2013 年的成绩
select * from persongrade where name= 'lucy' and year = '2013' ;
-- 10 、 bob 要退学,必须要删除 bob 所有的信息 ( 包括成绩单 ), 通过设置触发器,自动删除bob 相关的所有数据,设置触发器 tg_delete
delimiter ||
create trigger tg_delete after delete on person for each row
begin
delete from grade where grade .id = old .id ;
end ||
delimiter ;
-- 11 、执行删除 bob 的操作
delete from person where name= 'bob' ;
-- 12 、查看所有人的信息,确定是否执行了删除操作
select * from person;
select * from grade;
select * from persongrade;