MySQL 基本操作
数据库的基本概念
数据
l 描述事物的符号记录称为数据(Data)
l 包括数字,文字、图形、图像、声音、档案记录等
l 以“记录”形式按统一的格式进行存储
数据表
l 将不同的记录组织在一起,就形成了 “表”
l 是用来存储具体数据的
数据库
l 数据库就是表的集合,是存储数据表的仓库
l 以一定的组织方式存储的相互有关的数据
MySQL 数据库系统也是典型的C/S(客户端/服务器)架构的应用,连接时需要专用的客户端工具,Linux下通过mysql命令工具(如果是通过rpm格式安装软件需要安装mysql软件包)。
连接并登录到MySQL操作环境
mysql
-u 指定用户名
-p 指定密码(选项和密码之间不能有空格)
-h 指定主机
-P 指定端口
-S 指定Socket文件
-e 指定SQL命令语句(非交互模式)
SQL及其规范
<1> 在数据库系统中,SQL语句不区分大小写(建议用大写) 。但字符串常量区分大小写。建议命令大写,表名库名小写;
<2> SQL语句可单行或多行书写,以“;”结尾。关键词不能跨多行或简写。
<3> 用空格和缩进来提高语句的可读性。子句通常位于独立行,便于编辑,提高可读性。
SELECT * FROM tb_table
WHERE NAME="YUAN";
<4> 注释:单行注释:--
多行注释:/*......*/
<5>sql语句可以折行操作
SQL语句分类:
1、数据定义语言(DDL)
创建、修改或删除数据库中各种对象,包括表、视图、索引等。
命令:CREATE TABLE , CREATE VIEW, CREATE INDEX、ALTER TABLE ,
DROP TABLE , DROP VIEW, DROP INDEX
2、查询语言(DQL)
按照指定的组合、条件表达式或排序检索已存在的数据库中数据,
不改变数据库中数据。
命令:SELECT…FROM…WHERE…
3、数据操纵语言(DML)
对已经存在的数据库进行元组的插入、删除、修改等操作
命令:INSERT、UPDATE、DELETE
4、数据控制语言(DCL)
用来授予或收回访问数据库的某种特权、
控制数据操纵事务的发生时间及效果、对数据库进行监视
命令:GRANT、REVOKE、COMMIT、ROLLBACK
数据库操作
库名的命令规则:首字符是字母,其余部分可以是字母、数字、下划线、@、$
不能是关键字,如create database table,最长128位,不能是纯数字
查询所有库 show databases; mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | #虚拟库,不占用磁盘空间,存储的是数据库启动后的一些参数(用户表信息,列信息,权限信息,字符信息),存放于内存中 | mysql | #授权库,存放mysql所有的授权信息 | performance_schema | #存放mysql服务的性能参数 | test | #测试库 +--------------------+ 5 rows in set (0.00 sec) 创建库 create database 数据库名; 查看某一个数据库 show create database 数据库名;
示例: mysql> create database xixi; Query OK, 1 row affected (0.00 sec) mysql> show create database xixi; +----------+------------------------------------------------------------------+ | Database | Create Database | +----------+------------------------------------------------------------------+ | xixi | CREATE DATABASE `xixi` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ | +----------+------------------------------------------------------------------+ 1 row in set (0.00 sec) 登录使用数据库 use 库名;
查看当前使用的库 select database();
示例: mysql> use xixi; Database changed mysql> select database(); +------------+ | database() | +------------+ | xixi | +------------+ 1 row in set (0.00 sec) 修改:alter 删除库 drop database 数据库名;
示例: mysql> drop database xixi; Query OK, 0 rows affected (0.01 sec) mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test | +--------------------+ 4 rows in set (0.00 sec)
mysql数据库类型
数值类型
下面的表显示了需要的每个整数类型的存储和范围。

日期 /时间类型

字符串类型
字符串类型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET。该节描述了这些类型如何工作以及如何在查询中使用这些类型。

CHAR和VARCHAR类型类似,但它们保存和检索的方式不同。它们的最大长度和是否尾部空格被保留等方面也不同。在存储或检索过程中不进行大小写转换。
BINARY和VARBINARY类类似于CHAR和VARCHAR,不同的是它们包含二进制字符串而不要非二进制字符串。也就是说,它们包含字节字符串而不是字符字符串。
BLOB是一个二进制大对象,可以容纳可变数量的数据。有4种BLOB类型:TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB。它们只是可容纳值的最大长度不同。
有4种TEXT类型:TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT。这些对应4种BLOB类型,有相同的最大长度和存储需求。
数据表操作
1 我们需要进入某一个库里才能创建表 2 一张表必须属于一个库 3 表分成:字段+数据记录
create table 表名 (
字段名1 类型 (宽度) 约束条件,
字段名2 类型(宽度) 约束条件,
字段名3 类型(宽度) 约束条件,
.......
);
注:
同一张表中,字段名不能相同
字段名和类型必须有宽度和约束条件为可选项
最后一个字段不加 “,”
示例:
mysql> create table host (
-> id int(10) not null,
-> hostname char(20) default '',
-> primary key(id)
-> );
Query OK, 0 rows affected (0.11 sec)
查看某个库有多少表,先进入库 show tables;
查看某个新建表信息 show create table 表名;
查看表结构 desc 表名; describe 库名.表名;
查看表的所有字段内容 select * from 表名; mysql> select * from host; Empty set (0.00 sec) #表中没有内容,空集
查看表的某些字段的内容 select id from host; #查看host表的id字段的内容 select id,port from host; #查看host表的id字段和port字典的内容
查看表的某一行的内容 select * from user wherer user_name='zhangsan' #查看user表中user_name等于zhangsan的这一行的所有字段
#查看字符集是否支持中文
show variables like 'character_set_%';
示例:
mysql> show tables;
+----------------+
| Tables_in_xixi |
+----------------+
| host |
+----------------+
1 row in set (0.00 sec)
mysql> show create table host;
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+
| host | CREATE TABLE `host` (
`id` int(10) DEFAULT NULL,
`hostname` char(20) DEFAULT NULL,
`port` int(5) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> desc host;
+----------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+----------+------+-----+---------+-------+
| id | int(10) | YES | | NULL | |
| hostname | char(20) | YES | | NULL | |
| port | int(5) | YES | | NULL | |
+----------+----------+------+-----+---------+-------+
3 rows in set (0.01 sec)
field 代表字段名
type 代表该字段类型,
Null 该字段是否可以为空
default 该字段的默认设置
extra 额外的设置
mysql> select * from xixi.host;
Empty set (0.00 sec) #empty这里表示一张空表
mysql> select id,port from xixi.host;
Empty set (0.00 sec)
mysql> select * from user where user_name='zhangsan';
+-----------+-------------------------------------------+
| user_name | user_passwd |
+-----------+-------------------------------------------+
| zhangsan | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 |
+-----------+-------------------------------------------+
1 row in set (0.00 sec)
create table employee(
id int primary key auto_increment ,
name varchar(20),
gender bit default 1, -- gender char(1) default 1 ----- 或者 TINYINT(1)
birthday date,
entry_date date,
job varchar(20),
salary double(4,2) unsigned,
resume text -- 注意,这里作为最后一个字段不加逗号
);
/* 约束:
primary key (非空且唯一) :能够唯一区分出当前记录的字段称为主键!
unique
not null
auto_increment 主键字段必须是数字类型。
外键约束 foreign key */
设置用户权限(用户不存在时,则新建用户)
MySQL数据库的root用户账户拥有对所有库,表的全部权限,频繁使用root账号会给数据库服务器带来一定的安全风险,实际工作中,通常会建立一些低权限的用户,只负责一部分库,表的管理和维护操作,甚至可以对查询,修改,删除记录等各种操作做进一步的细化限制,从而降低数据库的风险。
GRANT 权限列表 ON 数据库名.表名 TO 用户名@来源地址 [ IDENTIFIED BY ‘密码’ ];
l 权限列表:用于列出授权的各种数据库操作,通过逗号进行分割,如:select,insert,update等,all表示所有权限,可以执行任意操作。
l 库名.表名:用于指定授权操作的数据库和表的名称,可以使用通配符(*)表示所有
l 用户名@来源地址:用于指定用户和允许访问的客户机地址;来源地址可以是IP地址,域名,%通配符表示所有(但不能表示localhost)
MySQL通配符:
l _:任意单个字符 192.168.1._
l %:任意长度的任意字符 192.168.1.%
案例:
mysql> GRANT select ON crushlinux.* TO 'teacher'@'localhost' IDENTIFIED BY '123456';
使用GRANT语句授权的用户记录,会保存到mysql库的user,db,host,tables_priv等相关表中,无需刷新授权表即可生效。
查看用户的权限
SHOW GRANTS FOR 用户名@域名或IP
案例:
mysql> SHOW GRANTS FOR 'teacher'@'localhost';
+---------------------------------------------------------+
| Grants for teacher@localhost |
+---------------------------------------------------------+
| GRANT USAGE ON *.* TO 'teacher'@'localhost' |
| GRANT SELECT ON `crushlinux`.* TO 'teacher'@'localhost' |
+---------------------------------------------------------+
2 rows in set (0.00 sec)
撤销用户的权限
REVOKE 权限列表 ON 数据库名.表名 FROM 用户名@域名或IP
案例:
mysql> REVOKE all ON crushlinux.* FROM 'teacher'@'localhost';
Query OK, 0 rows affected (0.01 sec)
mysql> SHOW GRANTS FOR 'teacher'@'localhost';
+---------------------------------------------+
| Grants for teacher@localhost |
+---------------------------------------------+
| GRANT USAGE ON *.* TO 'teacher'@'localhost' |
+---------------------------------------------+
1 row in set (0.01 sec)
显示服务器信息
mysql> status;
--------------
mysql Ver 14.14 Distrib 5.7.24, for Linux (x86_64) using EditLine wrapper
Connection id: 29
Current database: client
Current user: root@localhost
SSL: Not in use
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server version: 5.7.24-log Source distribution
Protocol version: 10
Connection: Localhost via UNIX socket
Server characterset: utf8
Db characterset: utf8
Client characterset: utf8
Conn. characterset: utf8
UNIX socket: /tmp/mysql.sock
Uptime: 2 days 42 sec
Threads: 1 Questions: 276 Slow queries: 0 Opens: 125 Flush tables: 1 Open tables: 112 Queries per second avg: 0.001
--------------
用于显示广泛的服务器状态信息
mysql> show status;
+-----------------------------------------------+--------------------------------------------------+
| Variable_name | Value |
+-----------------------------------------------+--------------------------------------------------+
| Aborted_clients | 0 |
| Aborted_connects | 0 |
显示创建特定数据库或表
help create database;
help create table;
显示授权用户的安全权限
mysql> show grants;
+---------------------------------------------------------------------+
| Grants for root@localhost |
+---------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION |
| GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION |
+---------------------------------------------------------------------+
2 rows in set (0.00 sec)
显示服务器错误或警告信息
show errors;
show warnings;
显示当前时间
mysql> select now();
+---------------------+
| now() |
+---------------------+
| 2018-12-07 21:05:00 |
+---------------------+
1 row in set (0.00 sec)
显示当前用户及时间
mysql> select CURRENT_USER(),CURRENT_TIMESTAMP;
mysql> select user(),now();
授权Windows客户机地址拥有访问权限:
mysql> grant all on *.* to 'root'@'192.168.200.2' IDENTIFIED BY '123456';
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec)
Windows客户机安装Navicat客户端工具














修改表结构(字段)
修改一列类型
alter table tab_name modify 列名 类型 [完整性约束条件][first|after 字段名];
alter table users2 modify age tinyint default 20;
alter table users2 modify age int after id;
修改列名
alter table tab_name change [column] 列名 新列名 类型 [完整性约束条件][first|after 字段名];
alter table users2 change age Age int default 28 first;
删除一列
alter table tab_name drop [column] 列名;
-- 思考:删除多列呢?删一个填一个呢?
alter table users2
add salary float(6,2) unsigned not null after name,
drop addr;
修改表名
rename table 表名 to 新表名;
修该表所用的字符集
alter table student character set utf8;
删除表
drop table tab_name;
添加主键,删除主键
alter table tab_name add primary key(字段名称,...)
alter table users drop primary key;
eg:
mysql> create table test5(num int auto_increment);
ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key
create table test(num int primary key auto_increment);
-- 思考,如何删除主键?
alter table test modify id int; -- auto_increment没了,但这样写主键依然存在,所以还要加上下面这句
alter table test drop primary key;-- 仅仅用这句也无法直接删除主键
-- 唯一索引
alter table tab_name add unique [index|key] [索引名称](字段名称,...)
alter table users add unique(name)-- 索引值默认为字段名show create table users;
alter table users add unique key user_name(name);-- 索引值为user_name
-- 添加联合索引
alter table users add unique index name_age(name,age);#show create table users;
-- 删除唯一索引
alter table tab_name drop {index|key} index_name
表记录增,删,改
-- 1.增加一条记录insert
/*insert [into] tab_name (field1,filed2,.......) values (value1,value2,.......);*/
create table employee_new(
id int primary key auto_increment,
name varchar(20) not null unique,
birthday varchar(20),
salary float(7,2)
);
insert into employee_new (id,name,birthday,salary) values
(1,'yuan','1990-09-09',9000);
insert into employee_new values
(2,'alex','1989-08-08',3000);
insert into employee_new (name,salary) values
('xialv',1000);
-- 插入多条数据
insert into employee_new values
(4,'alvin1','1993-04-20',3000),
(5,'alvin2','1995-05-12',5000);
-- set插入: insert [into] tab_name set 字段名=值
insert into employee_new set id=12,name="alvin3";
-- 2.修改表记录 update tab_name set field1=value1,field2=value2,......[where 语句]
/* UPDATE语法可以用新值更新原有表行中的各列。
SET子句指示要修改哪些列和要给予哪些值。
WHERE子句指定应更新哪些行。如没有WHERE子句,则更新所有的行。*/
update employee_new set birthday="1989-10-24" WHERE id=1;
--- 将yuan的薪水在原有基础上增加1000元。
update employee_new set salary=salary+4000 where name='yuan';
-- 3.删除表纪录
delete from tab_name [where ....]
/* 如果不跟where语句则删除整张表中的数据
delete只能用来删除一行记录
delete语句只能删除表中的内容,不能删除表本身,想要删除表,用drop
TRUNCATE TABLE也可以删除表中的所有数据,词语句首先摧毁表,再新建表。此种方式删除的数据不能在
事务中恢复。*/
-- 删除表中名称为’alex’的记录。
delete from employee_new where name='alex';
-- 删除表中所有记录。
delete from employee_new;-- 注意auto_increment没有被重置:alter table employee auto_increment=1;
-- 使用truncate删除表中记录。
truncate table emp_new;
表记录 查
CREATE TABLE ExamResult(
id INT PRIMARY KEY auto_increment,
name VARCHAR (20),
JS DOUBLE ,
Django DOUBLE ,
Database DOUBLE
);
INSERT INTO ExamResult VALUES (1,"yuan",98,98,98),
(2,"xialv",35,98,67),
(3,"alex",59,59,62),
(4,"wusir",88,89,82),
(5,"alvin",88,98,67),
(6,"yuan",86,100,55);
-- (1)select [distinct] *|field1,field2,...... from tab_name
-- 其中from指定从哪张表筛选,*表示查找所有列,也可以指定一个列
-- 表明确指定要查找的列,distinct用来剔除重复行。
-- 查询表中所有学生的信息。
select * from ExamResult;
-- 查询表中所有学生的姓名和对应的英语成绩。
select name,JS from ExamResult;
-- 过滤表中重复数据。
select distinct JS ,name from ExamResult;
-- (2)select 也可以使用表达式,并且可以使用: 字段 as 别名或者:字段 别名
-- 在所有学生分数上加10分特长分显示。
select name,JS+10,Django+10,Database+10 from ExamResult;
-- 统计每个学生的总分。
select name,JS+Django+Database from ExamResult;
-- 使用别名表示学生总分。
select name as 姓名,JS+Django+Database as 总成绩 from ExamResult;
select name,JS+Django+Database 总成绩 from ExamResult;
select name JS from ExamResult; //what will happen?---->记得加逗号
-- (3)使用where子句,进行过滤查询。
-- 查询姓名为XXX的学生成绩
select * from ExamResult where name='yuan';
-- 查询英语成绩大于90分的同学
select id,name,JS from ExamResult where JS>90;
-- 查询总分大于200分的所有同学
select name,JS+Django+Database as 总成绩 from
ExamResult where JS+Django+Database>200 ;
-- where字句中可以使用:
-- 比较运算符:
> < >= <= <> !=
between 80 and 100 值在10到20之间
in(80,90,100) 值是10或20或30
like 'yuan%'
/*
pattern可以是%或者_,
如果是%则表示任意多字符,此例如唐僧,唐国强
如果是_则表示一个字符唐_,只有唐僧符合。
*/
-- 逻辑运算符
在多个条件直接可以使用逻辑运算符 and or not
-- 练习
-- 查询JS分数在 70-100之间的同学。
select name ,JS from ExamResult where JS between 80 and 100;
-- 查询Django分数为75,76,77的同学。
select name ,Django from ExamResult where Django in (75,98,77);
-- 查询所有姓王的学生成绩。
select * from ExamResult where name like '王%';
-- 查询JS分>90,Django分>90的同学。
select id,name from ExamResult where JS>90 and Django >90;
-- 查找缺考数学的学生的姓名
select name from ExamResult where Database is null;
-- (4)Order by 指定排序的列,排序的列即可是表中的列名,也可以是select 语句后指定的别名。
-- select *|field1,field2... from tab_name order by field [Asc|Desc]
-- Asc 升序、Desc 降序,其中asc为默认值 ORDER BY 子句应位于SELECT语句的结尾。
-- 练习:
-- 对JS成绩排序后输出。
select * from ExamResult order by JS;
-- 对总分排序按从高到低的顺序输出
select name ,(ifnull(JS,0)+ifnull(Django,0)+ifnull(Database,0))
总成绩 from ExamResult order by 总成绩 desc;
-- 对姓李的学生成绩排序输出
select name ,(ifnull(JS,0)+ifnull(Django,0)+ifnull(Dababase,0))
总成绩 from ExamResult where name like 'a%'
order by 总成绩 desc;
-- (5)group by 分组查询:
-- 注意,按分组条件分组后每一组只会显示第一条记录
-- group by字句,其后可以接多个列名,也可以跟having子句,对group by 的结果进行筛选。
-- 按位置字段筛选
select * from ExamResult group by 2;
-- 练习:对成绩表按名字分组后,显示每一类名字的JS的分数总和
select NAME ,SUM(JS)from ExamResult group by name;
-- 练习:对成绩表按名字分组后,显示每一类名字的Django的分数总和>150的
-- 类名字和django总分
--INSERT INTO ExamResult VALUES (12,"alex",90,90,90);
select name,sum(Django) from ExamResult group by name
having sum(Django)>150;
/*
having 和 where两者都可以对查询结果进行进一步的过滤,差别有:
<1>where语句只能用在分组之前的筛选,having可以用在分组之后的筛选;
<2>使用where语句的地方都可以用having进行替换
<3>having中可以用聚合函数,where中就不行。
*/
-- 练习:对成绩表按名字分组后,显示除了yuan这一组以外的每一类名字的Django
-- 的分数总和>150的类名字和django总分
select name,sum(Django) from ExamResult
WHERE name!="yuan"
group by name
having sum(Django)>130;
-- GROUP_CONCAT() 函数
SELECT id,GROUP_CONCAT(name),GROUP_CONCAT(JS) from ExamResult GROUP BY id;
-- (6)聚合函数: 先不要管聚合函数要干嘛,先把要求的内容查出来再包上聚合函数即可。
-- (一般和分组查询配合使用)
--<1> 统计表中所有记录
-- COUNT(列名):统计行的个数
-- 统计一个班级共有多少学生?先查出所有的学生,再用count包上
select count(*) from ExamResult;
-- 统计JS成绩大于70的学生有多少个?
select count(JS) from ExamResult where JS>70;
-- 统计总分大于280的人数有多少?
select count(name) from ExamResult
where (ifnull(JS,0)+ifnull(Django,0)+ifnull(Database,0))>280;
-- 注意:count(*)统计所有行; count(字段)不统计null值.
-- SUM(列名):统计满足条件的行的内容和
-- 统计一个班级JS总成绩?先查出所有的JS成绩,再用sum包上
select JS as JS总成绩 from ExamResult;
select sum(JS) as JS总成绩 from ExamResult;
-- 统计一个班级各科分别的总成绩
select sum(JS) as JS总成绩,
sum(Django) as Django总成绩,
sum(Database) as Database总成绩 from ExamResult;
-- 统计一个班级各科的成绩总和
select sum(ifnull(JS,0)+ifnull(Django,0)+ifnull(Database,0))
as 总成绩 from ExamResult;
-- 统计一个班级JS成绩平均分
select sum(JS)/count(*) from ExamResult ;
-- 注意:sum仅对数值起作用,否则会报错。
-- AVG(列名):
-- 求一个班级JS平均分?先查出所有的JS分,然后用avg包上。
select avg(ifnull(JS,0)) from ExamResult;
-- 求一个班级总分平均分
select avg((ifnull(JS,0)+ifnull(Django,0)+ifnull(Database,0)))
from ExamResult ;
-- Max、Min
-- 求班级最高分和最低分(数值范围在统计中特别有用)
select Max((ifnull(JS,0)+ifnull(Django,0)+ifnull(Database,0)))
最高分 from ExamResult;
select Min((ifnull(JS,0)+ifnull(Django,0)+ifnull(Database,0)))
最低分 from ExamResult;
-- 注意:null 和所有的数计算都是null,所以需要用ifnull将null转换为0!
-- -----ifnull(JS,0)
-- with rollup的使用
--<2> 统计分组后的组记录
-- (7) 重点:Select from where group by having order by
-- Mysql在执行sql语句时的执行顺序:from where select group by having order by
-- 分析:
select JS as JS成绩 from ExamResult where JS成绩 >70; ---- 不成功
select JS as JS成绩 from ExamResult having JS成绩 >90; --- 成功
select JS as JS成绩 from ExamResult group by JS成绩 having JS成绩 >80; ----成功
select JS as JS成绩 from ExamResult order by JS成绩;----成功
select * from ExamResult as 成绩 where 成绩.JS>85; ---- 成功
-- (8) limit
SELECT * from ExamResult limit 1;
SELECT * from ExamResult limit 1,5;
外键约束
创建外键
--- 每一个班主任会对应多个学生 , 而每个学生只能对应一个班主任
--- 主表
CREATE TABLE ClassCharger(
id TINYINT PRIMARY KEY auto_increment,
name VARCHAR (20),
age INT ,
is_marriged boolean -- show create table ClassCharger: tinyint(1)
);
INSERT INTO ClassCharger (name,age,is_marriged) VALUES ("冰冰",12,0),
("丹丹",14,0),
("歪歪",22,0),
("姗姗",20,0),
("小雨",21,0);
--- 子表
CREATE TABLE Student(
id INT PRIMARY KEY auto_increment,
name VARCHAR (20),
charger_id TINYINT, --切记:作为外键一定要和关联主键的数据类型保持一致
-- [ADD CONSTRAINT charger_fk_stu]FOREIGN KEY (charger_id) REFERENCES ClassCharger(id)
) ENGINE=INNODB;
INSERT INTO Student(name,charger_id) VALUES ("alvin1",2),
("alvin2",4),
("alvin3",1),
("alvin4",3),
("alvin5",1),
("alvin6",3),
("alvin7",2);
DELETE FROM ClassCharger WHERE name="冰冰";
INSERT student (name,charger_id) VALUES ("yuan",1);
-- 删除居然成功,可是 alvin3显示还是有班主任id=1的冰冰的;
-----------增加外键和删除外键---------
ALTER TABLE student ADD CONSTRAINT abc
FOREIGN KEY(charger_id)
REFERENCES classcharger(id);
ALTER TABLE student DROP FOREIGN KEY abc;
innodb支持的on语句
--外键约束对子表的含义: 如果在父表中找不到候选键,则不允许在子表上进行insert/update
--外键约束对父表的含义: 在父表上进行update/delete以更新或删除在子表中有一条或多条对
-- 应匹配行的候选键时,父表的行为取决于:在定义子表的外键时指定的
-- on update/on delete子句
-----------------innodb支持的四种方式---------------------------------------
-----cascade方式 在父表上update/delete记录时,同步update/delete掉子表的匹配记录
-----外键的级联删除:如果父表中的记录被删除,则子表中对应的记录自动被删除--------
FOREIGN KEY (charger_id) REFERENCES ClassCharger(id)
ON DELETE CASCADE
------set null方式 在父表上update/delete记录时,将子表上匹配记录的列设为null
-- 要注意子表的外键列不能为not null
FOREIGN KEY (charger_id) REFERENCES ClassCharger(id)
ON DELETE SET NULL
------Restrict方式 :拒绝对父表进行删除更新操作(了解)
------No action方式 在mysql中同Restrict,如果子表中有匹配的记录,则不允许对父表对应候选键
-- 进行update/delete操作(了解)
多表查询
-- 准备两张表
-- company.employee
-- company.department
create table employee(
emp_id int auto_increment primary key not null,
emp_name varchar(50),
age int,
dept_id int
);
insert into employee(emp_name,age,dept_id) values
('A',19,200),
('B',26,201),
('C',30,201),
('D',24,202),
('E',20,200),
('F',38,204);
create table department(
dept_id int,
dept_name varchar(100)
);
insert into department values
(200,'人事部'),
(201,'技术部'),
(202,'销售部'),
(203,'财政部');
mysql> select * from employee;
+--------+----------+------+---------+
| emp_id | emp_name | age | dept_id |
+--------+----------+------+---------+
| 1 | A | 19 | 200 |
| 2 | B | 26 | 201 |
| 3 | C | 30 | 201 |
| 4 | D | 24 | 202 |
| 5 | E | 20 | 200 |
| 6 | F | 38 | 204 |
+--------+----------+------+---------+
rows in set (0.00 sec)
mysql> select * from department;
+---------+-----------+
| dept_id | dept_name |
+---------+-----------+
| 200 | 人事部 |
| 201 | 技术部 |
| 202 | 销售部 |
| 203 | 财政部 |
+---------+-----------+
rows in set (0.01 sec)
多表查询之连接查询
1.笛卡尔积查询
mysql> SELECT * FROM employee,department; -- select employee.emp_id,employee.emp_name,employee.age, -- department.dept_name from employee,department; +--------+----------+------+---------+---------+-----------+ | emp_id | emp_name | age | dept_id | dept_id | dept_name | +--------+----------+------+---------+---------+-----------+ | 1 | A | 19 | 200 | 200 | 人事部 | | 1 | A | 19 | 200 | 201 | 技术部 | | 1 | A | 19 | 200 | 202 | 销售部 | | 1 | A | 19 | 200 | 203 | 财政部 | | 2 | B | 26 | 201 | 200 | 人事部 | | 2 | B | 26 | 201 | 201 | 技术部 | | 2 | B | 26 | 201 | 202 | 销售部 | | 2 | B | 26 | 201 | 203 | 财政部 | | 3 | C | 30 | 201 | 200 | 人事部 | | 3 | C | 30 | 201 | 201 | 技术部 | | 3 | C | 30 | 201 | 202 | 销售部 | | 3 | C | 30 | 201 | 203 | 财政部 | | 4 | D | 24 | 202 | 200 | 人事部 | | 4 | D | 24 | 202 | 201 | 技术部 | | 4 | D | 24 | 202 | 202 | 销售部 | | 4 | D | 24 | 202 | 203 | 财政部 | | 5 | E | 20 | 200 | 200 | 人事部 | | 5 | E | 20 | 200 | 201 | 技术部 | | 5 | E | 20 | 200 | 202 | 销售部 | | 5 | E | 20 | 200 | 203 | 财政部 | | 6 | F | 38 | 204 | 200 | 人事部 | | 6 | F | 38 | 204 | 201 | 技术部 | | 6 | F | 38 | 204 | 202 | 销售部 | | 6 | F | 38 | 204 | 203 | 财政部 | +--------+----------+------+---------+---------+-----------+
2.内连接
-- 查询两张表中都有的关联数据,相当于利用条件从笛卡尔积结果中筛选出了正确的结果。
select * from employee,department where employee.dept_id = department.dept_id;
--select * from employee inner join department on employee.dept_id = department.dept_id;
+--------+----------+------+---------+---------+-----------+
| emp_id | emp_name | age | dept_id | dept_id | dept_name |
+--------+----------+------+---------+---------+-----------+
| 1 | A | 19 | 200 | 200 | 人事部 |
| 2 | B | 26 | 201 | 201 | 技术部 |
| 3 | C | 30 | 201 | 201 | 技术部 |
| 4 | D | 24 | 202 | 202 | 销售部 |
| 5 | E | 20 | 200 | 200 | 人事部 |
+--------+----------+------+---------+---------+-----------+
3.外链接
--(1)左外连接:在内连接的基础上增加左边有右边没有的结果
select * from employee left join department on employee.dept_id = department.dept_id;
+--------+----------+------+---------+---------+-----------+
| emp_id | emp_name | age | dept_id | dept_id | dept_name |
+--------+----------+------+---------+---------+-----------+
| 1 | A | 19 | 200 | 200 | 人事部 |
| 5 | E | 20 | 200 | 200 | 人事部 |
| 2 | B | 26 | 201 | 201 | 技术部 |
| 3 | C | 30 | 201 | 201 | 技术部 |
| 4 | D | 24 | 202 | 202 | 销售部 |
| 6 | F | 38 | 204 | NULL | NULL |
+--------+----------+------+---------+---------+-----------+
--(2)右外连接:在内连接的基础上增加右边有左边没有的结果
select * from employee RIGHT JOIN department on employee.dept_id = department.dept_id;
+--------+----------+------+---------+---------+-----------+
| emp_id | emp_name | age | dept_id | dept_id | dept_name |
+--------+----------+------+---------+---------+-----------+
| 1 | A | 19 | 200 | 200 | 人事部 |
| 2 | B | 26 | 201 | 201 | 技术部 |
| 3 | C | 30 | 201 | 201 | 技术部 |
| 4 | D | 24 | 202 | 202 | 销售部 |
| 5 | E | 20 | 200 | 200 | 人事部 |
| NULL | NULL | NULL | NULL | 203 | 财政部 |
+--------+----------+------+---------+---------+-----------+
--(3)全外连接:在内连接的基础上增加左边有右边没有的和右边有左边没有的结果
-- mysql不支持全外连接 full JOIN
-- mysql可以使用此种方式间接实现全外连接
select * from employee RIGHT JOIN department on employee.dept_id = department.dept_id
UNION
select * from employee LEFT JOIN department on employee.dept_id = department.dept_id;
+--------+----------+------+---------+---------+-----------+
| emp_id | emp_name | age | dept_id | dept_id | dept_name |
+--------+----------+------+---------+---------+-----------+
| 1 | A | 19 | 200 | 200 | 人事部 |
| 2 | B | 26 | 201 | 201 | 技术部 |
| 3 | C | 30 | 201 | 201 | 技术部 |
| 4 | D | 24 | 202 | 202 | 销售部 |
| 5 | E | 20 | 200 | 200 | 人事部 |
| NULL | NULL | NULL | NULL | 203 | 财政部 |
| 6 | F | 38 | 204 | NULL | NULL |
+--------+----------+------+---------+---------+-----------+
-- 注意 union与union all的区别:union会去掉相同的纪录
多表查询之复合条件链接查询
-- 查询员工年龄大于等于25岁的部门
SELECT DISTINCT department.dept_name
FROM employee,department
WHERE employee.dept_id = department.dept_id
AND age>25;
--以内连接的方式查询employee和department表,并且以age字段的升序方式显示
select employee.emp_id,employee.emp_name,employee.age,department.dept_name
from employee,department
where employee.dept_id = department.dept_id
order by age asc;
多表查询之子查询
-- 子查询是将一个查询语句嵌套在另一个查询语句中。
-- 内层查询语句的查询结果,可以为外层查询语句提供查询条件。
-- 子查询中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等关键字
-- 还可以包含比较运算符:= 、 !=、> 、<等
-- 1. 带IN关键字的子查询
---查询employee表,但dept_id必须在department表中出现过
select * from employee
where dept_id IN
(select dept_id from department);
+--------+----------+------+---------+
| emp_id | emp_name | age | dept_id |
+--------+----------+------+---------+
| 1 | A | 19 | 200 |
| 2 | B | 26 | 201 |
| 3 | C | 30 | 201 |
| 4 | D | 24 | 202 |
| 5 | E | 20 | 200 |
+--------+----------+------+---------+
rows in set (0.01 sec)
-- 2. 带比较运算符的子查询
-- =、!=、>、>=、<、<=、<>
-- 查询员工年龄大于等于25岁的部门
select dept_id,dept_name from department
where dept_id IN
(select DISTINCT dept_id from employee where age>=25);
-- 3. 带EXISTS关键字的子查询
-- EXISTS关字键字表示存在。在使用EXISTS关键字时,内层查询语句不返回查询的记录。
-- 而是返回一个真假值。Ture或False
-- 当返回Ture时,外层查询语句将进行查询;当返回值为False时,外层查询语句不进行查询
select * from employee
WHERE EXISTS
(SELECT dept_name from department where dept_id=203);
--department表中存在dept_id=203,Ture
select * from employee
WHERE EXISTS
(SELECT dept_name from department where dept_id=205);
-- Empty set (0.00 sec)
ps: create table t1(select * from t2);



浙公网安备 33010602011771号