My SQL数据库
一、数据库的基础知识
1.数据库
数据库(database)就是一个存储和管理数据的仓库。为了方便数据的存储和管理,它将数据按照特定的规律存储在磁盘上。通过数据库管理系统,可以有效地组织和管理存储在数据库中的数据。是一个长期存储在计算机内的、有 组织的、有共享的、统一管理的数据集合。
2.数据库的五个基本概念
数据库服务器、数据库、数据表、数据字段、数据行
1.数据库服务器
是指用来运行数据库服务的一台电脑。小型项目通常为一台,中大型项目通常是多台数据库服务器共同来存储或计算。由于数据安全非常重要,所以我们需要对数据库服务器里边的数据进行备份管理。
2.数据库
一个数据库服务器里面可以有多个数据库。主要用来分类使用。我们可以建立学员管理系统数据库、电子商城数据库、CRM数据库、ERP数据库等等,主要用来将各个不同用途的数据,按照业务进行划分。
3.数据表
例如,在学员管理系统中。根据业务的不同又分为了不同的数据表。专门用来存放不同人员的数据。例如:学员数据表(学号、用户名、密码);老师数据表(用户名、密码、工作经验)
4.数据字段(数据列)
就是我们日常所见表格里面的列。在表格中,我们会将一张用户表分成多个列。如:用户编号、用户名、性别、年龄等是字段,在真正的数据库中数据字段需换成英文,需要写成:id,username,sex,age等。
5.数据行
真正的数据存在在每一个表的行里面。字段(列)划分出来了一个表应该按照什么样的格式存数据。而行,是真正的数据。每一行需要遵循数据字段(列)的规范和要求进行存入数据。
3.数据库的分类
关系型数据库
就是使用二维表格(Table)的方式来存放数据的数据库,多表间建 立关联关系,通过分类、合并、连接、选取等运算实现访问。
数据库中的数据都是项目中的数据,所以数据库中的数据表示的就是Java对象
那么关系型数据库这个二维表格,每一个表格就相当于一个Java类,表头就表示Java类的属性,从第二行开始,每一个行表示一个Java对象
常见的关系型数据库:MySQL、Oracle、Microsoft SQL Server、IBM Db 2等,最常用的是MySQL。
非关系型数据库
常见的非关系型数据库:Redis 、MongoDB 、ElastecSearch等。多数使用哈希表,表中以键值(keyvalue)的方式实现特定的键和一个指针指向的特定数据。
网状结构数据库
美国通用电气公司IDS(Integrated Data Store),以节点形式存储和访问。
层次结构数据库
IBM公司IMS(Information Management System)定向有序的树状结构 实现存储和访问。
4.数据库管理系统
1.概念
数据库管理系统(DataBase Management System,DBMS):指一种操作和管理数据库的大型软件,用于建立、使用和维护数据库,对数据库进行统一管理和控制,以保证数据库的安全性和完整性。用户通过数据库管理系统访问数据库中的数据。
2.常见数据库管理系统
Oracle:被认为是业界目前比较成功的关系型数据库管理系统。Oracle数据库可以运行在 UNIX、Windows等主流操作系统平台,完全支持所有的工业标准,并获得最高级别的ISO标 准安全性认证。
DB2:IBM公司的产品,DB2数据库系统采用多进程多线索体系结构,其功能足以满足大中 公司的需要,并可灵活地服务于中小型电子商务解决方案。
SQL Server:Microsoft 公司推出的关系型数据库管理系统。具有使用方便可伸缩性好与相 关软件集成程度高等优点。
SQLLite:应用在手机端的数据库。
5.MySQL
MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。 MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面MySQL是最好的 RDBMS(Relational Database Management System,关系数据库管理系统) 应用软件之一。
My SQL是一款完全免费的产品,用户可以直接从网上下载使用,而不必支付任何费用。此外,My SQL数据库的跨平台性也是其一个很大的优势之一;My SQL是一个真正的多用户、多线程SQL数据库服务器。它是以客户机/服务器结构实现的,由一个服务器守护程序以及很多不同的客户程序和库组成。
MySQL 5.5融合了MySQL数据库和InnoDB存储引擎的优点,能够提供高性能的数据管理解决方案,包括:
InnoDB作为默认的数据库存储引擎;
改善性能和可扩展性,全面利用各平台现代、多核构架的计算能力;
提高实用性;
提高易管理性和效率;
提高可用性。
官方下载地址:
http://dev.mysql.com/downloads/mysql/
安装MySQL注意事项:
双击即可,大部分都是一路next
关键节点注意事项:
-
选中“Typical”,典型安装模式
-
选中“Detailed Configuration”(详细配置)单选按钮
-
选中“Developer Machine”(开发者机器)单选按钮
-
选中“Multifunctional Database”(多功能数据库)单选按钮
-
服务端口3306,不建议更改
-
字符集注意要选“Manual Selected Default Character Set/Collation”单选按钮,设置字符集编码为utf8
-
设置密码尽量简单,注意不要忘了
用户名:root 密码:root
卸载MySQL
控制台卸载。
找到mysql的安装目录进行删除。
programdata 删除mysql
注意:如果卸载后,如有未删除的MySQL服务,可采用手动删除。
以管理员身份打开命令行,输入 sc delete MySQL5.7 + 回车。
配置环境变量
Windows
创建MYSQL_HOME:C:\Program Files\MySQL\MySQL Server 5.7
追加PATH:%MYSQL_HOME%\bin;
MacOS / Linux
终端中输入cd ~ 进入目录,并检查.bash_profile是否存在,有则追加,无则 创建
创建文件 touch .bash_profile
打开文件 open .bash_profile
输入export PATH=${PATH}:/usr/local/mysql/bin 保存并退出终端
MySQL目录结构
核心文件介绍
文件名称 | 内容 |
---|---|
bin | 命令文件 |
lib | 库文件 |
include | 头文件 |
Share | 字符集、语言等信息 |
MySQL配置文件
在MySQL安装目录中找到my.ini文件,并打开my.ini文件查看几个常用配置参数
参数 | 描述 |
---|---|
default-character-set | 客户端默认字符集 |
character-set-server | 服务器端默认字符集 |
port | 客户端和服务器端的端口号 |
default-storage-engine | MySQL默认存储引擎 INNODB |
启动MySQL
在命令提示符(cmd)页面我们cd到MySQL的bin目录下,就可通过命令启动或停止MySQL。命令如下:
启动mysql: net start mysql
关闭mysql: net stop mysql
登录mysql: mysql -u root -p (-u : username,-p : password)
6.数据库客户端工具
1.Navicate
Navicat是一套快速、可靠并价格相宜的数据库管理工具,专为简化数据库的管理及降低系统管理 成本而设。它的设计符合数据库管理员、开发人员及中小企业的需要。Navicat 是以直觉化的图形 用户界面而建的,让你可以以安全并且简单的方式创建、组织、访问并共用信息。
2.SQLyog(小海豚)
MySQL可能是世界上最流行的开源数据库引擎,但是使用基于文本的工具和配置文件可能很难进 行管理。SQLyog提供了完整的图形界面,即使初学者也可以轻松使用MySQL的强大功能。其拥有 广泛的预定义工具和查询、友好的视觉界面、类似 Excel 的查询结果编辑界面等优点。
二、SQL分类
数据定义语言(DDL ,Data Definition Language)语句:数据定义语句,用于定义不同的数据对象、数据库、表、列、索引等。常用的语句关键字包括create、drop、alter等。
数据操作语言(DML , Data Manipulation Language)语句:数据操纵语句,用于添加、删除、更新和查询数据库记录,并检查数据的完整性。常用的语句关键字主要包括insert、delete、update和select等。(DML:添加,修改,删除,DQL:查询)。
数据控制语言(DCL, Data Control Language)语句:数据控制语句,用于控制不同数据段直接的许可和访问级别的语句。这些语句定义了数据库、表、字段、用户的访问权限和安全级别。主要的语句关键字包括grant、revoke等。
1.数据定义语言 - DDL
对于库的操作
对于库的操作 | 代码 |
---|---|
遍历数据库 | SHOW DATABASES |
使用数据库 | USER 数据库名 |
创建数据库 | CREATE DATABASE 数据库名 |
删除数据库 | DROP DATABASE 数据库名 |
对于表的操作
对于表的操作 | 代码 |
---|---|
遍历表 | SHOW TABLES; |
创建表 | CREATE TABLE 表名(字段 类型,…字段 类型); |
修改表名 | ALTER TABLE 旧表名 RENAME 新表名; |
删除表 | DROP TABLE 表名; |
获取表信息 | DESC 表名; |
对于字段的操作
对于字段的操作 | 代码 |
---|---|
添加字段 | ALTER TABLE 表名 ADD 字段 类型; |
删除字段 | ALTER TABLE 表名 DROP 字段 类型; |
修改字段名 | ALTER TABLE 表名 CHANGE 旧字段 新字段; |
修改字段类型 | ALTER TABLE 表名 MODIFY 字段 类型; |
查询所有字段信息 | DESC 表名; |
查询创建表信息 | SHOW CREATE TABLE 表名; |
代码演示
#查询所有数据库
SHOW DATABASES;
#创建数据库
CREATE DATABASE 2104javaee;
#使用数据库
USE 2104javaee;
#查询该数据库中所有的表
SHOW TABLES;
#删除数据库
DROP DATABASE 2104javaee;
#创建表
CREATE TABLE db_student(
s_id INT(3),
s_name VARCHAR(32),
s_sex CHAR(3),
s_salary FLOAT(8,2)
)
#获取表信息
DESC db_student;
#获取创建表信息
SHOW CREATE TABLE db_student;
#修改表名
ALTER TABLE db_student RENAME student;
#删除表
DROP TABLE student;
#创建表
CREATE TABLE student(
s_id INT(3),
s_name VARCHAR(32),
s_sex CHAR(3),
s_salary FLOAT(8,2)
)
#修改字段类型
ALTER TABLE student MODIFY s_sex char(1);
#获取表信息
DESC student;
#添加字段
ALTER TABLE student ADD course VARCHAR(32);
#删除字段
ALTER TABLE student DROP course;
#修改字段名+类型
ALTER TABLE student CHANGE s_id id INT(3);
ALTER TABLE student CHANGE s_name name VARCHAR(20);
ALTER TABLE student CHANGE s_sex sex char(1);
ALTER TABLE student CHANGE s_salary salary FLOAT(8,2);
#获取表信息
DESC student;
2.数据操作语言 - DML
对数据的添加、修改、删除 | 代码 |
---|---|
插入数据(不指定字段) | INSERT INTO 表名 VALUES(值1,值2,值n); |
插入数据(指定字段,推荐使用) | INSERT INTO 表名(字段1,字段2,字段n) VALUES(值1,值2,值n); |
更新数据(该字段上所有的数据都更改) | UPDATE 表名 SET 字段=值; |
更新数据(更改单个字段上的数据+单个条件) | UPDATE 表名 SET 字段=值 WHERE 条件; |
更新数据(更改单个字段上的数据+多个条件) | UPDATE 表名 SET 字段=值 WHERE 条件 AND 条件; |
更新数据(更改单个字段上的数据+多个条件) | UPDATE 表名 SET 字段=值 WHERE 条件 OR 条件; |
更新数据(更改多个字段上的数据+单个条件) | UPDATE 表名 SET 字段=值,…,字段=值 WHERE 条件; |
更新数据(更改多个字段上的数据+多个条件) | UPDATE 表名 SET 字段=值,…,字段=值 WHERE 条件 AND 条件; |
更新数据(更改多个字段上的数据+多个条件) | UPDATE 表名 SET 字段=值,…,字段=值 WHERE 条件 OR 条件; |
删除所有数据(不建议使用,清空数据后再添加数据id从1开始) | TRUNCATE TABLE 表名; |
删除所有数据 | DELETE FROM 表名; |
删除数据+条件 | DELETE FROM 表名 WHERE 条件; |
补:两种清空表的优缺点
DELETE FROM 表名;
#效果:删除表中的所有记录
#缺点:本身是将数据一行一行的删除,所以如果数据量比较大,删除的效率就很低
TRUNCATE TABLE 表名;
#效果:删除表中的所有记录
#删除效率较高,实现方式是:将该表直接删除,然后创建一个同名的表
3.数据查询语言 - DQL(重点)
对数据的查询 | 代码 |
---|---|
查询所有数据 | SELECT * FROM 表名; |
查询指定字段上的数据 | SELECT 字段,字段 FROM 表名; |
查询指定字段上的数据+别名 | SELECT 字段 AS ‘别名’ FROM 表名; |
查询指定字段上的数据+去重 | SELECT DISTINCT 字段 FROM 表名; |
查询指定字段上的数据+条件 | SELECT * FROM 表名 WHERE 条件 AND 条件; SELECT * FROM 表名 WHERE 条件 OR 条件; SELECT * FROM 表名 WHERE 条件 NOT 条件; 使用算数运算符来作为条件:> >= < <= = != … |
查询指定字段上的数据是否为NULL | SELECT * FROM 表名 WHERE 字段 IS NULL; SELECT * FROM 表名 WHERE 字段 IS NOT NULL; |
查询指定字段是否在指定范围中 | SELECT * FROM 表名 WHERE 字段 BETWEEN 最小值 AND 最大值; |
枚举查询:查询指定字段的值是否属于指定的集合 | SELECT * FROM 表名 WHERE 字段 IN(值1,值2,值n); 效果:字段的值与in后面的集合中某一个值相等,则条件成立 |
模糊查询(like): %表示不确定多少个字符 _表示一个字符 []表示匹配[]中的任意一个字符 [^]表示不匹配[]中的任意一个字符 | SELECT * FROM 表名 WHERE 字段 LIKE ‘%内容%’; SELECT * FROM 表名 WHERE 字段 LIKE ‘_内容’; |
查询数据+排序 ASC:升序(默认) DESC:降序 | SELECT * FROM 表名 ORDER BY 字段 ASC; SELECT * FROM 表名 ORDER BY 字段 DESC; |
查询数据+多字段排序 | SELECT * FROM 表名 ORDER BY 字段 DESC,字段 ASC; |
限制查询(限制查询出结果的条数) | SELECT * FROM LIMIT 数量; |
限制查询 + 排序 | SELECT * FROM 表名 ORDER BY 排序关键字 DESC/ASC LIMIT 数量; 注意:先排序再限制 |
分页查询 | SELECT * FROM 表名 LIMIT 偏移量,数量; *分页公式:SELECT * FROM student LIMIT ((页数-1)获取条数,获取条数) |
聚合查询 | 求总和SUM :SELECT SUM(字段) FROM 表名; 统计总数COUNT(主键):SELECT COUNT(字段) FROM 表名; 求最大值MAX :SELECT MAX(字段) FROM 表名; 求最小值MIN :SELECT MIN(字段) FROM 表名; 求平均值AVG :SELECT AVG(字段) FROM 表名; |
子查询 | SELECT * FROM 表名 WHERE 字段=(子查询语句); 注意:子查询出的结果再复制给前面的sql语句 |
分组查询 | SELECT 字段,AVG(字段) FROM 表名 GROUP BY 字段; |
分组查询+条件 | SELECT 字段,AVG(字段) FROM 表名 GROUP BY 字段 HAVING 条件; |
三表联合查询 | SELECT * FROM t_employees e INNER JOIN t_departments d ON e.department_id = d.department_id INNER JOIN t_locations l ON d.location_id = l.location_id |
多表联合查询:内连接 | SELECT s.name,t.name FROM student s,teacher t WHERE s.t_id=t.id; SELECT s.name,t.name FROM student s INNER JOIN teacher t ON s.t_id=t.id; |
多表联合查询:自动连接(不建议使用) | SELECT s.name,t.name FROM student s NATURAL JOIN teacher t ; |
多表联合查询:左连接 | SELECT s.name,t.name FROM student s LEFT JOIN teacher t ON s.t_id=t.id; |
多表联合查询:右连接 左连接和右链接统称为外连接[OUTER] | SELECT s.name,t.name FROM student s RIGHT JOIN teacher t ON s.t_id=t.id; |
合并两个查询结果 | (SELECT s.name,t.name FROM student s LEFT JOIN teacher t ON s.t_id=t.id;) UNION ALL (SELECT s.name,t.name FROM student s RIGHT JOIN teacher t ON s.t_id=t.id;) |
全连接(并集,去重) | (SELECT s.name,t.name FROM student s LEFT JOIN teacher t ON s.t_id=t.id;) UNION (SELECT s.name,t.name FROM student s RIGHT JOIN teacher t ON s.t_id=t.id;) |
交集 | SELECT * FROM student WHERE age>21 AND id IN (SELECT id FROM student WHERE id<5); |
差集 | SELECT * FROM student WHERE age>21 AND NOT id IN (SELECT id FROM student WHERE id<5); |
代码演示
#创建表 + 主键 + 主键自动增长
#主键:不能重复并且不能为空(null)
#创建表,将id设为主键,且自动增长
#PRIMARY KEY:主键
#auto_increment:自动增长
CREATE TABLE student(
id INT(32) PRIMARY KEY auto_increment,
name VARCHAR(32),
sex VARCHAR(32),
age INT(3),
salary FLOAT(8,2),
course VARCHAR(32)
);
#插入数据
INSERT INTO student VALUES(1,'小舞','男',18,8000,'JAVA');
INSERT INTO student(name,sex,age,salary,course)VALUES('麻生希','女',29,13000,'JAVA');
INSERT INTO student(name,sex,age,salary,course) VALUES('刘德华','男',62,20000,'JAVA');
INSERT INTO student(name,sex,age,salary,course) VALUES('霍华德','男',36,6000,'HTML');
INSERT INTO student(name,sex,age,salary,course) VALUES('霍建华','男',38,9000,'HTML');
INSERT INTO student(name,sex,age,salary,course) VALUES('华晨宇','男',25,3500,'PYTHON');
INSERT INTO student(name,sex,age,salary,course) VALUES('水野朝阳','女',27,15000,'PYTHON');
INSERT INTO student(name,sex,age,salary,course) VALUES('欧阳正华','男',47,18000,'JAVA');
#修改数据(所有的年纪都改成50岁)
UPDATE student SET age=50;
#修改数据+条件
#需求:把刘德华的年龄改为50
UPDATE student SET age=50 WHERE id=3;
#修改数据 + 条件
#需求:把id大于5或者年龄大于30的学生的工资改成8000
UPDATE student SET salary=8000 WHERE id>5 OR age>30;
#修改数据 + 条件
#需求:把id大于5和者年龄大于30的学生的工资改成8000
UPDATE student SET salary=8000 WHERE id>5 AND age>30;
#删除数据(清空所有数据)
DELETE FROM student;
TRUNCATE TABLE student;#清空后,再添加时id从1开始(不推荐使用,因为恢复备份时会造成id冲突,从而数据恢复失败)
#删除数据+条件
#需求:把id为2的数据删除
DELETE FROM student WHERE id=2;
#查询所有字段
SELECT * FROM student;
#查询指定字段
SELECT name,age FROM student;
#查询指定字段+别名
SELECT name AS '姓名',age AS '年龄' FROM student;
#查询数据+条件
SELECT name FROM student WHERE age<28;
#查询数据+去重
SELECT DISTINCT course FROM student;
#判断字段的值是否为null
#不能使用=或者!=来进行判断
#应该使用IS NULL/IS NOT NULL来进行判断
#需求:查询student表中age字段值为null的记录
SELECT * FROM student WHERE age IS NULL;
#需求:查询student表中age字段值不为null的记录
SELECT * FROM student WHERE age IS NOT NULL;
#between...and...
#用来判断指定字段的指定是否在指定范围中
#需求:查询年龄在18与23之间的学生信息
SELECT * FROM student WHERE age BETWEEN 18 AND 23;
#in
#用来判断指定的字段的值是否属于指定的集合
#WHERE 字段名 in(值1,值2,值3....)
#效果:字段的值与in后面的集合中某一个值相等,则条件成立
#需求:查询student表中年龄为18岁以上25以下,并且年龄为奇数的学员信息
SELECT * FROM stu WHERE age BETWEEN 19 AND 24 AND age%2 = 1;
SELECT * FROM stu WHERE age in(19,21,23);
#模糊查询
#%表示不确定多少个字符
#_表示一个字符
#[]表示匹配[]中的任意一个字符
#[^]表示不匹配[]中的任意一个字符
#需求:查询姓名中带华字的数据
SELECT * FROM student WHERE name LIKE '%华%';
#需求:查询姓名中间带华字的数据
SELECT * FROM student WHERE name LIKE '_华_';
#需求:查询姓名中开头带华字的数据
SELECT * FROM student WHERE name LIKE '华%';
#需求:查询姓名中末尾带华字的数据
SELECT * FROM student WHERE name LIKE '%华';
#查询+排序
#ASC:表示升序(默认)
#DESC:表示降序
#需求:按照年龄排升序
SELECT * FROM student ORDER BY age;
SELECT * FROM student ORDER BY age ASC;
#需求:按照工资排降序
SELECT * FROM student ORDER BY salary DESC;
#多字段排序查找
#需求:年龄做升序,年龄相同工资做降序
SELECT * FROM student ORDER BY age ASC,salary DESC;
#限制查找
SELECT * FROM student LIMIT 3;
#分页
#分页公式:SELECT * FROM student LIMIT ((页数-1)*获取条数,获取条数)
#SELECT * FROM student LIMIT 偏移量,获取条数
#需求:分页查询,每一页展示3个信息
SELECT * FROM student LIMIT 0,3;#第1页
SELECT * FROM student LIMIT 3,3;#第2页
SELECT * FROM student LIMIT 6,3;#第3页
#需求:取这个班年龄最大的前三个人(思路:先排序再限制)
SELECT * FROM student ORDER BY age DESC LIMIT 3;
#聚合查询
#需求:工资总和
SELECT SUM(salary) FROM db_student;
#需求:求年龄的平均数
SELECT AVG(age) FROM db_student;
#需求:求最大年龄
SELECT MAX(age) FROM db_student;
#需求:求最小年龄
SELECT MIN(age) FROM db_student;
#需求:求学生的个数(count()如果值为null是不算进个数,所以字段一般选择主键即可)
SELECT COUNT(id) FROM db_student;
#子查询
#需求:查询最高工资的学生
SELECT * FROM db_student WHERE salary=(SELECT MAX(salary) FROM db_student);
#分组:分组过滤+条件
#需求:查询各个学科的平均工资,展示出>10000的学科
SELECT course,AVG(salary) FROM db_student GROUP BY course HAVING AVG(salary)>10000;
#多表联合查询
# 建立老师表(id、name)并添加数据
# 建立学生表(id、name、t_id)并添加数据
#内连接
SELECT s.name,t.name FROM student s,teacher t WHERE s.t_id=t.id;
SELECT s.name,t.name FROM student s INNER JOIN teacher t ON s.t_id=t.id;
#左连接
SELECT s.name,t.name FROM student s LEFT JOIN teacher t ON s.t_id=t.id;
#右链接
SELECT s.name,t.name FROM student s RIGHT JOIN teacher t ON s.t_id=t.id;
#查询合并
SELECT s.name,t.name FROM student s LEFT JOIN teacher t ON s.t_id=t.id
UNION ALL
SELECT s.name,t.name FROM student s RIGHT JOIN teacher t ON s.t_id=t.id;
# 全链接(查询到的重复结果给去掉)
SELECT s.name,t.name FROM student s LEFT JOIN teacher t ON s.t_id=t.id
UNION
SELECT s.name,t.name FROM student s RIGHT JOIN teacher t ON s.t_id=t.id;
4.事务处理语言 - TPL(重点)
1.模拟转账
生活当中转账是转账方账户扣钱,收账方账户加钱。我们用数据库操作来模拟现实转账。
1.1 数据库模拟转账
#A 账户转账给 B 账户 1000 元。
#A 账户减1000 元
UPDATE account SET MONEY = MONEY-1000 WHERE id=1;
#B 账户加 1000 元
UPDATE account SET MONEY = MONEY+1000 WHERE id=2;
上述代码完成了两个账户之间转账的操作。
1.2 模拟转账错误
#A 账户转账给 B 账户 1000 元。
#A 账户减1000 元
UPDATE account SET MONEY = MONEY-1000 WHERE id=1;
#断电、异常、出错...
#B 账户加 1000 元
UPDATE account SET MONEY = MONEY+1000 WHERE id=2;
上述代码在减操作后过程中出现了异常或加钱语句出错,会发现,减钱仍旧是成功的,而加钱失败了!
注意:每条 SQL 语句都是一个独立的操作,一个操作执行完对数据库是永久性的影响。
2.事务的概念
事务是一个原子操作。是一个最小执行单元。可以由一个或多个SQL语句组成,在同一个事务当中,所有的SQL语句都成功执行时,整个事务成功,有一个SQL语句执行失败,整个事务都执行失败。
3.事务的边界
- 开始:连接到数据库,执行一条DML语句。 上一个事务结束后,又输入了一条DML语句,即 事务的开始
- 结束:
- 提交:
- 显示提交:commit;
- 隐式提交:一条创建、删除的语句,正常退出(客户端退出连接);
- 回滚:
- 显示回滚:rollbcak;
- .隐式回滚:非正常退出(断电、宕机),执行了创建、删除的语句,但是失败了, 会为这个无效的语句执行回滚。
- 提交:
4.事务的原理
数据库会为每一个客户端都维护一个空间独立的缓存区(回滚段),一个事务中所有的增删改语句的 执行结果都会缓存在回滚段中,只有当事务中所有SQL 语句均正常结束(commit),才会将回 滚段中的数据同步到数据库。否则无论因为哪种原因失败,整个事务将回滚(rollback)。
5.事务的特性
- Atomicity(原子性):表示一个事务内的所有操作是一个整体,要么全部成功,要么全部失败。
- Consistency(一致性):表示一个事务内有一个操作失败时,所有的更改过的数据都必须回滚到修改前状态
- Isolation(隔离性):事务查看数据操作时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另 一事务修改它之后的状态,事务不会查看中间状态的数据。
- Durability(持久性):持久性事务完成之后,它对于系统的影响是永久性的。
6.用事务完成转账
#A 账户给 B 账户转账。
#1.开启事务
START TRANSACTION;
setAutoCommit=0;#禁止自动提交
setAutoCommit=1;#开启自动提交
#2.事务内数据操作语句
UPDATE ACCOUNT SET MONEY = MONEY-1000 WHERE ID = 1;
UPDATE ACCOUNT SET MONEY = MONEY+1000 WHERE ID = 2;
#3.事务内语句都成功了,执行 COMMIT;
COMMIT;
#4.事务内如果出现错误,执行 ROLLBACK;
ROLLBACK;
注意:开启事务后,执行的语句均属于当前事务,成功再执行 COMIIT,失败要进行 ROLLBACK.
5.数据控制语言 - DCL
含义
权限管理。给子账户开辟权限。
语法格式
功能 | 代码格式 |
---|---|
开辟子账户 | CREATE USER ‘用户名’@‘localhost’ IDENTIFIED BY ‘密码’; |
给定权限 | GRANT 权限 ON 库.表 TO ‘用户’@‘localhost’ IDENTIFIED BY ‘密码’; |
删除权限 | REVOKE 权限 ON 库.表 FROM ‘用户’@‘localhost’; |
注:权限:insert、delete、select、update
参数说明
符号 | 说明 |
---|---|
grant all | 在grant后接all说明给予所有权限 |
revoke all | 在revoke后接all说明删除所有权限 |
权限 on. | . 指明给予所有库所有表的操作权限 |
‘用户’@‘主机’ | 主机里面若为%。任意来源的主机均可以使用这个用户来访问 |
代码演示
#创建子账号并设置权限(前提是主账号登录后)
grant select,insert,updata,delete on 2104javaee.* to 'aaa'@'localhost' identified by '123';
#删除权限
revoke updata,delete on 2104javaee.* from 'aaa'@'localhost';
#解决编码问题(在黑窗口输入)
Set charset gbk;
三、数据类型
MySQL的数据类型主要分为四大类:
整数类型、浮点类型、字符串类型、日期类型。
1.整型
MySQL数据类型 | 所占字节 | 值范围 |
---|---|---|
tinyint | 1字节 | -128~127 |
smallint | 2字节 | -32768~32767 |
mediumint | 3字节 | -8388608~8388607 |
int | 4字节 | -2147483648~2147483647 |
bigint | 8字节 | ±9.22*10的18次方 |
补充:UNSIGNED(无符号)主要用于整型和浮点类型,使用无符号,即,没有前面面的-(负号)。存储位数更长。tinyint整型的取值区间为,-128~127。而使用无符号unsigned修饰后可存储0-255个长度。
2.浮点型
MySQL数据类型 | 所占字节 | 值范围 |
---|---|---|
float(m,d) | 4字节 | 单精度浮点型,m总个数,d小数位 |
double(m,d) | 8字节 | 双精度浮点型,m总个数,d小数位 |
decimal(m,d) | decimal是存储为字符串的浮点数 |
设一个字段定义为float(6,3),如果插入一个数123.45678,实际数据库里存的是123.457,但总个数还以实际为准,即6位。整数部分最大是3位,如果插入数12.123456,存储的是12.1234,如果插入12.12,存储的是12.1200.所以浮点型float和double都有可能失去精度。所以我们常用不会失精的decimal。
重点:定点数(decimal):浮点型在数据库中存放的是近似值,而定点数在数据库中存放的是精确值。decimal(m,d) 参数m<65 是总个数,d<30且 d<m 是小数位。
3.字符类型
MySQL数据类型 | 所占字节 | 值范围 |
---|---|---|
char | 0-255字节 | 定长字符串 |
varchar | 0-255字节 | 变长字符串 |
tinyblob | 0-255字节 | 不超过255个字符的二进制字符串 |
tinytext | 0-255字节 | 短文本字符串 |
blob | 0-65535字节 | 二进制形式的长文本数据 |
text | 0-65535字节 | 长文本数据 |
mediumblob | 0-16 777 215字节 | 二进制形式的中等长度文本数据 |
mediumtext | 0-16 777 215字节 | 中等长度文本数据 |
longblob | 0-4 294 967 295字节 | 二进制形式的极大文本数据 |
longtext | 0-4 294 967 295字节 | 极大文本数据 |
varbinary(m) | 允许长度0-M个字节的定长字节符串 | 值的长度+1个字节 |
binary(m) | m | 允许长度0-M个字节的定长字节符串 |
char和varchar的区别:
-
char表示定长字符串。 指定长度后,占用的空间就一定是这个长度。适合用来存放固定长度的值;
varchar表示可变长字符串。根据实际存到值,占用对应的空间大小,但是需要使用一个单独的空间来记录实际的长度。
-
char(n) 若存入字符数小于n,则以空格补于其后,查询之时再将空格去掉。所以char类型存储的字符串末尾不能有空格,varchar不限于此。
-
char(n) 固定长度,char(4)不管是存入几个字符,都将占用4个字节,varchar是存入的实际字符数+1个字节(n<=255)或2个字节(n>255),
所以varchar(4),存入3个字符将占用4个字节。
- char类型的字符串检索速度要比varchar类型的快。
-
varchar和text的区别:
1. varchar可指定n,text不能指定,内部存储varchar是存入的实际字符数+1个字节(n<=255)或2个字节(n>255),text是实际字符数+2个字节。
2. text类型不能有默认值。
3. varchar可直接创建索引,text创建索引要指定前多少个字符。varchar查询速度快于text,在都创建索引的情况下,text的索引似乎不起作用。
blob和text的区别:
1. BLOB和TEXT存储方式不同,TEXT以文本方式存储,英文存储区分大小写,而Blob是以二进制方式存储,不分大小写。
2. BLOB存储的数据只能整体读出。
3. TEXT可以指定字符集,BLOB不用指定字符集。
4.日期类型
MySQL数据类型 | 所占字节 | 含义和格式 |
---|---|---|
date | 3字节 | 日期,格式:2020-05-31 |
time | 3字节 | 时间,格式:13:14:52 |
datetime | 8字节 | 日期时间,格式:2021-05-31 13:14:52 |
timestamp | 4字节 | 自动存储记录修改的时间,格式:2021-05-31 |
year | 1字节 | 年份,格式:2021 |
**注意:**时间类型在web系统中用的比较少,很多时候很多人喜欢使用int来存储时间。插入时插入的是unix时间戳,因为这种方式更方便计算。在前端业务中用date类型的函数,再将unix时间戳转成人们可识别的时间。
补充:常见数据类型的属性
MySQL关键字 | 含义 |
---|---|
null | 数据列可包含null值 |
not null | 数据列不允许包含null值 |
default | 默认值 |
primary key | 主键 |
auto_increment | 自动递增,适用于整数类型 |
unsigned | 无符号 |
character set name | 指定一个字符集 |
四、约束
1.含义
约束(constraint)是一种限制,它通过对表的行或列的数据作出限制,来确保表的数据的完整性、唯一性。约束其实就是给表的字段添加限制。
2.实体完整新约束
表中的一行数据代表一个实体(entity),实体完整性的作用即是标识每一行数据不重复、实体唯 一。
1.主键约束:primary key
主键约束 = 唯一约束 + 非空约束
理解:数据库表对应Java类,表中的每一行记录对应Java对象;
那么一个Java对象应该有一个唯一 标识;
那没每一行记录应该有一个字段值,这个字段值不能为空,不能重复,这个字段就被成为主键;
一个表必须有主键
格式:
CREATE TABLE 表名(
字段名 类型 PRIMARY KEY,
...
)
ALTER TABLE 表名 DROP PRIMARY KEY
示例:
#创建product产品表
CREATE TABLE product(
pid INT PRIMARY KEY,
pname VARCHAR(50)
);
#给表中插入数据
INSERT INTO product VALUES(NULL,"huaweip40");#会报错,因为主键不能为null
INSERT INTO product VALUES(1,"iphone12");
INSERT INTO product VALUES(1,"iphone13");#会报错,因为作为主键的pid不能重复
#删除主键
ALTER TABLE product DROP PRIMARY KEY;
2.主键自增长(自动增长列):auto_increment
当主键的类型是整数时,可以为主键添加自增长约束
我们如果没有为该主键赋值,主键不再是默认的NULL
而是默认从1开始自己赋值,每添加一条数据的主键值都是在上一条添加的数据的主键值基础上**+1**
格式:
CREATE TABLE 表名(
字段名 类型 PRIMARY KEY AUTO_INCREMENT,
...
)
示例:
CREATE TABLE category(
cid INT PRIMARY KEY AUTO_INCREMENT,
cname VARCHAR(50)
);
INSERT INTO category VALUES(NULL, "手机");
INSERT INTO category VALUES(NULL, "电脑");
SELECT * FROM category;# 效果是:正常执行 并且 主键有值了
3.唯一约束:unique
顾名思义,添加了唯一约束的字段值不能重复。
格式:
CREATE TABLE 表名(
字段名 类型 UNIQUE,
...
)
ALTER TABLE 表名 ADD UNIQUE(字段名)
ALTER TABLE 表名 DROP INDEX 字段名
示例:
#添加唯一约束
ALTER TABLE product ADD UNIQUE(pname);
#删除唯一约束
ALTER TABLE product DROP INDEX pname;
3.域完整性约束
限制列的单元格的数据正确性。
1.非空约束:not null
顾名思义,非空约束的字段值不能为空
格式:
CREATE TABLE 表名(
字段名 类型 NOT NULL,
...
)
示例:
#添加非空约束 和 默认值
ALTER TABLE user MODIFY password VARCHAR(32) NOT NULL DEFAULT '000000';
#删除非空约束 和 默认值
ALTER TABLE user MODIFY password VARCHAR(32);
2.默认值约束:default
如果一个字段添加了默认值约束,则如果没有给该字段赋值,该字段就使用默认值。
格式:
CREATE TABLE 表名(
字段名 类型 DEFAULT 值,
...
)
综合示例:
CREATE TABLE car(
cid INT PRIMARY KEY AUTO_INCAREMENY,
cname VARCHAR(50) NOT NULL,
brand VARCHAR(50) UNIQUE,
price DECIMAL(5,2) DEFAULT 20.50
);
#插入数据
# 会出错 因为cname字段有非空约束,不能为null
INSERT INTO car(cname, brand) VALUES(NULL, "BMW");
# 不会出错 price没有主动赋值,应该是默认值 20.5
INSERT INTO car(cname, brand) VALUES("m5", "BMW");
# 会出错 因为brend字段有唯一约束,不能重复
INSERT INTO car(cname, brand) VALUES("m5", "BMW");
3.外键约束(引用完整新约束):foreign key
本表跟外部表的关联约束。要想实现表与表之间的关联,就需要添加外键约束,为了避免bug,建议给主键添加外键约束,就可以避免重复导致的关联失效。一般不用外键,效率极低。
格式:
CREATE TABLE 表名(
字段 类型,
...
CONSTRAINT 外键名称 FOREIGN KEY(字段名称) REFERENCES 引用的表名(引用的主键名),
...
)
ALTER TABLE 表名 ADD FOREIGH KEY(字段名称) REFERENCES 引用的表名(引用的主键名)
ALTER TABLE 表名 DROP FOREIGH KEY 表名
示例:
#外键约束
#本表跟外部表的关联约束
# 注意:不用外键的原因时,修改数据时都要去外键所在的表中查询一遍,效率极低
#添加外键
ALTER TABLE student add FOREIGN KEY(t_id) REFERENCES teacher(id);
#查询外键名
SHOW CREATE TABLE student;
#删除外键
ALTER TABLE student DROP FOREIGN KEY student_ibfk_1;
五、深入扩展
1.索引
1.概述
索引就相当于书的目录,可以优化查找速度。
优点:提高该字段的查询效率。
缺点:更新数据,索引的数据结构也会随之改变。
优化缺点:大量更新数据,先把索引删除掉,更新完数据后再添加索引。
2.索引类型
索引类型 | 功能说明 |
---|---|
普通索引 | 最基本的索引,它没有任何限制。该列上的数据可以重复,可以为null |
唯一索引 | 某一行企用了唯一索引则不准许这一列的行数据中有重复的值。针对这一列的每一行数据都要求是唯一的 |
主键索引 | 它是一种特殊的唯一索引,不允许有空值。一般是在建表的时候同时创建主键索引,常用于用户 |
全文索引 | 对于需要全局搜索的数据,进行全文索引 |
1.普通索引
该列上的数据可以重复,可以为null
格式:
ALTER TABLE 表名 ADD INDEX(字段);
DROP INDEX 字段 ON 表名;
示例:
#为user表的username字段添加普通索引
ALTER TABLE user ADD INDEX(username);
#可以给两个字段同时添加普通索引,不过容易出现脏数据,索引容易失效
ALTER TABLE student add INDEX(name,age);
#删除普通索引
DROP INDEX username ON user;
2.唯一索引
唯一约束,该列上的数据必须相同,但可以为多个null
格式:
ALTER TABLE 表名 ADD UNIQUE(字段);
ALTER TABLE 表名 DROP INDEX(字段);
示例:
#为student表的name字段添加唯一索引
ALTER TABLE student ADD UNIQUE(name);
#删除唯一索引
ALTER TABLE db_student DROP INDEX name;
3.主键索引
主键约束,不允许重复,不允许为null
格式:
ALTER TABLE 表名 ADD PRIMARY KEY(字段);
ALTER TABLE 表名 DROP PRIMARY KEY(字段);
示例:
#创建主键索引(一般是随着建表而建索引)
ALTER TABLE db_student ADD PRIMARY KEY(id);
#删除索引
ALTER TABLE db_student DROP PRIMARY KEY;
4.全文索引
对于需要全局搜索的数据,进行全文索引
格式:
ALTER TABLE 表名 ADD FULLTEXT(字段);
DROP INDEX 字段 ON 表名;
示例:
#为student表的content字段添加全文约束
ALTER TABLE student ADD FULLTEXT(content);
#建表的时候也可以设置对应的索引
CREATE TABLE test (
id INT NOT NULL ,
username VARCHAR(20) NOT NULL ,
password INT NOT NULL ,
content INT NOT NULL ,
PRIMARY KEY (id),
INDEX pw (password),
UNIQUE (username),
FULLTEXT (content)
) ENGINE = InnoDB;
#删除索引
drop index index_name on table_name;
2、视图
1.含义
虚拟表view,mysql5.1版本出现的新特性,是通过表动态生成的数据。从一个表或多个表中查询出来的表,作用和真实表一样,包含一系列带有行和列的 数据。视图中,用户可以使用SELECT语句查询数据,也可以使用INSERT,UPDATE,DELETE修改 记录,视图可以使用户操作方便,并保障数据库系统安全。
2.视图的优缺点
- 优点
- 简单化,数据所见即所得
- 安全性,用户只能查询或修改他们所能见到得到的数据。
- 逻辑独立性,可以屏蔽真实表结构变化带来的影响。
- 缺点
- 性能相对较差,简单的查询也会变得稍显复杂。
- 修改不方便,特变是复杂的聚合视图基本无法修改。
2.创建视图
格式:CREATE VIEW 视图名 AS 查询数据源表语句;
CREATE [OR REPLACE] VIEW 视图名 AS SELECT 字段 FROM 表名 WHERE 条件 [WITH CHECK OPTION];
#or replace:如果已有视图,则替换
#with check option:当修改值超过条件时,不允许修改
示例:
CREATE OR REPLACE VIEW view1 AS SELECT name,age FROM student WHERE age>20 WITH CHECK OPTION;
3.查询视图
格式:
SELECT * FROM 视图名;
示例:
SELECT * FROM view1;
4.修改视图
格式:
INSERT INTO 视图名(字段1,字段n) VALUES(值1,值n)
UPDATE 视图名 SET 字段=值 WHERE 字段=值;
示例:
#给视图插入数据
INSERT INTO view1(name,age) VALUES('ccc',25);
insert into view1(name,age) values('ddd',19);
insert into view1(name,age) values('xxx',25);
insert into view1(name,age) values('yyy',19);
#修改视图
UPDATE view1 SET age=33 WHERE name='aaa';
5.删除视图
格式:
DROP VIEW 视图名;
示例:
#删除视图
DROP VIEW view1;
注意:删除视图不会影响原表
6.视图注意事项
- 视图不会独立存储数据,原表发生改变,视图也发生改变。没有优化任何查询性能。
- 如果视图包含以下结构中的一种,则视图不可更新
- 聚合函数的结果
- DISTINCT 去重后的结果
- GROUP BY 分组后的结果
- HAVING 筛选过滤后的结果
- UNION、UNION ALL 联合后的结果
3.触发器
1.含义
某个事件触发某个功能。
2.创建触发器
CREATE TRIGGER 触发器名
3.代码练习
#触发器:某个事件触发某个功能
#new.字段:当前写法可以获得添加语句字段对应的值
#old.字段:当前写法可以获得删除语句字段对应的值
#delimiter xx :设置xx为一条sql语句的结束符
#业务场景
#student(id,name,class_id,course_id)
#class(id,name,sum)
# 需求:student表插入数据后,class表自动更新
# 当学生表发生了插入事件,就执行班级表的更新操作
CREATE TRIGGER trigger1 AFTER INSERT ON student FOR EACH ROW UPDATE class SET sum=sum+1 WHERE id= new.class_id;
INSERT INTO student(name,class_id) VALUES('aaa',1);
INSERT INTO student(name,class_id) VALUES('bbb',1);
INSERT INTO student(name,class_id) VALUES('ccc',1);
INSERT INTO student(name,class_id) VALUES('ddd',2);
INSERT INTO student(name,class_id) VALUES('eee',2);
# 需求:student表删除数据后,class表自动更新
# 当学生表发生了删除事件,就执行班级表的更新操作
CREATE TRIGGER trigger2 BEFORE DELETE ON student FOR EACH ROW UPDATE class SET sum=sum-1 WHERE id=old.class_id;
DELETE FROM student WHERE id=1;
DROP TRIGGER trigger1;
DROP TRIGGER trigger2;
#业务场景
#student(id,name,class_id,course_id)
#class(id,name,sum)
#course(id,name,sum)
# 需求:student表插入数据后,class表自动更新,course表自动更新
delimiter xx
CREATE TRIGGER trigger3 AFTER INSERT ON student FOR EACH ROW
BEGIN
UPDATE class SET sum=sum+1 WHERE id=new.class_id;
UPDATE course SET sum=sum+1 WHERE id=new.course_id;
END xx
delimiter ;
INSERT INTO student(name,class_id,course_id) VALUES('aaa',1,1);
INSERT INTO student(name,class_id,course_id) VALUES('bbb',1,1);
INSERT INTO student(name,class_id,course_id) VALUES('ccc',2,1);
INSERT INTO student(name,class_id,course_id) VALUES('ddd',2,1);
INSERT INTO student(name,class_id,course_id) VALUES('eee',2,1);
INSERT INTO student(name,class_id,course_id) VALUES('fff',3,2);
# 需求:student表删除数据后,class表自动更新,course表自动更新
delimiter xx
CREATE TRIGGER trigger4 BEFORE DELETE ON student FOR EACH ROW
BEGIN
UPDATE class SET sum=sum-1 WHERE id=old.class_id;
UPDATE course SET sum=sum-1 WHERE id=old.course_id;
delimiter ;
DELETE FROM student WHERE id=1;
4.函数和自定义函数
1.常见函数
#数学函数
SELECT ABS(-100); #获取绝对值
SELECT SQRT(9); #获取平方根
SELECT MOD(10,3); #求余数
SELECT RAND(); #获取随机值 0(包含)~1(不包含)
SELECT POW(10,3); #幂运算
#字符串函数
SELECT LENGTH('abc123456'); #获取长度
SELECT CONCAT('123','abc','木头人'); #拼接字符串
SELECT SUBSTRING('abcdefg',2,4); #(字符串,第一个字符(从1开始),获取字符的个数)
#日期时间函数
SELECT CURDATE(); #获取当前日期
SELECT CURTIME(); #获取当前时间
SELECT NOW(); #获取当前时间加日期
SELECT YEAR(NOW()); # 获取年
SELECT MONTH(NOW()); # 获取月
SELECT DAYOFMONTH(NOW());# 获取日
SELECT HOUR(NOW());# 获取小时
SELECT MINUTE(NOW()); # 获取分
SELECT SECOND(NOW());# 获取秒
SELECT DATE_FORMAT(NOW(),"%Y年%m月%d日 %H时%i分%s秒");
2.自定义函数
#函数:类似于java中的方法
#注意:函数必须有返回值
#最简单的函数
CREATE FUNCTION fun01() RETURNS INT(3) RETURN 666;
#调用
SELECT fun01();
#带有返回值的函数
#需求:返回id为4的学生年龄
delimiter xx
CREATE FUNCTION fun02() RETURNS INT(3)
BEGIN
DECLARE a INT(3);
SELECT age INTO a FROM student WHERE id=4;
RETURN a;
END xx
delimiter ;
#调用
SELECT fun02();
#带返回值和参数的函数
#需求:传入学生姓名,查询出对应的年龄
delimiter xx
CREATE FUNCTION fun03(s_name VARCHAR(32)) RETURNS INT(3)
BEGIN
DECLARE a int(3);
SELECT age INTO a FROM student WHERE name=s_name;
RETURN a;
END xx
delimiter ;
#调用
SELECT fun03('ccc');
#删除函数
DROP FUNCTION fun01;
5.存储过程
1.含义
存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给定参数(如果该存储过程带有参数)来调用执行它。
2.创建存储过程
CREATE PROCEDURE 存储过程名
3.参数
输入类型的参数 -- in;
输出类型的参数 -- out;
输入输出类型的参数 -- inout;
4.代码练习
#存储过程
#参数列表
#输入类型的参数 -- in;
#输出类型的参数 -- out;
#输入输出类型的参数 -- inout;
#案例1:最简单的的存储过程
#需求:查询学生信息和班级信息
delimiter xx
CREATE PROCEDURE myprocedure01()
BEGIN
SELECT * FROM student;
SELECT * FROM class;
END xx
delimiter ;
#调用存储过程
CALL myprocedure01();
# 案例2:输入一个学生的id,查询该学生的信息
delimiter xx
CREATE PROCEDURE myprocedure02(in s_id INT(3))
BEGIN
SELECT * FROM student WHERE id=s_id;
END xx
delimiter ;
#调用存储过程
CALL myprocedure02(2);
# 案例3:输入一个学生的id,返回该id对应的学生姓名
delimiter xx
CREATE PROCEDURE myprocedure03(in s_id INT(3),out s_name VARCHAR(32))
BEGIN
SELECT name INTO s_name FROM student WHERE id=s_id;
END xx
delimiter ;
#调用存储过程
CALL myprocedure03(2,@a);
SELECT @a;
# 案例4:输入一个学生的id,返回该id对应的学生年龄
delimiter xx
CREATE PROCEDURE myprocedure04(INOUT pram INT(3))
BEGIN
SELECT age INTO pram FROM student WHERE id=pram;
END xx
delimiter ;
#调用存储过程
SET @pram=2;#设置局部变量
CALL myprocedure04(@pram);
SELECT @pram;
# 案例5:定义存储过程中的变量
# 需求:获取学生表中学生的人数
delimiter xx
CREATE PROCEDURE myprocedure05(out s_out int(3))
BEGIN
# 定义变量
# declare 变量名 类型 [default 默认值];
DECLARE a INT DEFAULT 0;
# 给变量赋值(目的:告诉你们可以这样复制,在本案例里没有任何意义)
SET a=100;
SELECT COUNT(id) INTO a FROM student;
SET s_out=a;
END xx
delimiter ;
# 调用存储过程
call myprocedure05(@a);
select @a;
#删除存储过程
DROP PROCEDURE myprocedure05;
五、代码练习
1.导入数据
/*创建部门表*/
CREATE TABLE dept(
deptno INT PRIMARY KEY,
dname VARCHAR(50),
loc VARCHAR(50)
);
/*创建雇员表*/
CREATE TABLE emp(
empno INT PRIMARY KEY,
ename VARCHAR(50),
job VARCHAR(50),
mgr INT,
hiredate DATE,
sal DECIMAL(7,2),
COMM DECIMAL(7,2),
deptno INT,
CONSTRAINT fk_emp FOREIGN KEY(mgr) REFERENCES emp(empno)
);
/*创建工资等级表*/
CREATE TABLE salgrade(
grade INT PRIMARY KEY,
losal INT,
hisal INT
);
/*创建学生表*/
CREATE TABLE stu(
sid INT PRIMARY KEY,
sname VARCHAR(50),
age INT,
gander VARCHAR(10),
province VARCHAR(50),
tuition INT
);
/*插入dept表数据*/
INSERT INTO dept VALUES (10, '教研部', '北京');
INSERT INTO dept VALUES (20, '学工部', '上海');
INSERT INTO dept VALUES (30, '销售部', '广州');
INSERT INTO dept VALUES (40, '财务部', '武汉');
/*插入emp表数据*/
INSERT INTO emp VALUES (1009, '曾阿牛', '董事长', NULL, '2001-11-17', 50000, NULL, 10);
INSERT INTO emp VALUES (1004, '刘备', '经理', 1009, '2001-04-02', 29750, NULL, 20);
INSERT INTO emp VALUES (1006, '关羽', '经理', 1009, '2001-05-01', 28500, NULL, 30);
INSERT INTO emp VALUES (1007, '张飞', '经理', 1009, '2001-09-01', 24500, NULL, 10);
INSERT INTO emp VALUES (1008, '诸葛亮', '分析师', 1004, '2007-04-19', 30000, NULL, 20);
INSERT INTO emp VALUES (1013, '庞统', '分析师', 1004, '2001-12-03', 30000, NULL, 20);
INSERT INTO emp VALUES (1002, '黛绮丝', '销售员', 1006, '2001-02-20', 16000, 3000, 30);
INSERT INTO emp VALUES (1003, '殷天正', '销售员', 1006, '2001-02-22', 12500, 5000, 30);
INSERT INTO emp VALUES (1005, '谢逊', '销售员', 1006, '2001-09-28', 12500, 14000, 30);
INSERT INTO emp VALUES (1010, '韦一笑', '销售员', 1006, '2001-09-08', 15000, 0, 30);
INSERT INTO emp VALUES (1012, '程普', '文员', 1006, '2001-12-03', 9500, NULL, 30);
INSERT INTO emp VALUES (1014, '黄盖', '文员', 1007, '2002-01-23', 13000, NULL, 10);
INSERT INTO emp VALUES (1011, '周泰', '文员', 1008, '2007-05-23', 11000, NULL, 20);
INSERT INTO emp VALUES (1001, '甘宁', '文员', 1013, '2000-12-17', 8000, NULL, 20);
/*插入salgrade表数据*/
INSERT INTO salgrade VALUES (1, 7000, 12000);
INSERT INTO salgrade VALUES (2, 12010, 14000);
INSERT INTO salgrade VALUES (3, 14010, 20000);
INSERT INTO salgrade VALUES (4, 20010, 30000);
INSERT INTO salgrade VALUES (5, 30010, 99990);
/*插入stu表数据*/
INSERT INTO `stu` VALUES ('1', '王永', '23', '男', '北京', '1500');
INSERT INTO `stu` VALUES ('2', '张雷', '25', '男', '辽宁', '2500');
INSERT INTO `stu` VALUES ('3', '李强', '22', '男', '北京', '3500');
INSERT INTO `stu` VALUES ('4', '宋永合', '25', '男', '北京', '1500');
INSERT INTO `stu` VALUES ('5', '叙美丽', '23', '女', '北京', '1000');
INSERT INTO `stu` VALUES ('6', '陈宁', '22', '女', '山东', '2500');
INSERT INTO `stu` VALUES ('7', '王丽', '21', '女', '北京', '1600');
INSERT INTO `stu` VALUES ('8', '李永', '23', '男', '北京', '3500');
INSERT INTO `stu` VALUES ('9', '张玲', '23', '女', '广州', '2500');
INSERT INTO `stu` VALUES ('10', '啊历', '18', '男', '山西', '3500');
INSERT INTO `stu` VALUES ('11', '王刚', '23', '男', '湖北', '4500');
INSERT INTO `stu` VALUES ('12', '陈永', '24', '男', '北京', '1500');
INSERT INTO `stu` VALUES ('13', '李雷', '24', '男', '辽宁', '2500');
INSERT INTO `stu` VALUES ('14', '李沿', '22', '男', '北京', '3500');
INSERT INTO `stu` VALUES ('15', '王小明', '25', '男', '北京', '1500');
INSERT INTO `stu` VALUES ('16', '王小丽', '23', '女', '北京', '1000');
INSERT INTO `stu` VALUES ('17', '唐宁', '22', '女', '山东', '2500');
INSERT INTO `stu` VALUES ('18', '唐丽', '21', '女', '北京', '1600');
INSERT INTO `stu` VALUES ('19', '啊永', '23', '男', '北京', '3500');
INSERT INTO `stu` VALUES ('20', '唐玲', '23', '女', '广州', '2500');
INSERT INTO `stu` VALUES ('21', '叙刚', '18', '男', '山西', '3500');
INSERT INTO `stu` VALUES ('22', '王累', '23', '男', '湖北', '4500');
INSERT INTO `stu` VALUES ('23', '赵安', '23', '男', '北京', '1500');
INSERT INTO `stu` VALUES ('24', '关雷', '25', '男', '辽宁', '2500');
INSERT INTO `stu` VALUES ('25', '李字', '22', '男', '北京', '3500');
INSERT INTO `stu` VALUES ('26', '叙安国', '25', '男', '北京', '1500');
INSERT INTO `stu` VALUES ('27', '陈浩难', '23', '女', '北京', '1000');
INSERT INTO `stu` VALUES ('28', '陈明', '22', '女', '山东', '2500');
INSERT INTO `stu` VALUES ('29', '孙丽', '21', '女', '北京', '1600');
INSERT INTO `stu` VALUES ('30', '李治国', '23', '男', '北京', '3500');
INSERT INTO `stu` VALUES ('31', '张娜', '23', '女', '广州', '2500');
INSERT INTO `stu` VALUES ('32', '安强', '18', '男', '山西', '3500');
INSERT INTO `stu` VALUES ('33', '王欢', '23', '男', '湖北', '4500');
INSERT INTO `stu` VALUES ('34', '周天乐', '23', '男', '北京', '1500');
INSERT INTO `stu` VALUES ('35', '关雷', '25', '男', '辽宁', '2500');
INSERT INTO `stu` VALUES ('36', '吴强', '22', '男', '北京', '3500');
INSERT INTO `stu` VALUES ('37', '吴合国', '25', '男', '北京', '1500');
INSERT INTO `stu` VALUES ('38', '正小和', '23', '女', '北京', '1000');
INSERT INTO `stu` VALUES ('39', '吴丽', '22', '女', '山东', '2500');
INSERT INTO `stu` VALUES ('40', '冯含', '21', '女', '北京', '1600');
INSERT INTO `stu` VALUES ('41', '陈冬', '23', '男', '北京', '3500');
INSERT INTO `stu` VALUES ('42', '关玲', '23', '女', '广州', '2500');
INSERT INTO `stu` VALUES ('43', '包利', '18', '男', '山西', '3500');
INSERT INTO `stu` VALUES ('44', '威刚', '23', '男', '湖北', '4500');
INSERT INTO `stu` VALUES ('45', '李永', '23', '男', '北京', '1500');
INSERT INTO `stu` VALUES ('46', '张关雷', '25', '男', '辽宁', '2500');
INSERT INTO `stu` VALUES ('47', '送小强', '22', '男', '北京', '3500');
INSERT INTO `stu` VALUES ('48', '关动林', '25', '男', '北京', '1500');
INSERT INTO `stu` VALUES ('49', '苏小哑', '23', '女', '北京', '1000');
INSERT INTO `stu` VALUES ('50', '赵宁', '22', '女', '山东', '2500');
INSERT INTO `stu` VALUES ('51', '陈丽', '21', '女', '北京', '1600');
INSERT INTO `stu` VALUES ('52', '钱小刚', '23', '男', '北京', '3500');
INSERT INTO `stu` VALUES ('53', '艾林', '23', '女', '广州', '2500');
INSERT INTO `stu` VALUES ('54', '郭林', '18', '男', '山西', '3500');
INSERT INTO `stu` VALUES ('55', '周制强', '23', '男', '湖北', '4500');
2.题目
-
查询出部门编号为30的所有员工
SELECT * FROM emp WHERE deptno=30;
-
所有销售员的姓名、编号和部门编号。
SELECT ename,empno,deptno FROM emp;
-
找出奖金高于工资的员工。
SELECT * FROM emp WHERE COMM>sal;
-
找出奖金高于工资60%的员工。
SELECT * FROM emp WHERE COMM>(sal*0.6);
-
找出部门编号为10中所有经理,和部门编号为20中所有销售员的详细资料。
SELECT * FROM emp WHERE job='经理' AND deptno=10 OR job='销售员' AND deptno=20;
-
找出部门编号为10中所有经理,部门编号为20中所有销售员,还有即不是经理又不是销售员但其工资大或等于20000的所有员工详细资料。
SELECT * FROM emp WHERE job='经理' AND deptno=10 OR job='销售员' AND deptno=20 OR job!='经理' AND job!='销售员' AND sal>=20000;
-
无奖金或奖金低于1000的员工。
SELECT * FROM emp WHERE COMM<1000 OR COMM IS NULL;
-
查询名字由三个字组成的员工
SELECT * FROM emp WHERE ename LIKE '___';
-
查询2000年入职的员工。
SELECT * FROM emp WHERE hiredate LIKE '2000%';
-
查询所有员工详细信息,用编号升序排序
SELECT * FROM emp ORDER BY empno; SELECT * FROM emp ORDER BY empno ASC;
-
查询所有员工详细信息,用工资降序排序,如果工资相同使用入职日期升序排序
SELECT * FROM emp ORDER BY sal DESC,hiredate
12.查询每个部门的平均工资
SELECT deptno,AVG(sal) FROM emp GROUP BY deptno;
13.查询每个部门的雇员数量
SELECT deptno,COUNT(deptno) FROM emp GROUP BY deptno;
14.查询每种工作的最高工资、最低工资、人数
SELECT deptno,MAX(sal),MIN(sal),COUNT(deptno) FROM emp GROUP BY deptno;
15.查出至少有一个员工的部门。显示部门编号、部门名称、部门位置、部门人数
SELECT e.deptno,COUNT(e.empno),d.dname,d.loc
FROM emp e,dept d
WHERE e.deptno=d.deptno
GROUP BY deptno
HAVING COUNT(empno)>=4;
16.列出所有员工的姓名及其直接上级的姓名
SELECT e1.ename,e2.ename
FROM emp e1,emp e2
WHERE e1.mgr=e2.empno;
SELECT e1.ename,e2.ename
FROM emp e1 LEFT JOIN emp e2
ON e1.mgr=e2.empno;
17.列出受雇日期早于直接上级的所有员工的编号、姓名、部门名称
SELECT e1.empno,e1.ename,d.dname
FROM emp e1,emp e2,dept d
WHERE e1.mgr=e2.empno AND e1.deptno=d.deptno AND
e1.hiredate<e2.hiredate;
SELECT e1.empno,e1.ename,d.dname
FROM emp e1 LEFT JOIN emp e2
ON e1.mgr=e2.empno
LEFT JOIN dept d
ON e1.deptno=d.deptno
WHERE e1.hiredate<e2.hiredate;
18.列出部门名称和这些部门的员工信息,同时列出那些没有员工的部门
SELECT d.dname,e.*
FROM dept d LEFT JOIN emp e
ON d.deptno = e.deptno;
19.列出最低薪金大于15000的各种工作及从事此工作的员工人数
SELECT job,MIN(sal+IFNULL(COMM,0)),COUNT(empno)
FROM emp
GROUP BY job
HAVING MIN(sal+IFNULL(COMM,0))>15000;
20.列出在销售部工作的员工的姓名,假定不知道销售部的部门编号
SELECT emp.ename,dept.deptno FROM emp,dept WHERE emp.deptno=dept.deptno AND dname='销售部';
21.列出薪金高于公司平均薪金的所有员工信息,所在部门名称,上级领导,工资等级
SELECT
FROM emp e1,emp e2,dept d,salgrade s
WHERE (e1.sal+IFNULL(e1.COMM,0))>(SELECT AVG(sal+IFNULL(COMM,0)) FROM emp)
AND e1.mgr=e2.empno AND e1.deptno=d.deptno
AND e1.sal>s.losal AND e1.sal<=s.hisal;
22.列出与庞统从事相同工作的所有员工及部门名称
SELECT emp.*,dept.dname
FROM emp,dept WHERE emp.deptno=dept.deptno
AND emp.job=(SELECT job FROM emp WHERE ename='庞统');
23.列出薪金高于在部门30工作的所有员工的薪金的员工姓名和薪金、部门名称
SELECT e.ename,e.((sal + IFNULL(COMM,0)),d.dname
FROM emp e,dept d
WHERE e.deptno=d.deptno
AND (e.sal+IFNULL(e.COMM,0))>(SELECT MAX(sal+IFNULL(COMM,0)) FROM emp WHERE deptno=30);
24.列出每个部门的员工数量、平均工资
SELECT COUNT(*),AVG(sal)
FROM emp
WHERE deptno IN(SELECT deptno FROM dept)
GROUP BY deptno;