数据库概述
什么是数据库?
所谓的数据库就是指存储和管理数据的仓库
扩展内容1:数据库有哪些分类?(了解)
早期: 层次式数据库、网络型数据库(已过时)
现在:关系型数据库、非关系型数据库
一些工具的使用注意事项:
pdf 能看不能编辑
md 可以编辑 需要安装软件
数据库比文件直接存数据 更安全,更可靠
大部分还是关系型数据库
外面往Dos窗口粘贴: 先复制 在DOS窗口鼠标右键空白处即可
Dos窗口往外面 复制黏贴
win7 先标记(右键-->标记) 然后在空白处右键,在复制的地方ctrl v
win8 win 10 不用标记
在DOS窗口中写错数据不能返回上一行,只能同行返回。建议在外面写出后复制过去。
想用Dos窗口以前的命令 上下箭头进行切换 (只能是同一个窗口。)
打开黑屏的解决方式 typora:
右键点击typora.exe,“属性”——“兼容性”,勾选“以兼容模式运行这个程序”,在下拉菜单里选择“Windows Vista (Service Pack 1)”,确定后再重新打开typora。
大小写都可以sql语句,在DOS窗口中。
typora 右键--》插入--》代码块
cmd窗口出现 syntax syntax 语说明法有问题 (语法)
创建快捷方式:右键-- 发送到---桌面快捷方式
syst 输出有关联的语句
Tab是缩进键
什么是关系型数据库?
底层以二维表(有行有列)的形式保存数据的库就是关系型数据库
stu-学生表
学生编号 | 姓名 | 年龄 |
---|---|---|
1001 | 刘沛霞 | 35 |
1002 | 陈子枢 | 18 |
扩展内容2:常见的关系型数据库有哪些?(了解)
-
Sql Server:微软提供,收费,适用于一些中型或大型的项目中,在java中的使用占比不高(.NET中使用的较多)
-
Oracle:甲骨文公司提供,收费,适用于一些大型或者超大型的项目中,在java中的使用占比非常高
-
mysql:瑞典MySQLAB公司提供,免费开源,适用于一些小型或者中型的项目中,在Java中的使用占比较高(小巧轻量) 被Oracle收购后现在变成了收费。
mariadb其实就是MySQL的一个分支,用法和MySQL完全一样。免费 -
DB2:IBM公司提供,收费,在一些银行、金融等行业中使用较多。在java中的使用占比也不高。
-
Sqlite:迷你数据库,嵌入式设备中(安卓、苹果手机、pad)
查询表记录
数据库相关概念
1、什么是数据库服务器
数据库服务器就是一个软件(比如mysql软件)将数据库软件安装在电脑上,当前电脑就是一个数据库服务器。就可以对外提供存取数据的服务
在一个数据库服务器中可以创建多个数据库(dataBases),每一个数据库都是一个单独的仓库。
2、什么是数据库
数据库就是存储和管理数据的仓库,通常情况下,一个网站的中的所有数据会存放在一个数据库中。例如:
jd.com db_jd(数据库)
taobao.com db_taobao(数据库)
...
3、什么是表
一个数据库中可以创建多张表,每张表用于存储一类信息(数据库),例如:
jd.com中的用户数据 tb_user(表)
jd.com中的商品数据 tb_product(表)
jd.com中的订单数据 tb_order(表)
…
4、什么表记录·
一张表中可以包含多行表记录,每一行表记录用于存储某一个具体的数据
学生编号 | 姓名 | 年龄 |
---|---|---|
1001 | 刘沛霞 | 35 |
1002 | 陈子枢 | 18 |
。。。 | 。。。 | 。。。 |
什么是SQL语言?
SQL是一门用于操作关系型数据库的通用的语言(使用SQL可以操作所有的关系型数据库)
使用SQL可以操作数据库、表、表记录
(1)创建数据库、删除数据库、修改数据库、查询数据库
(2)创建表、删除表、修改表、查询表
(3)新增表记录、删除表记录、修改表记录、查询表记录
使用SQL也可以操作存储过程/视图/索引等。 每句话分号结尾。
提示:SQL是一个标准通用的操作关系型数据库的语言(普通话),每个数据库厂商为了增强自己数据库的功能,都提供了支持自己数据库的语言,称之为数据库的方言。方言不通用!
连接mysql服务器
**通过命令行工具(也可以通过第三方的工具如:Navicat , SQLyog )**可以登录MySQL客户端,连接MySQL服务器,从而访问服务器中的数据。
1、连接mysql服务器:
mysql -uroot -p密码 -- 注意空格 这个没有分号特殊.其他的sql语句每句话几乎都有分号. 输入密码 可以写 -P +回车 (密码在下一行书写) 密码不显示安全输入
**-u:**后面的root是用户名,这里使用的是超级管理员root; (mysql默认的用户名就是root)
**-p:(小写的p)**后面的root是密码,这是在安装MySQL时就已经指定的密码;
2、连接mysql服务器并指定IP和端口:
mysql -uroot -proot -h127.0.0.1 -P3306
-h:后面给出的127.0.0.1是服务器主机名或ip地址,可以省略的,默认连接本机(即 如果是这个ip地址代表本机,可以省略不写);
**-P:(大写的P)**后面的3306是连接端口,可以省略,默认连接3306端口 (3306端口可以省略);
3、退出客户端命令:quit或exit或 \q
4、FAQ:常见问题:
解决方法:复制mysql安装目录下的bin目录的路径,将bin目录的路径添加到path环境变量中!!
把mysql安装目录放到最前面 用 “ ,”隔开。 win7
win8 win10 没有分号。 编辑后上移即可。
重装 mysql要先停用服务:
计算机—右键管理----服务和应用程序 ,服务----mysql(mariadb)—右键—停止 右键属性—启动类型—手动或禁用. 每次开启计算机它会随着操作系统会自动启动.
扩展内容3:
(1)在cmd中连接mysql服务器之后,可以使用 #、/**/、-- 等符号添加注释,例如:
注意: – (这个注释后面先要加空格)
(2)在cmd中连接mysql服务器之后,在书写SQL语句时,可以通过 \c 取消当前语句的执行。例如:
数据库及表操作
创建、删除、查看数据库(注意删数据库不要把它系统自带的数据库删除 mysql,information_schema, performance_schema)
提示: (1)SQL语句对大小写不敏感。推荐关键字使用大写,自定义的名称(库名,表名,列名等)使用小写。
SHOW DATABASES; -- 查看当前数据库服务器中的所有库 多个s query:查询
CREATE DATABASE mydb1; -- 创建mydb1库 database 数据库
(2)并且在自定义名称时,针对多个单词不要使用驼峰命名,而是使用下划线连接。(例如:tab_name,而不是 tabName )
– 01.查看mysql服务器中所有数据库
show databases; -- 查看服务器所有的数据库
show tables; -- 查询当前库所有表 table表
– 02.进入某一数据库(先进入数据库后,才能操作库中的表和表记录)
– 语法:USE 库名;
use mysql;-- 进入到"mysql"数据库
show tables; -- 查询当前库所有表
– 查看已进入的库(了解)
select database(); -- select选择,选定 这个语法比较特殊
– 03.查看当前数据库中的所有表
-- 先进入某一个库,再查看当前库中的所有表
use test;
show tables;
– 04.删除mydb1库
– 语法:DROP DATABASE 库名;
drop database mydb1;-- 删除mydb1库,但如果删除的库不存在,则会报错。 drop 减少
-- 思考:当删除的库不存在时,如何避免错误产生?
drop database if exists mydb1;
-- 如果mydb1库存在则删除,如果不存在,也就不会执行删除操作。
– 05.重新创建mydb1库,并指定编码为utf8
– 语法:CREATE DATABASE 库名 CHARSET 编码;
– 需要注意的是,mysql中不支持横杠(-),所以utf-8要写成utf8;
create database mydb1 charset utf8;-- 字符集和 charset
– 如果不存在则创建mydb1; //创建数据库需要先判断是否有一个同名的数据库,有需要先进行删除操作(因为不能在创建一个相同名字的数据库),之后再进行创建.
create database if not exists mydb1 charset utf8;
– 06.查看建库时的语句(并验证数据库库使用的编码) 这个主要是验证数据库的编码用的(了解)
– 语法:SHOW CREATE DATABASE 库名; 直接在创建数据库的语句前加个 show
show create database mydb1;
创建、删除、查看表 (对表进行操作需要先进入到数据库)
总结: 对数据库和表的创建和删除,查看 都是 create drop show,创建和删除都是先进行判断,创建是不存在创建数据库,而表是先删除表在创建.
– 07.进入mydb1库,删除stu学生表(如果存在)
– 语法:DROP TABLE 表名; 注意多条sql语句可以一起执行前提是有分号(;)隔开.
use mydb1;-- 进入到mydb1库
drop table if exists stu;-- 如果存在stu表,则删除
– 08.创建stu学生表(编号[数值类型]、姓名、性别、出生年月、考试成绩[浮点型]),建表的语法:
CREATE TABLE 表名(
列名 数据类型, (逗号分隔)
列名 数据类型,
...
列名 数据类型
);
SQL语句: 主键不一定是数值,也有可能是字符串,只有主键是数字的时候才能设置为自增.
-- 如果存在,则删除stu表
drop table if exists stu;
-- 创建stu学生表
create table stu( -- 先换行(shift+enter,单独的enter键是执行sql命令),在tab缩进一下
-- 如果id是主键并且是数值,可以设置为自增.可以保证每次的id值都不一样.
id int primary key auto_increment, -- 给id添加主键约束,并自增。
name varchar(50), -- 可变长字符串 ,50代表最多只能存50个字符。
gender varchar(10) not null, -- 给gender添加非空的约束。
birthday date,
score double -- 最后不需要逗号。列和列之间用 ,隔开
) ;
– 09.查看stu学生表结构
– 语法:desc 表名;
desc stu;
Null:表示将来给这些列插入值是否允许为空(yes代表允许) Default:表示如果不给值的话默认为null
新增、更新、删除(表记录,引号的用法,GBK)
注意在sql语句中写的都是英文符号,java也是不要写成中文.可以再输入法中设置标点符号为英文的格式.
在输入法上右键–设置—勾选在中文是使用英文标点—确定.
– 10.往学生表(stu)中插入记录(数据)
– 语法:INSERT INTO 表名(列名1,列名2,列名3…) VALUES(值1,值2,值3…);
-- 如果是在cmd中执行插入记录的语句,先 set names gbk; 再插入记录!
-- 由于id已经设置了主键自增,所以再插入数据,id可以不用给值,但不可以不给,写个null。 在数据库中字符串和日期用单引号,不要写双引号。
insert into stu(id,name,gender,birthday,score) values(null,'tom','male','2000-3-4',89);-- 注意前后顺序一致.
insert into stu values(null,'john','male','2002-5-4',79);-- 同时插入多行数据,从第二行开始前面的那个()的内容可以省略.
insert into stu values(null,'andy','fmale','2004-5-4',69);-- insert 插入 into到...里面
-- 查询学生表中的所有记录
select*from stu; -- *代表所有的
提示:
(1)当为所有列插入值时,可以省写列名(从第二个),但值的个数和顺序必须和声明时列的个数和顺序保持一致!
(2)SQL语句中的值为字符串或日期时,值的两边要加上单引号(有的版本的数据库双引号也可以,但推荐使用单引号)。
(3)(针对cmd窗口)在插入数据之前,先设置编码:set names gbk; -- 因为cmd窗口默认是gbk
或者用以下命令连接mysql服务器:
mysql --default-character-set=gbk -uroot -proot
等价于:
mysql -uroot -proot
set names gbk;
– 11.查询stu表所有学生的信息
– 语法:SELECT 列名 | * FROM 表名
select * from stu; -- *代表所有 select几乎都是对表进行查询操作的,除了查看当前进入的库.
– 12.修改stu表中所有学生的成绩,加10分特长分
– 修改语法: UPDATE 表名 SET 列=值,列=值,列=值…[WHERE子句];
update stu set score=score+10; -- update更新 (不写条件代表更新所有的score)
-- score+=10 mysql中不支持+=
– 13.修改stu表中编号为1的学生成绩,将成绩改为83分。
update stu set score=83 where id=1;-- where一般用于语句中加个条件时,进行过滤用的
-- 修改3号学生的性别为'male',成绩改为99;
update stu set score=99,gender='male' where id=3;
提示:where子句用于对记录进行筛选过滤,保留符合条件的记录,将不符合条件的记录剔除。
– 14.删除stu表中所有的记录 (删除的语法是最简单的) 注意增删改查都是对表的记录进行操作的
– 删除记录语法: DELETE FROM 表名 [where子句]
delete from stu; -- 删除stu表中的所有记录 删除表中的记录用的是delete,那2个用的是drop
– 仅删除符合条件的 (删除是直接删,不像查询样考虑显示的数据,直接删就完了)
delete from stu where id>2; – 删除stu表中id大于2的记录
查询表记录
– 准备数据: 以下练习将使用db10库中的表及表记录,请先进入db10数据库!!!
基础查询
SELECT 语句用于从表中选取数据。结果被存储在一个结果表中(称为结果集)。
语法:SELECT 列名称 | * FROM 表名
提示:(1) *(星号)为通配符,表示查询所有列。
select * from emp;
(2)但使用 *(星号)有时会把不必要的列也查出来了,并且效率不如直接指定列名
– 15.查询emp表中的所有员工,显示姓名,薪资,奖金
select name,sal,bonus from emp;
– 16.查询emp表中的所有部门和职位
select dept,job from emp;
比如想看 部门dept 和 讲师 job 的种类,每类只需要显示一条就行了。
思考:如果查询的结果中,存在大量重复的记录,如何剔除重复记录,只保留一条? */
剔除一个表中的重复记录
– 在select之后、列名之前,使用DISTINCT 剔除重复的记录
select distinct dept,job from emp; -- distinct 不同种类的
WHERE子句查询
WHERE子句查询语法:SELECT 列名称 | * FROM 表名称 WHERE 列 运算符 值
WHERE子句后面跟的是条件,条件可以有多个,多个条件之间用连接词(or | and)进行连接
下面的运算符可在 WHERE 子句中使用:
– 17.查询emp表中【薪资大于3000】的所有员工,显示员工姓名、薪资
select name,sal from emp where sal>3000;
– 18.查询emp表中【总薪资(薪资+奖金)大于3500】的所有员工,显示员工姓名、总薪资
select name,sal+bonus from emp ; -- 求所有员工的总薪资
select name,sal+bonus from emp
where sal+bonus>3500;
–如果将’韩少云’的奖金更新为null值,在执行上面的SQL语句,会有问题吗?(null+任何值=null)
update emp set bonus=null where name='韩少云';
在进行查询:可以看出韩少云,薪资 sal=5000应该>3500,但是奖金为null,所以相加为null值。显示不出来。
– ifnull(列名, 值)函数: 判断指定的列是否包含null值,如果有null值,用第二个值替换null值
(null一般用0替换)
select name,sal+ifnull(bonus,0) from emp
where sal+ifnull(bonus,0)>3500;
– 注意查看上面查询结果中的表头,如何将表头中的 sal+bonus 修改为 “dec总薪资”
注意列别名不能用在where子句里面
– 使用as
可以为表头指定别名
select name as 姓名,sal+ifnull(bonus,0) as 总薪资 from emp
where sal+ifnull(bonus,0)>3500;
– 另外as可以省略
select name 姓名,sal+ifnull(bonus,0) 总薪资 from emp
where sal+ifnull(bonus,0)>3500;
– 19.查询emp表中【薪资在3000和4500之间】的员工,显示员工姓名和薪资
select name, sal from emp
where sal>=3000 and sal<=4500; -- and
– 提示: between…and… 在…和…之间
select name,sal from emp
where sal between 3000 and 4500; -- 包括3000,也包括4500.如果不包括头和尾不能用between and.
注意:这2者的区别只有一条:上面的写法边界可以控制,是否为>= ,>号。
下面的写法必须包含头和尾。
– 20.查询emp表中【薪资为 1400、1600、1800】的员工,显示员工姓名和薪资
注意:1.where字句里面多个条件要有连接词。
2.如果用and表示你逻辑有错误:用and表示把每个员工的薪资都拿来,看是否同时满足这3个条件,怎么可能有一个员工的薪资同时满足这3个条件.所以应该用or
select name,sal from emp
where sal=1400 or sal=1600 or sal=1800; -- or表示或则
– 或者用另一种写法:in
select name,sal from emp
where sal in(1400,1600,1800); //查询显示所有满足其中()任意一个条件的表里面的记录
– 21.查询薪资不为1400、1600、1800的员工,显示员工姓名和薪资
select name,sal from emp
where not(sal=1400 or sal=1600 or sal=1800);
-- 或
select name,sal from emp
where sal not in(1400,1600,1800);
– 22.(自己完成) 查询emp表中薪资大于4000和薪资小于2000的员工,显示员工姓名、薪资。
注意:不能用and,因为没有薪资是比4000大,比2000还小。
select name,sal from emp
where sal>4000 or sal<2000;
– 23.(自己完成) 查询emp表中薪资大于3000并且奖金小于600的员工,显示员工姓名、薪资、奖金。
select name,sal,bonus from emp
where sal>3000 and bonus<600; -- 结果有误差,少了一行数据 null的哪一行
–== 处理null值(null值和任何值比较都是false)==
select name,sal,ifnull(bonus,0) from emp
where sal>3000 and ifnull(bonus,0)<600;
– 24.查询没有部门的员工(即部门列为null值)
select * from emp where dept=null; -- 条件错误,在where条件里不能用某一个列名等于null值作为条件去筛选. 即便是它本身。解决:用is.
select * from emp where dept is null; -- 信息正确
– 思考:如何查询有部门的员工(即部门列不为null值)
select * from emp where dept is not null;
-- 或则
select * from emp where not (dept is null);
模糊查询(它也属于where字句查询)
LIKE 操作符用于在 WHERE 子句中搜索列中的指定模式。
可以和通配符(%、_)配合使用,其中"%"表示0或多个任意的字符
,"_"表示一个任意的字符
。
语法:SELECT 列 | * FROM 表名 WHERE 列名 LIKE 值
示例:
– 25.查询emp表中姓名中以"刘"字开头的员工,显示员工姓名。
select name from emp where name like '刘%';
– 26.查询emp表中姓名中包含"涛"字的员工,显示员工姓名。
select name from emp where name like '%涛%';
– 27.查询emp表中姓名以"刘"开头,并且姓名为两个字的员工,显示员工姓名。
select name from emp where name like '刘_';
select name from emp where name like '刘_ _';
多行函数查询
多行函数也叫做聚合(聚集)函数,根据某一列或所有列进行统计。
常见的多行函数有:
多行函数 | 作用 |
---|---|
COUNT( 列名 | * ) | 统计结果集中指定列的记录的行数。 – 数数,计算 |
MAX( 列名 ) | 统计结果集中某一列值中的最大值 |
MIN( 列名 ) | 统计结果集中某一列值中的最小值 |
SUM( 列名 ) | 统计结果集中某一列所有值的和 |
AVG( 列名 ) | 统计结果集中某一列值的平均值 |
提示:(1**)多行函数不能用在where子句中。
(2)多行函数和是否分组有关,分组与否会直接影响多行函数的执行结果。
(3)多行函数在统计时会对null值进行过滤,直接将null值丢弃,不参与统计。
– 28.统计emp表中薪资大于3000的员工个数(就是把查询的列名,用关键字包起来)
注意:统计所有列有几行,统计某一列有多少行,结果有可能一样也可能不一样。因为比如bonus这一列:有null值,统计结果就由原来的7变为6.
==推荐写 * ==
select count(*)from emp where sal>3000; --count* 对所有列统计行数 7
select count(id)from emp where sal>3000; --countid 对所有id统计行数 7
– 29.求emp表中的最高薪资
select max(sal) from emp; -- 返回最高薪资 5000
select min(sal) from emp;
– 30.统计emp表中所有员工的薪资总和(不包含奖金)
select sum(sal) from emp;-- 薪资总和:39650
select sum(bonus) from emp;--奖金总和:5900 数值正确,多行函数会对null值处理,直接丢弃,不参与统计.
– 31.统计emp表员工的平均薪资(不包含奖金)
select sum(sal)/count(*) from emp;
select avg(sal) from emp;-- 39650/12 一般用这个,底层用的是上面那种方式算的。
多行函数需要注意的问题:
- 多行函数和是否分组有关,如果查询结果中的数据没有经过分组,默认整个查询结果是一个组,多行函数就会默认统计当前这一个组的数据。产生的结果只有一个。
-== 如果查询结果中的数据经过分组(分的组不止一个),多行函数会根据分的组进行统计,有多少个组,就会统计出多少个结果。==
select * from emp;
例如:统计emp表人数
select count(*) from emp; -- 12 没分组按照是默认是同一个组进行统计人数.一个组只会参生一个结果.
结果返回的就是emp表中的所有人数
再例如:根据性别对emp表中的所有员工进行分组,再统计每组的人数,显示性别和对应人数
按性别是分为2组,然后再去统计每组的人数
select count(*) from emp group by gender; --10 2
分组查询(这几个分组,排序,分页是和where子句并列的关系,只不过分顺序,而不要当做where条件来用。)
GROUP BY 语句根据一个或多个列对结果集进行分组。 (类似于where子句,放在查询表后面)
在分组的列上我们可以使用 COUNT,SUM,AVG,MAX,MIN等函数。
语法:SELECT 列 | * FROM 表名 [WHERE子句] GROUP BY 列;(注意如果有where子句则先写where子句在写分组)
培优部,就业部,null. 这3组。
– 32.对emp表,按照部门对员工进行分组,查看分组后效果。
select name,dept from emp group by dept; -- 只显示每组的第一个人 group 组
--统计分组后,每组的人数
select count(*) from emp group by dept;-- 3个组,所以会统计出三个结果
因为是二维表所以只能看到每组的第一个人。
– 33.对emp表按照职位进行分组,并统计每个职位的人数,显示职位和对应人数
-- 根据job进行分组,统计每个组的人数(每个职位的人数)
select job,count(*) from emp group by job;
当然也不是每一个列都适合分组,如按姓名,50个人如果都是不同的名字,分为50组,所以也没啥意义。
– 34.对emp表按照部门进行分组,求每个部门的最高薪资(不包含奖金),显示部门名称和最高薪资
88888888888
-- 如果不分组,直接使用max(sal),这是统计整个emp表中的最高薪资
select max(sal) from emp;-- 5000;
-- 如果根据部门分组,可以分为三个组,在使用max(sal),就是统计每个组的最高薪资.
select dept,max(sal) from emp group by dept;
因为是按照部门分的列,所以可以显示部门,你要是显示名字又不是按照名字分组,2者关系有没有映射没啥意义。
排序查询
注意: where子句>分组>排序 先写where在写分组,在写排序. (优先顺序)
使用 ORDER BY 子句将结果集中记录根据指定的列排序后再返回
语法:SELECT 列名 FROM 表名 ORDER BY 列名 [ASC|DESC]
ASC(默认)升序,即从低到高;DESC 降序,即从高到低。
– 35.对emp表中所有员工的薪资进行升序(从低到高)排序,显示员工姓名、薪资。
注意:升序指的是重上到下数,由低到高。
select name,sal from emp order by sal ; -- 默认是升序asc可以省略 order 顺序
select name,sal from emp order by sal asc; -- 升序 order by 排序依据 (ascend上升)
– 36.对emp表中所有员工的奖金进行降序(从高到低)排序,显示员工姓名、奖金。
select name,bonus from emp order by bonus desc; -- 降序 不能省略 (descend降序)
分页查询(这几个的顺序)
先写 where 分组 排序 分页 (优先顺序)即前面where 分组,排序,分页都没有在写分页。
总结: 它们都是放在查询表之后的位置.
在mysql中,通过**limit进行分页查询,**查询公式为:
limit 重什么位置开始取值(即页码的起始位置),每页显示的记录数
limit (页码-1)*每页显示记录数, 每页显示记录数
– 37.查询emp表中的所有记录,分页显示:每页显示3条记录,返回所有页的数据。
页码:比如,第一页就是1.
-- 每页显示3条,查询第1页数据 limit 界限,范围
select * from emp limit 0,3; -- 第一页页码是1,(1-1)*3=0 每页记录数;3条记录为:3
-- 每页显示3条,查询第2页数据
select * from emp limit 3,3;
-- 每页显示3条,查询第3页数据
select * from emp limit 6,3;
– 38.求emp表中薪资最高的前3名员工的信息,显示姓名和薪资
-- 现根据薪资降序(从高到低)排序
select name,sal from emp order by sal desc;
-- 在排序的基础上分页查询,只查询第一页
select name,sal from emp order by sal desc limit 0,3;
其他函数==(可以放在前面也可以放在where子句里面)==
函数名 | 解释说明 |
---|---|
curdate() | 获取当前日期,格式是:年月日 用法: select curdate(); |
curtime() | 获取当前时间 ,格式是:时分秒 同上 |
sysdate()/now() | 获取当前日期+时间,格式是:年月日 时分秒 同上 |
year(date) | 返回date中的年份 用法:里面需要传一个参数 |
month(date) | 返回date中的月份 select month(now()); 获取now这个时间中的月份 |
day(date) | 返回date中的天数 |
hour(date) | 返回date中的小时 |
minute(date) | 返回date中的分钟 |
second(date) | 返回date中的秒 |
CONCAT(s1,s2…) | 将s1,s2 等多个字符串合并为一个字符串 |
CONCAT_WS(x,s1,s2…) | 同CONCAT(s1,s2,…)函数,是在每个字符串之间要加上x,x是分隔符 |
1.curdate,curtime,sysdate/now, year 用法类似
2. year(date) 从当前日期获取年份,month,day,hour,minute,second,用法类似
– 39.查询emp表中所有【在1993和1995年之间出生】的员工,显示姓名、出生日期。
日期可以进行比较,但是在这个表的birthday是一个年-月-日格式的数据,所以把日期1993进行转化为日期格式在进行比较:‘1993-1-1’ 或则用year函数把日期提取出来在进行比较。
-- 将运算符两边的值都转成日期类型,在进行比较
select name,birthday from emp
where birthday>='1993-1-1' and birthday<='1995-12-31';
--或则,将日期中的年份提取出来,用年份和年份进行比较
select name,birthday from emp
where year(birthday)>=1993 and year(birthday)<=1995;
– 40.查询emp表中本月过生日的所有员工
select * from emp
where month(now())=month(birthday);
now():获取当前日期 年 月 日。 month:把当前年份的日期提取出来。然后再把当前表中的年 月 日 中的月份获取出来。最后在进行比较。
补充:获取下个月过生日的所有员工:注意第一种写法如果是12月+1为13月,不等于1月。下面这种写法更好,2边都要取余。
拼接字符串练习即:给查询的值添加单位。
– 41.查询emp表中员工的姓名和薪资(薪资格式为: xxx(元) )
select name,concat(sal,'(元)') from emp; -- concat(s1,s2,s3...)
– 补充练习:查询emp表中员工的姓名和薪资(薪资格式为: xxx/元 )
-- 用concat 函数实现
select name,concat(sal,'/元') from emp;
-- 或则 用concat_ws实现, concat_ws(x,s1,s2,s3...)
select name, concat_ws('/',sal,'元') from emp; -- 即,s1与s2两两拼接会加上一个x
mysql的数据类型
数值类型
MySQL中支持多种整型,其实很大程度上是相同的,只是存储值的大小范围不同而已。
tinyint:占用1个字节,相对于java中的byte
smallint:占用2个字节,相对于java中的short
int:占用4个字节,相对于java中的int (重点掌握)
bigint:占用8个字节,相对于java中的long
其次是浮点类型即:float和double类型
float:4字节单精度浮点类型,相对于java中的float
double:8字节双精度浮点类型,相对于java中的double (重点掌握)
字符串类型
1、char(n) 定长字符串,最长255个字符。n表示字符数,例如:
– 创建user表,指定用户名为char类型,字符长度不超过10
字符数量: 张三,2个字符. Tom,3个字符.
create table user(
username char(10),
...
);
所谓的定长,是当插入的数据的长度小于指定的长度时,剩余的空间会用空格填充。(缺点:这样可能会浪费空间)
优点是 :效率比varchar更高。
char类型往往用于储存长度固定的数据。(如:身份证号,学生编号)
2、varchar(n) 变长字符串,最长不超过65535个字节,n表示字符数,一般超过255个字符,会使用text类型,例如: various 各种各样的。
iso8859-1码表:一个字符占用1个字节,1*n <65535, n最多等于 65535
utf8码表:一个中文汉字占用3个字节,3*n<65535,n最多等于 65535/3
GBK码表:一个中文汉字占用2个字节,2*n<65535,n最多等于 65535/2
– 创建user表,指定用户名为varchar类型,长度不超过10个字符
create table user(
username varchar(10)
);
所谓的不定长,是当插入的数据的长度小于指定的长度时,剩余的空间可以留给别的数据使用。(节省空间)
总结:长度固定的数据,用char类型,这样既不会浪费空间,效率也比较高。
如果长度不固定,使用varchar类型,这样不会浪费空间。
3、大文本(长文本)类型
最长65535个字节,一般超过255个字符列的会使用text,超过用char或varchar类型.
– 创建user表:
create table user(
resume text
);
另,text也分多种,其中bigtext存储数据的长度约为4GB。
扩展内容3:(面试题)char(n)、varchar(n)、text都可以表示字符串类型,其区别在于:
(1)char(n)在保存数据时,如果存入的字符串长度小于指定的长度n,后面会用空格补全,因此可能会造成空间浪费,但是char类型的存储速度较varchar和text快。
因此char类型适合存储长度固定的数据,这样就不会有空间浪费,存储效率比后两者还快!
(2)varchar(n)保存数据时,按数据的真实长度存储,剩余的空间可以留给别的数据用,因此varchar不会浪费空间。
因此varchar适合存储长度不固定的数据,这样不会有空间的浪费。
(3)text是大文本类型,一般文本长度超过255个字符,就会使用text类型存储。
日期类型
date:年月日
time:时分秒
datetime:年月日 时分秒
timestamp:时间戳(实际存储的是一个时间毫秒值),与datetime存储日期格式相同。两者的区别是:
-
timestamp最大表示1970~2038年,而datetime范围是1000~9999
-
timestamp在插入数据、修改数据时,可以自动更新成系统当前时间(后面用到时再做讲解)
mysql的字段约束
字段约束/列约束 --> 约束: 即添加一些限制.
主键约束
主键约束:如果为一个列添加了主键约束,那么这个列就是主键,主键的特点是唯一且不能为空。
主键的作用: 作为一个唯一标识,唯一的表示一条表记录(作用类似于人的身份证号,可以唯一的表示一个人一样。)
添加主键约束,例如将id设置为主键: primary key
create table stu(
id int primary key, -- primary 主要的 key 键
...
);
如果主键是数值类型,为了方便插入主键(并且保证插入数据时,主键不会因为重复而报错),可以设置一个主键自增策略。 – 注意:只有是数值类型才可以设置自增。
主键自增策略是指:设置了自增策略的主键,可以在插入记录时,不给id赋值,只需要设置一个null值,数据库会自动为id分配一个值(AUTO_INCREMENT变量,默认从1开始,后面依次+1),这样既可以保证id是唯一的,也省去了设置id的麻烦。
注意:设置自增 第二个数删除后 在插入一个数直接回变为3
设置自增 也可以从新赋值 如果大于自增的值 则会返回一个+1的数 因为id不能重复
将id主键设置为自增:
create table stu(
id int primary key auto_increment, -- automatic 自动的
... -- increament 增加
);
注意:主键约束不等于非空约束+唯一约束,还作为唯一标示。
非空约束
非空约束:如果为一个列添加了非空约束,那么这个列的值就不能为空,但可以重复。
添加非空约束,例如为password添加非空约束: not null
create table user(
password varchar(50) not null,
...
);
唯一约束
唯一约束:如果为一个列添加了唯一约束,那么这个列的值就必须是唯一的(即不能重复),但可以为空。
添加唯一约束,例如为username添加唯一约束及非空约束:
unique:代表唯一约束
unique not null:代表 唯一且不为空,它和主键约束有区别(主键约束还有一个标识的作用)
create table user(
username varchar(50) unique not null,
...
);
外键约束(通常2张或2张以上的表)
解释:如果需要查询多张表,多张表中间是需要有关联的。如:在查询部门的同时查询员工,再查询班级的时候查询学生。这个关联就是建立在表和表之间的,这种关联关系就是通过外键约束来实现的。
外键其实就是用于 通知 数据库两张表数据之间对应关系的这样一个列。这样数据库就会帮我们维护两张表中数据之间的关系。
foreign key(dept_id) references dept(id) references:参考
(1) 创建表的同时添加外键
create table emp(
id int,
name varchar(50),
dept_id int,
foreign key(dept_id) references dept(id)
);
(1)如果是要表示两张表的数据之间存在对应关系,只需要在其中的一张表中添加一个列,保存另外一张表的主键,就可以保存两张表数据之间的关系。
但是添加的这个列(dept_id)对于数据库来说就是一个普通列,数据库不会知道两张表存在任何关系,因此数据库也不会帮我们维护这层关系。
(2)如果将dept_id列设置为外键,等同于通知数据库,部门表和员工表之间存在对应关系,dept_id列中的数据要参考部门的主键,数据库一旦知道部门和员工表之间存在关系,就会帮我们维护这层关系。
(可以避免数据的完整性和一致性被破坏,比如你删除销售部,赵四和刘能就找不到部门了会报错,阻止你删除)
那现在就是想删除呢? 可以吧赵四和刘能的id改为别的部门的id如3:update emp dept_id=3 where is=4 or id=5;
注意:正在公司中可以设置外键,也可以不设置外键。区别在于设置外键数据库会帮你维护关系,不设置这个关系你自己维护。而保存这种关系则是在一个表中添加另一个表的主键,一般是在数据多行的一张表添加少的一张。因为再少的一方添加主键保存不完数据,如:在同一行中的一个位置显示2个数据
思考:如果在创建表时没有指定外键,那么后期该如何指定外键?以及如何删除外键? 在下面扩展中。
表关系
常见的表关系分为以下三种:
一对多(多对一)、一对一、多对多
解释: 1对应1,说明张飞被王老师教过,1对应2说明刘备被齐老师教过。
对于多对多的关系,设置联合主键就表明各个单独的主键在第三张表中可以重复,但是stuid和teaid加起来不能重复。 然后添加外键数据库底层会帮你自动维护这种关系,不添加外键就需要你自己维护这种关系,比如:删除其中一行是否对另一种表存在影响。参考扩展。
如何判断主表从表
多表查询
连接查询
– 准备数据: 以下练习将使用db30库中的表及表记录,请先进入db30数据库!!!
查询部门表
查询员工表
– 42.查询部门和部门对应的员工信息
select *from dept,emp; -- 就是写多张表,之间用逗号隔开。
上面的查询中存在大量错误的数据,一般我们不会直接使用这种查询。
**笛卡尔积查询:**所谓笛卡尔积查询就是指,查询两张表,其中一张表有m条记录,另一张表有n条记录,查询的结果是m*n条。
虽然笛卡尔积查询中包含大量错误数据,但我们可以通过where子句将错误数据剔除,保留下来的就是正确数据。
-- 员工部门编号=部门的编号
select *from dept,emp -- 因为id在部门表和员工表都有,所以加上列名进行区分
where emp.dept_id=dept.id; -- 因为dept_id只存在于emp表中得列,所以可以直接写 写dept_id 而id则是既存在emp表又存在dept表,所以dept.id(表名.列名) 用于区分, 不然会报错模糊不清的。
那么这个条件是怎么找的:第一行根据表可以看出员工表的id,比如张三的id为1对应的主键depe_id为1,恰好又是部门表的id为1所以查询显示的数据正确。 第二行:员工表的id为1对应的外键是1,但是对应的部门表的id为2所以这是个错误数据。
通过where子句将笛卡尔积查询中的错误数据剔除,保留正确的数据,这就是连接查询!
上面的查询可以换成下面的查询:(,换位inner join where换位on )
select *from dept inner join emp
on emp.dept_id=dept.id; -- 内连接查询,和上面的查询结果一样
左外连接查询 (以左边为基准)
和上面的区别就是,上面的连接查询只查询部门对应的员工信息,这个地方的左外连接是部门表所有员工的信息,然后出了显示部门对应的员工信息外还要显示如果没有对应的信息则显示为null. 总结:区别就是出了显示满足对应的关系外还要显示没有关系的数据
– 43.查询【所有部门】及部门对应的员工,如果某个部门下没有员工,员工显示为null
注意:where变为on
select *from dept left join emp
on emp.dept_id=dept.id;
左外连接查询:可以将左边表中的所有记录都查询出来,右边表只显示和左边相对应的数据,如果左边表中某些记录在右边没有对应的数据,右边显示为null即可。
( 如果是想查左边所有表的数据,就用左外连接查询)
连接符号","换成 left join where 换成on
总结:左外连接就是查询左边表所有的的数据,然后右边表显示和左边表对应的数据。
右外连接查询 (以右边为基准)
– 44.查询【所有员工】及员工所属部门,如果某个员工没有所属部门,部门显示为null
select *from dept right join emp
on emp.dept_id=dept.id;
右外连接查询:可以将右边表中的所有记录都查询出来,左边表只显示和右边相对应的数据,如果右边表中某些记录在左边没有对应的数据,可以显示为null。
总结:右外连接就是查询右边表所有的的数据,然后左边表显示和右边表对应的数据。
全外连接查询:
扩展:如果想将两张表中的所有数据都查询出来(左外+右外并去除重复记录),可以使用全外连接查询,但是mysql又不支持全外连接查询。
select *from dept left join emp on emp.dept_id=dept.id
union
select *from dept right join emp on emp.dept_id=dept.id;
可以使用union将左外连接查询的结果和右外连接查询的结果合并在一起,并去除重复的记录。例如:
需要注意的是:union可以将两条SQL语句执行的结果合并,但是有前提:
(1**)两条SQL语句查询的结果列数必须一致**
联合查询:把2张表所有的数据显示在一张表中。
== 但是dept有列 emp表有3列,所以报错==
解决:只显示列数相同的个数。*是一个2列,一个3列所以不对。
(2)两条SQL语句查询的结果列名、顺序也必须一致
如果不一致我们可以指定列别名。
并且union默认就会将两个查询中重复的记录去除(如果不希望去除重复记录,可以使用union all)
子查询练习
将一个sql执行的结果作为条件来完成的一个查询叫做子查询。
– 准备数据:以下练习将使用db40库中的表及表记录,请先进入db40数据库!!!
– 45.列出薪资比’王海涛’的薪资高的所有员工,显示姓名、薪资
单表
-- 求出'王海涛'的薪资
select sal from emp where name='王海涛'; -- 2450
-- 求出比'王海涛'薪资高的所有员工信息 这样写没有写死,以后再改工资不用再更改代码 像这样将一条语句作为另一条语句的子句就叫子查询.
select name,sal from emp
where sal>(select sal from emp where name='王海涛');
– 46.列出与’刘沛霞’从事相同职位的所有员工,显示姓名、职位。
单表
-- 求出刘培霞从事的职位
select job from emp where name='刘沛霞';
-- 再求出和刘培霞从事相同职位的员工
select name ,job from emp
where job=(select job from emp where name='刘沛霞');
– 47.列出薪资比’大数据部’部门(已知部门编号为30)所有员工薪资都高的员工信息,显示员工姓名、薪资和部门名称。=这个是查询的2张表:部门表 员工表
如果不考虑没有部门的员工
-- 先连接查询部门表和员工表,显示员工姓名、薪资和部门名称
select emp.name ,sal, dept.name from dept,emp
where emp.dept_id=dept.id;
-- .列出薪资比'大数据部'部门(已知部门编号为30)所有员工薪资都高的员工信息,可以简化为:1.求出'大数据'部门最高的薪资
select max(sal) from emp where dept_id=30;
2.--列出薪资比'大数据'部门最高薪资还高的员工信息
select emp.name ,sal, dept.name from dept,emp
where emp.dept_id=dept.id and
sal>(select max(sal) from emp where dept_id=30);
如果加上没有部门的员工 (考虑韩少云),保证其中一张表的数据都查询出来可以用外连接
-- 使用外连接查询部门表和员工表
select emp.name ,sal, dept.name from dept right join emp
on emp.dept_id=dept.id;
-- 求出'大数据'部门最高的薪资
select max(sal) from emp where dept_id=30;
--列出薪资比'大数据'部门最高薪资还高的员工信息
select emp.name ,sal, dept.name from dept right join emp
on emp.dept_id=dept.id
where sal>(select max(sal) from emp where dept_id=30);
多表查询练习(表别名用法,列别名)
– 48.列出在’培优部’任职的员工,假定不知道’培优部’的部门编号,显示部门名称,员工名称。
分析:部门的名称和员工的名称来自2张表所以用多表查询。
注意:1.可以添加列别名,也可以添加表别名。用法差不多,as可以省略。
-- 连接查询部门表和员工表 多张表查询 先连接查询
select dept.name,emp.name from dept,emp
where emp.dept_id=dept.id;
-- 求出部门名称为'培优部'的员工
select dept.name,emp.name from dept,emp
where emp.dept_id=dept.id and dept.name='培优部';
注意:2.如果你声明了别名又不用,那也是错的。比如:在前面select中from表指定别名时,在后面的where条件中不用e.dept_id 仍用以前的则还是错的。 总之在前面声明后的别名,后面再出现就一定要用别名替换,不然你声明它干啥的。
列别名没有这个用法。前面指定列的别名后,后面的列还是要用原先的。
– 扩展:可以为表明加别名,加了别名后,就需要使用别名替换表名
select d.name,e.name from dept d,emp e
where e.dept_id=d.id and d.name='培优部';
– 49.(自查询)列出所有员工及其直接上级,显示员工姓名、上级编号,上级姓名
把一张表当做2张表来看
/* 将emp同时看做员工表和上级表----起别名当做2张表,其实还是一张表。
* emp e1 看做员工表 emp e2 看做上级表
* 查询的表: emp e1, emp e2
* 查询的列: e1.name,e2.id, e2.name
* 连接条件: 员工所属上级编号=上级编号
* e1.topid=e2.id
*/
select e1.name,e2.id, e2.name -- select一般用于查询表的结构
from emp e1, emp e2 -- from 一般跟来至那个表
where e1.topid=e2.id; -- where 一般用于条件的筛选
– 50.列出最低薪资大于1500的各种职位,显示职位和该职位的最低薪资
-- 根据职位进行分组,在求出每个职位的最低薪资
select job,min(sal) from emp group by job;
-- 求出最低薪资大于1500的职位有哪些
select job,min(sal) from emp group by job
having min(sal) >1500;
补充内容:where和having子句的区别:
(1)相同点: where和having都可以对记录进行筛选过滤。
(2)区别:where是在分组之前,对记录进行筛选过滤,并且where子句中不能使用多行函数以及列别名(但是可以使用表别名)
(3)区别:having是在分组之后,对记录进行筛选过滤,并且having子句中可以使用多行函数以及列别名、表别名。
– 51.列出在每个部门就职的员工数量、平均工资。显示部门编号、员工数量,平均薪资。
-- 根据部门分组,统计每个组(每个部门)的人数,平均薪资
select dept_id,count(*),avg(sal)
from emp
group by dept_id;
– 52.查出至少有一个员工的部门,显示部门编号、部门名称、部门位置、部门人数。
-- 连接查询部门表和员工表
select d.id,d.name,d.loc
from dept d,emp e
where d.id=e.dept_id;
-- 根据部门进行分组
select d.id,d.name,d.loc,count(*)
from dept d,emp e
where d.id=e.dept_id
group by d.name
having count(*)>0; -- 这句话加不加都行,因为上面分组已经满足了这个条件.
– 53.列出受雇日期早于直接上级的所有员工,显示员工编号、员工姓名、部门名称。
/* emp e1 员工表, emp e2 上级表
* 查询的表: emp e1, emp e2, dept d
* 查询的列: e1.id, e1.name, d.name
* 连接条件: e1.topid=e2.id
* e1.dept_id=d.id
* 筛选条件: e1.hdate < e2.hdate
*/
select e1.id, e1.name, d.name
from emp e1, emp e2, dept d
where e1.topid=e2.id
and e1.dept_id=d.id
and e1.hdate < e2.hdate;
– 补充:查询员工表中薪资最高的员工信息 day11pm 223
select name,max(sal) from emp; -- 这个查询的结果是错误的,因为name和sal没有对应关系。
-- 可以按照薪资降序排序,每页显示一条,查询第一页.
select * from emp order by sal desc limit 0,1;
-- 或则 : 也可以使用子查询 效率会偏低一些
select max(sal) from emp;-- 求emp表中的最高薪资
select * from emp where sal=(select max(sal) from emp);
数据库备份与恢复
也可以使用工具进行备份Navicat,Sqlyog
备份数据库
在cmd窗口中(未登录的状态下,即:没有连接数据库),可以通过如下命令对指定的数据库进行备份:
mysqldump -u用户名 -p 数据库的名字 > 备份文件的位置
– 注意-p和数据库的名字有空格 文件没有会自动帮你创建
示例1: 对db40
库中的数据(表,表记录)进行备份,备份到 d:/db40.sql
文件中
mysqldump -uroot -p db40 > d:/db40.sql
– 这个没有分号
键入密码,如果没有提示,即表示备份成功!
也可以一次性备份所有库,例如:
对mysql服务器中所有的数据库进行备份,备份到 d:/all.sql文件中
mysqldump -uroot -p --all-database > d:/all.sql
键入密码,如果没有提示错误(警告信息不是错误,可以忽略),即表示备份成功!
恢复数据库(先备份才能恢复)
1、恢复数据库方式一:
在cmd窗口中(未登录的状态下),可以通过如下命令对指定的数据库进行恢复:
mysql -u用户名 -p 数据库的名字 < 备份文件的位置
示例:将d:/db40.sql文件中的数据恢复到db60库中
– 在cmd窗口中(已登录的状态下),先创建db60库:
create database db60 charset utf8;
– 在cmd窗口中(未登录的状态下)
mysql -uroot -p db60 < d:/db40.sql
2、恢复数据库方式二:
在cmd窗口中(已登录的状态下),可以通过source执行指定位置的SQL文件:
source sql文件的位置
示例:将d:/db40.sql文件中的数据恢复到db80库中
– 在cmd窗口中(已登录的状态下),先创建db80库,进入db80库:
create database db80 charset utf8;
use db80;
– 再通过source执行指定位置下的sql文件:
source d:/db40.sql
Navicat软件的使用
Navicat Premium是一套带图形用户界面的数据库管理工具,让你从单一应用程序中同时连接MySQL、MariaDB、MongoDB、SQL Server、Oracle、PostgreSQL 和 SQLite数据库。使用Navicat可以快速、轻松地创建、管理和维护数据库。
1、使用navicat连接mysql服务器(使用cmd连接mysql服务器)
2、查看所有库、进入数据库、创建数据库、删除数据库、修改数据库
3、创建表、查看表、修改表、删除表
4、新增表记录、查询表记录、修改表记录、删除表记录
5、使用navicat书写SQL语句操作数据库、表和表记录
...
哔哩哔哩视频链接:https://www.bilibili.com/video/BV1yA41147Vi/
扩展内容
现创建学生表:
use test; -- 进入test库
drop table if exists stu; -- 删除学生表(如果存在)
create table stu( -- 创建学生表
id int, -- 学生id
name varchar(20), -- 学生姓名
gender char(1), -- 学生性别
birthday date -- 出生年月
);
修改表—新增列
语法:ALTER TABLE tabname ADD col_name datatype [DEFAULT expr][,ADD col_name datatype…];
1、往stu表中添加score列,double类型
alter table stu add score double;
修改表—修改列
语法:ALTER TABLE tabname MODIFY (col_name datatype [DEFAULT expr][,MODIFY
col_name datatype]…);
1、修改id列,将id设置为主键
alter table stu modify id int primary key;
2、修改id列,将id主键设置为自动增长
alter table stu modify id int auto_increment;
修改表—删除列
语法:ALTER TABLE tabname DROP [COLUMN] col_name;
1、删除stu表中的score列
alter table stu drop score;
添加或删除主键及自增
思考:a) 在建表时,如何为id指定主键约束和自增?
b) 建好的表,如何通过修改添加主键约束和自增?
c) 如何删除表中的主键约束和自增?
1、创建stu学生表,不添加主键自增, 查看表结果
use mydb1; -- 切换到mydb1库
drop table if exists stu; -- 删除stu学生表(如果存在)
create table stu( -- 重建stu学生表,没有主键自增
id int,
name varchar(20),
gender char(1),
birthday date
);
desc stu; -- 查看表结构
表结构如下: 没有主键约束和自增。
2、如果表没有创建,或者要删除重建,在创建时可以指定主键或主键自增
drop table if exists stu; -- 删除stu表
create table stu( -- 重新创建stu表时,指定主键自增
id int primary key auto_increment,
name varchar(20),
gender char(1),
birthday date
);
desc stu; -- 查看表结构
表结构如下: 已经添加了主键约束和自增。
3、如果不想删除重建表,也可以通过修改表添加主键或主键自增
再次执行第1步,创建stu学生表,不添加主键自增,查看表结果
– 例如: 将stu学生表中的id设置为主键和自动增长
alter table stu modify id int primary key auto_increment;
desc stu; -- 查看表结构
如果只添加主键约束,不设置自增
alter table stu modify id int **primary key**;
如果已经添加主键约束,仅仅设置自增,但需注意:
(1)如果没有设置主键,不可添加自增
(2)只有当主键是数值时,才可以添加自增
alter table stu modify id int **auto_increment**;
4、如果想删除主键自增
– 删除主键自增时,要先删除自增
alter table stu modify id int;
– 再删除主键约束
alter table stu drop primary key;
desc stu; -- 查看表结构
添加外键约束
1、添加外键方式一:建表时添加外键
现有部门表如下:
– 创建部门表
create table dept(
id int primary key auto_increment, -- 部门编号
name varchar(20) -- 部门名称
);
要求创建员工表,并在员工表中添加外键关联部门主键
– 创建员工表
create table emp(
id int primary key auto_increment, -- 员工编号
name varchar(20), -- 员工姓名
dept_id int, -- 部门编号
foreign key(dept_id) references dept(id) -- 指定dept_id为外键
);
2、添加外键方式二:建表后添加外键
现有部门表和员工表:
– 创建部门表
create table dept(
id int primary key auto_increment, -- 部门编号
name varchar(20) -- 部门名称
);
– 创建员工表
create table emp(
id int primary key auto_increment, -- 员工编号
name varchar(20), -- 员工姓名
dept_id int -- 部门编号
);
– 如果表已存在,可以使用下面这种方式:
alter table emp add constraint fk_dept_id foreign key(dept_id) references dept(id);
其中 fk_dept_id (名字由自己定义),是指外键约束名称,也可以将【constraint fk_dept_id】省略,MySQL会自动分配一个外键名称,将来可以通过该名称删除外键。
foreign key(dept_id)中的dept_id为外键
删除外键约束
1、首先通过 “show create table 表名”语法,查询含有外键表的建表语句,例如:
show create table emp;
显示结果如下:
其中,emp_ibfk_1是在创建表时,数据库为外键约束指定的一个名字,删除这个名字即可删除外键关系,例如:
alter table emp drop foreign key emp_ibfk_1;
外键删除成功!
添加外键约束(多对多)
– 现有学生(stu)表和教师(tea)表:
– 创建学生表
create table stu(
stu_id int primary key auto_increment, -- 学生编号
name varchar(20) -- 学生姓名
);
– 创建教师表
create table tea(
tea_id int primary key auto_increment, -- 教师编号
name varchar(20) -- 教师姓名
);
– 添加第三方表(stu_tea)表示学生表和教师表关系
– 创建学生和教师关系表
create table stu_tea(
stu_id int, -- 学生编号
tea_id int, -- 教师编号
primary key(stu_id,tea_id), -- 设置联合主键
foreign key(stu_id) references stu(stu_id), -- 添加外键
foreign key(tea_id) references tea(tea_id) -- 添加外键
);
其中为了防止重复数据,将stu_id和tea_id设置为联合主键。联合主键就是在第三张表中单独的可以重复,但是加起来不能重复。
将stu_id设置为外键,参考stu表中的stu_id列
并将tea_id设置为外键,参考tea表中的tea_id列
级联更新、级联删除
– 创建db20库、dept表、emp表并插入记录
– 删除db20库(如果存在),并重新创建db20库
drop database if exists db20;
create database db20 charset utf8;
use db20;
– 创建部门表, 要求id, name字段
create table dept(
id int primary key auto_increment, -- 部门编号
name varchar(20) -- 部门名称
);
– 往部门表中插入记录
insert into dept values(null, '财务部');
insert into dept values(null, '人事部');
insert into dept values(null, '科技部');
insert into dept values(null, '销售部');
– 创建员工表, 要求id, name, dept_id
create table emp(
id int primary key auto_increment, -- 员工编号
name varchar(20), -- 员工姓名
dept_id int, -- 部门编号
foreign key(dept_id) references dept(id) -- 指定外键
on update cascade -- 级联更新
on delete cascade -- 级联删除
);
insert into emp values(null, '张三', 1);
insert into emp values(null, '李四', 2);
insert into emp values(null, '老王', 3);
insert into emp values(null, '赵六', 4);
insert into emp values(null, '刘能', 4);
级联更新:主表(dept表)中的主键发生更新时(例如将销售部的id改为40),从表(emp表)中的记录的外键数据也会跟着该表(即赵六和刘能的部门编号也会更新为40)
级联删除:如果不添加级联删除,当删除部门表中的某一个部门时(例如删除4号部门),若该部门在员工表中有对应的员工(赵六和刘能),删除会失败!
若果添加了级联删除,当删除部门表中的某一个部门时,若该部门在员工表中有对应的员工,会在删除部门的同时,将员工表中对应的员工也删除!
where中不能使用列别名
但可以使用表别名,而且是一旦指定了表别名·后面出现表明的要使用表别名替换。
SQL语句的书写顺序:
select * | 列名 -- 确定要查询的列有哪些
from 表名 -- 确定查询哪张表
where 条件 -- 通过筛选过滤,剔除不符合条件的记录
group by 分组的列 -- 指定根据哪一列进行分组
having 条件 -- 通过条件对分组后的数据进行筛选过滤
order by 排序的列 -- 指定根据哪一列进行排序
limit (countPage-1)*rowCount, rowCount -- 指定返回第几页记录以及每页显示多少条
SQL语句的执行顺序:
from 表名 -- 确定查询哪张表
where 条件 -- 通过筛选过滤,剔除不符合条件的记录
select * | 列名 列别名 -- 确定要查询的列有哪些,
group by 分组的列 -- 指定根据哪一列进行分组
having 条件 -- 通过条件对分组后的数据进行筛选过滤
order by 排序的列 -- 指定根据哪一列进行排序
limit (countPage-1)*rowCount, rowCount
**** 关于where中不能使用列别名但是可以使用表别名?**
是因为,表别名是声明在from中,from先于where执行,先声明再使用没有问题,但是列别名是声明在select中,where先于select执行,如果先使用列别名,再声明,这样执行会报错!!