第一章 基本概述

1. 数据库(数据库管理系统)

  • 通过简单的SQL语句便可以对数据进行增删改查,但其底层都是通过IO流对数据进行增删改查;但数据库只需几条简单的SQL语句就可以了,十分便捷

1.1 登录MySQL

进入DOS,输入命令
第一种:
mysql -uroot -p123
第二种:(密码会以*号代替)
mysql -uroot -p

1.2 修改密码

  1. - 方法1 SET PASSWORD

首先登录MySQL
格式:
mysql> set password for 用户名@localhost = password(‘新密码’);
例子:
mysql> set password for root@localhost = password(‘123’);

  1. - 方法2:用mysqladmin

格式:
mysqladmin -u用户名 -p旧密码 password 新密码
例子:
mysqladmin -uroot -p123456 password 123

  1. - 方法3:用UPDATE直接编辑user

首先登录MySQL
mysql> use mysql;
mysql> update user set password=password(‘123’) where user=’root’ and host=’localhost’;
mysql> flush privileges;

  1. - 方法4:在忘记root密码的时候,可以这样

以windows为例:
1. 关闭正在运行的MySQL服务。
2. 打开DOS窗口,转到mysql\bin目录。
3. 输入mysqld —skip-grant-tables 回车。—skip-grant-tables 的意思是启动MySQL服务的时候跳过权限表认证。
4. 再开一个DOS窗口(因为刚才那个DOS窗口已经不能动了),转到mysql\bin目录。
5. 输入mysql回车,如果成功,将出现MySQL提示符 >
6. 连接权限数据库: use mysql;
7. 改密码:update user set password=password(“123”) where user=”root”;(别忘了最后加分号)
8. 刷新权限(必须步骤):flush privileges;
9. 退出 quit。
10. 注销系统,再进入,使用用户名root和刚才设置的新密码123登录。

1.3 卸载MySQL

1、双击安装包,点击下一步,然后点击remove,卸载
2、手动删除Program Files中的MySQL目录
3、手动删除ProgramData目录(这个目录是隐藏的)中的MySQL

2. DB、DBMS、SQL的关系

DB:
DataBase(数据库,数据库实际上在硬盘上以文件的形式存在)
DBMS:
DataBase Management System(数据库管理系统,常见的有:MySQL Oracle DB2 Sybase SqlServer…)
SQL:
结构化查询语言,是一门标准通用的语言。标准的sql适合于所有的数据库产品。

  • SQL属于高级语言。SQL语句在执行的时候,实际上内部也会先进行编译,然后再执行sql。(sql语句的编译由DBMS完成。)

  • DBMS负责执行sql语句,通过执行sql语句来操作DB当中的数据。DBMS -(执行)-> SQL -(操作)-> DB

3. 表的概念

  • 表:table是数据库的基本组成单元,所有的数据都以表格的形式组织,目的是可读性强
  • 一个表包括行和列:行:被称为数据/记录(data);列:被称为字段(column)
  • 每一个字段应该包括哪些属性:字段名、数据类型、相关的约束。

4. SQL语句的分类

DQL(数据查询语言): 查询语句,凡是select语句都是DQL
DML(数据操作语言):insert delete update,对表当中的数据进行增删改
DDL(数据定义语言):create drop alter,对表结构的增删改
TCL(事务控制语言):commit提交事务,rollback回滚事务。(TCL中的T是Transaction)
DCL(数据控制语言): grant授权、revoke撤销权限等

5. 导入数据

第一步:登录mysql数据库管理系统
DOS窗口下:
mysql -uroot -p333

第二步:查看有哪些数据库
show databases; (这个不是SQL语句,属于MySQL的命令)

第三步:创建属于我们自己的数据库
create database bjpowernode; (这个不是SQL语句,属于MySQL的命令)

第四步:使用bjpowernode这个数据库的数据
use bjpowernode; (这个不是SQL语句,属于MySQL的命令。)

第五步:查看当前使用的数据库中有哪些表?
show tables; (这个不是SQL语句,属于MySQL的命令。)

第六步:初始化数据
mysql> source D:\course\05-MySQL\resources\bjpowernode.sql

6. sql脚本

  • 当一个文件的扩展名是.sql,并且该文件中编写了大量的sql语句,我们称这样的文件为sql脚本。


注意直接使用source命令可以执行sql脚本。sql脚本中的数据量太大的时候,无法打开,请使用source命令完成初始化

7. 删除数据库:

drop database bjpowernode;

8. 查看表结构:

desc dept;

9. 常用命令

  • select database(); 查看当前使用的是哪个数据库

  • select version(); 查看mysql的版本号。

  • \c 命令,结束一条语句。

  • exit 命令,退出mysql。

  • show create table emp;查看创建表的语句

10. 简单的查询语句(DQL)

  • 语法格式:

select 字段名1,字段名2,字段名3,…. from 表名;

提示: 1、任何一条sql语句以“;”结尾 2、sql语句不区分大小写

  • 字段可以参与数学

    1. select ename,sal * 12 from emp;
  • 给查询结果的列取别名

    1. select ename,sal * 12 as yearsal from emp;
  • 别名中有中文?

    1. select ename,sal * 12 as 年薪 from emp; // 错误<br /> select ename,sal * 12 as '年薪' from emp;

注意: 标准sql语句中要求字符串使用单引号括起来。虽然mysql支持双引号,尽量别用

  • as关键字可以省略?可以省略但不建议,会降低代码的可读性

mysql> select empno,ename,sal * 12 yearsal from emp;

  • 查询所有字段?实际开发中不建议使用*,效率较低

select * from emp;

  • 找出工资不等于3000的?

select ename,sal from emp where sal <> 3000;
select ename,sal from emp where sal != 3000;

  • 找出工资在1100和3000之间的员工,包括1100和3000?

select ename,sal from emp where sal >= 1100 and sal <= 3000;
// between…and…是闭区间 [1100 ~3000],与>= XXX and <=XXX等价
select ename,sal from emp where sal between 1100 and 3000;
// 查询不到任何数据,between and在使用的时候必须左小右大。
select ename,sal from emp where sal between 3000 and 1100;

  • between and(左闭右开)除了可以使用在数字方面之外,还可以使用在字符串方面。

select ename from emp where ename between ‘A’ and ‘C’;

  • 在数据库当中NULL不是一个值,代表什么也没有,为空;空不是一个值,不能用等号衡量,必须使用 is null或者is not null

  • in等同于or:select ename,job from emp where sal in(800, 5000); // in后面的值不是区间,是具体的值等价于:sal=800 or sal=5000

  • not in: 不在这几个值当中

10.1 模糊查询like ?

  • 在模糊查询当中,必须掌握两个特殊的符号,一个是%,一个是;%代表任意多个字符,代表任意1个字符。

  • 找出名字中有下划线的?通过转义字符

select name from tuser where name like ‘%\%’;

10.2 排序(升序、降序)

  • 注意:默认是升序。怎么指定升序或者降序呢?asc表示升序,desc表示降序。
  • 按照工资的降序排列,当工资相同的时候再按照名字的升序排列。

select ename,sal from emp order by sal desc , ename asc;

注意: 越靠前的字段越能起到主导作用;只有当前面的字段无法完成排序的时候,才会启用后面的字段

11. 分组函数

count :计数
sum : 求和
avg : 平均值
max : 最大值
min : 最小值

  • 记住:所有的分组函数都是对“某一组”数据进行操作的

  • 分组函数一共5个,分组函数还有另一个名字:多行处理函数;多行处理函数的特点:输入多行,最终输出的结果是1行。分组函数自动忽略NULL

  • count(*)和count(具体的某个字段),他们有什么区别?

count(*):不是统计某个字段中数据的个数,而是统计总记录条数(和某个字段无关);count(comm): 表示统计comm字段中不为NULL的数据总数量。

select ename,sal from emp where sal > avg(sal); //ERROR 1111 (HY000): Invalid use of group function 思考以上的错误信息:无效的使用了分组函数? 原因:SQL语句当中有一个语法规则,分组函数不可直接使用在where子句当中 怎么解释? 因为group by是在where执行之后才会执行的

11.1 单行处理函数

  • 什么是单行处理函数

输入一行,输出一行

  • 重点:所有数据库都是这样规定的,只要有NULL参与的运算结果一定是NULL

  • 使用ifnull函数:

select ename,(sal+ifnull(comm,0))*12 as yearsal from emp;

  • ifnull() 空处理函数?

ifnull(可能为NULL的数据,被当做什么处理) : 属于单行处理函数
select ename,ifnull(comm,0) as comm from emp;

多行处理函数其对多行进行处理,但输出只有一行,单行处理函数输入一行输出一行

11.2 group by 和 having

  • group by : 按照某个字段或者某些字段进行分组
  • having : having是对分组之后的数据进行再次过滤

注意:
分组函数一般都会和group by联合使用,这也是为什么它被称为分组函数的原因。并且任何一个分组函数(count sum avg max min)都是在group by语句执行结束之后才会执行的。当一条sql语句没有group by的话,整张表的数据会自成一组。
select ename,max(sal),job from emp group by job;
以上在mysql当中,查询结果是有的,但是结果没有意义,在Oracle数据库当中会报错,语法错误;Oracle的语法规则比MySQL语法规则严谨。
记住一个规则:
当一条语句中有group by的话,select后面只能跟分组函数和参与分组的字段

  • 建议能够使用where过滤的尽量使用where而不要使用having,效率较高

12. DQL语句顺序:

select 5
..
from 1
..
where 2
..
group by 3
..
having 4
..
order by 6
..

13. 关于查询结果集的去重

  • mysql> select distinct job from emp; // distinct关键字去除重复记录。

  • mysql> select ename,distinct job from emp;

以上的sql语句是错误的
记住:distinct只能出现在所有字段的最前面

14. 连接查询

  • 在实际开发中,大部分的情况下都不是从单表中查询数据,一般都是多张表联合查询取出最终的结果;在实际开发中,一般一个业务都会对应多张表,比如:学生和班级,起码两张表。

    stuno stuname classno classname
    —————————————————————————————————————————-
    1 zs 1 北京大兴区亦庄经济技术开发区第二中学高三1班
    2 ls 1 北京大兴区亦庄经济技术开发区第二中学高三1班

学生和班级信息存储到一张表中,结果就像上面一样,数据会存在大量的重复,导致数据的冗余。

14.1 连接查询的分类

  • 根据语法出现的年代来划分的话,包括:SQL92(一些老的DBA可能还在使用这种语法。DBA:DataBase Administrator,数据库管理员)SQL99(比较新的语法)
  • 根据表的连接方式来划分,包括:

内连接:
等值连接
非等值连接
自连接

外连接:
左外连接(左连接)
右外连接(右连接)

全连接(很少用)

14.2 笛卡尔积现象

  • 在表的连接查询方面有一种现象被称为:笛卡尔积现象。(笛卡尔乘积现象)

当两张表进行连接查询的时候,没有任何条件进行限制,最终的查询结果条数是两张表记录条数的乘积

  • 关于表的别名:

select e.ename,d.dname from emp e,dept d;
表的别名有什么好处?
第一:执行效率高
第二:可读性好

  • 怎么避免笛卡尔积现象?当然是加条件进行过滤

思考: 避免了笛卡尔积现象,会减少记录的匹配次数吗? 不会,次数还是56次。只不过显示的是有效记录

14.3 内连接之等值连接:

最大特点是:条件是等量关系

  1. 案例:查询每个员工的部门名称,要求显示员工名和部门名。
  2. SQL92:(太老,不用了)
  3. select
  4. e.ename,d.dname
  5. from
  6. emp e, dept d
  7. where
  8. e.deptno = d.deptno;
  9. SQL99:(常用的)
  10. select
  11. e.ename,d.dname
  12. from
  13. emp e
  14. join
  15. dept d
  16. on
  17. e.deptno = d.deptno;
  18. // inner可以省略的,带着inner目的是可读性好一些。
  19. select
  20. e.ename,d.dname
  21. from
  22. emp e
  23. inner join
  24. dept d
  25. on
  26. e.deptno = d.deptno;
  27. 语法:
  28. ...
  29. A
  30. join
  31. B
  32. on
  33. 连接条件
  34. where
  35. ...
  36. SQL99语法结构更清晰一些:表的连接条件和后来的where条件分离了

14.4 内连接之非等值连接

最大的特点是:连接条件中的关系是非等量关系。

  1. select
  2. e.ename,e.sal,s.grade
  3. from
  4. emp e
  5. join
  6. salgrade s
  7. on
  8. e.sal between s.losal and s.hisal;
  9. // inner可以省略
  10. select
  11. e.ename,e.sal,s.grade
  12. from
  13. emp e
  14. inner join
  15. salgrade s
  16. on
  17. e.sal between s.losal and s.hisal;

14.5 自连接:

最大的特点是:一张表看做两张表,自己连接自己

  1. 员工的领导编号 = 领导的员工编号
  2. select
  3. a.ename as '员工名',b.ename as '领导名'
  4. from
  5. emp a
  6. inner join
  7. emp b
  8. on
  9. a.mgr = b.empno;

14.6 外连接

  • 什么是外连接,和内连接有什么区别?

内连接:
假设A和B表进行连接,使用内连接的话,凡是A表和B表能够匹配上的记录查询出来,这就是内连接。 AB两张表没有主副之分,两张表是平等的。
外连接:
假设A和B表进行连接,使用外连接的话,AB两张表中有一张表是主表,一张表是副表,主要查询主表中的数据,捎带着查询副表,当副表中的数据没有和主表中的数据匹配上,副表自动模拟出NULL与之匹配。

  • 外连接的分类?

左外连接(左连接):表示左边的这张表是主表
右外连接(右连接):表示右边的这张表是主表
左连接有右连接的写法,右连接也会有对应的左连接的写法

  1. 内连接:
  2. select
  3. a.ename '员工', b.ename '领导'
  4. from
  5. emp a
  6. join
  7. emp b
  8. on
  9. a.mgr = b.empno;
  10. 外连接:(左外连接/左连接)
  11. select
  12. a.ename '员工', b.ename '领导'
  13. from
  14. emp a
  15. left join
  16. emp b
  17. on
  18. a.mgr = b.empno;
  19. // outer是可以省略的。
  20. select
  21. a.ename '员工', b.ename '领导'
  22. from
  23. emp a
  24. left outer join
  25. emp b
  26. on
  27. a.mgr = b.empno;
  28. 外连接:(右外连接/右连接)
  29. select
  30. a.ename '员工', b.ename '领导'
  31. from
  32. emp b
  33. right join
  34. emp a
  35. on
  36. a.mgr = b.empno;
  37. // outer可以省略。
  38. select
  39. a.ename '员工', b.ename '领导'
  40. from
  41. emp b
  42. right outer join
  43. emp a
  44. on
  45. a.mgr = b.empno;
  • 外连接最重要的特点是:主表的数据无条件的全部查询出来。

14.7 三张表连接查询

….
A
join
B
join
C
on


表示:A表和B表先进行表连接,连接之后A表继续和C表进行连接

  1. select
  2. e.ename '员工',d.dname,s.grade,e1.ename '领导'
  3. from
  4. emp e
  5. join
  6. dept d
  7. on
  8. e.deptno = d.deptno
  9. join
  10. salgrade s
  11. on
  12. e.sal between s.losal and s.hisal
  13. left join
  14. emp e1
  15. on
  16. e.mgr = e1.empno;

15. 子查询

  • 什么是子查询?子查询都可以出现在哪里?

select语句当中嵌套select语句,被嵌套的select语句是子查询。
子查询可以出现在哪里?
select … (select) from … (select) where … (select)

15.1 where子句中使用子查询

select * from emp where sal > (select avg(sal) from emp);

15.2 from后面嵌套子查询

  1. 案例:找出每个部门平均薪水的等级。
  2. 第一步:找出每个部门平均薪水(按照部门编号分组,求sal的平均值)
  3. select deptno,avg(sal) as avgsal from emp group by deptno;
  4. +--------+-------------+
  5. | deptno | avgsal |
  6. +--------+-------------+
  7. | 10 | 2916.666667 |
  8. | 20 | 2175.000000 |
  9. | 30 | 1566.666667 |
  10. +--------+-------------+
  11. 第二步:将以上的查询结果当做临时表t,让t表和salgrade s表连接,条件是:t.avgsal between s.losal and s.hisal
  12. select
  13. t.*,s.grade
  14. from
  15. (select deptno,avg(sal) as avgsal from emp group by deptno) t
  16. join
  17. salgrade s
  18. on
  19. t.avgsal between s.losal and s.hisal;

15.3 在select后面嵌套子查询

select
e.ename,(select d.dname from dept d where e.deptno = d.deptno) as dname
from
emp e;

16. union (可以将查询结果集相加)

两张不相干的表中的数据拼接在一起显示?

select ename from emp
union
select dname from dept;

mysql> select ename,sal from emp -> union -> select dname from dept; ERROR 1222 (21000): The used SELECT statements have a different number of columns

17. limit (重点中的重点,用于分页查询)

  • limit是mysql特有的,其他数据库中没有,不通用。(Oracle中有一个相同的机制,叫做rownum)
  • limit取结果集中的部分数据,这是它的作用

语法机制:
limit startIndex, length
startIndex表示起始位置,从0开始,0表示第一条数据,length表示取几个

  1. 案例:取出工资前5名的员工(思路:降序取前5个)
  2. select ename,sal from emp order by sal desc;
  3. 取前5个:
  4. select ename,sal from emp order by sal desc limit 0, 5;
  5. select ename,sal from emp order by sal desc limit 5;
  • limit是sql语句最后执行的一个环节:

select 5

from 1

where 2

group by 3

having 4

order by 6

limit 7
…;

18. 通用的标准分页sql

每页显示3条记录:
第1页:0, 3
第2页:3, 3
第3页:6, 3
第4页:9, 3
第5页:12, 3

每页显示pageSize条记录:
第pageNo页:(pageNo - 1) * pageSize, pageSize
pageSize是什么?是每页显示多少条记录
pageNo是什么?显示第几页

19. 创建表:

  • 建表语句的语法格式:

    create table 表名(
    字段名1 数据类型,
    字段名2 数据类型,
    字段名3 数据类型,
    ….
    );

  • 关于MySQL当中字段的数据类型?以下只说常见的

int 整数型(java中的int)
bigint 长整型(java中的long)
float 浮点型(java中的float double)
char 定长字符串(String)
varchar 可变长字符串(StringBuffer/StringBuilder)
date 日期类型 (对应Java中的java.sql.Date类型)
BLOB 二进制大对象(存储图片、视频等流媒体信息) Binary Large OBject (对应java中的Object)
CLOB 字符大对象(存储较大文本,比如,可以存储4G的字符串) Character Large OBject(对应java中的Object)
……

  • char和varchar怎么选择?

在实际的开发中,当某个字段中的数据长度不发生改变的时候,是定长的,例如:性别、生日等都是采用char;当一个字段的数据长度不确定,例如:简介、姓名等都是采用varchar

  • 表名在数据库当中一般建议以:t或者tbl开始。

  • 创建学生表: ```sql 学生信息包括: 学号、姓名、性别、班级编号、生日 学号:bigint 姓名:varchar 性别:char 班级编号:int 生日:char

create table t_student( no bigint, name varchar(255), sex char(1), classno varchar(255), birth char(10) );

  1. <a name="3Angq"></a>
  2. ## 20. insert语句插入数据
  3. - 语法格式:
  4. insert into 表名(字段名1,字段名2,字段名3,....) values(值1,值2,值3,....)
  5. 要求:<br />字段的数量和值的数量相同,并且数据类型要对应相同。
  6. // 除name字段之外,剩下的所有字段自动插入NULL。<br />insert into t_student(name) values('wangwu');
  7. ```sql
  8. //建表的时候设置默认值
  9. create table t_student(
  10. no bigint,
  11. name varchar(255),
  12. sex char(1) default 1,
  13. classno varchar(255),
  14. birth char(10)
  15. );
  16. insert into t_student(name) values('zhangsan');
  17. mysql> select * from t_student;
  18. +------+----------+------+---------+-------+
  19. | no | name | sex | classno | birth |
  20. +------+----------+------+---------+-------+
  21. | NULL | zhangsan | 1 | NULL | NULL |
  22. +------+----------+------+---------+-------+
  1. insert into t_student
  2. (no,name,sex,classno,birth)
  3. values
  4. (3,'rose','1','gaosi2ban','1952-12-14'),(4,'laotie','1','gaosi2ban','1955-12-14');
  5. mysql> select * from t_student;
  6. +------+----------+------+------------+------------+
  7. | no | name | sex | classno | birth |
  8. +------+----------+------+------------+------------+
  9. | NULL | zhangsan | 1 | NULL | NULL |
  10. | 1 | jack | 0 | gaosan2ban | 1986-10-23 |
  11. | 3 | rose | 1 | gaosi2ban | 1952-12-14 |
  12. | 4 | laotie | 1 | gaosi2ban | 1955-12-14 |
  13. +------+----------+------+------------+------------+

需要注意的地方: 当一条insert语句执行成功之后,表格当中必然会多一行记录。即使多的这一行记录当中某些字段是NULL,后期也没有办法在执行insert语句插入数据了,只能使用update进行更新。 字段可以省略不写,但是后面的value对数量和顺序都有要求。

21. 删除表

  1. drop table if exists t_student; // 当这个表存在的话删除

22. 表的复制

  • 语法:

create table 表名 as select语句;将查询结果当做表创建出来

  • 将查询结果插入到一张表中?
  1. mysql> insert into dept1 select * from dept;
  2. mysql> select * from dept1;
  3. +--------+------------+----------+
  4. | DEPTNO | DNAME | LOC |
  5. +--------+------------+----------+
  6. | 10 | ACCOUNTING | NEW YORK |
  7. | 20 | RESEARCH | DALLAS |
  8. | 30 | SALES | CHICAGO |
  9. | 40 | OPERATIONS | BOSTON |
  10. | 10 | ACCOUNTING | NEW YORK |
  11. | 20 | RESEARCH | DALLAS |
  12. | 30 | SALES | CHICAGO |
  13. | 40 | OPERATIONS | BOSTON |
  14. +--------+------------+----------+

23. 修改数据:update

  • 语法格式:

update 表名 set 字段名1=值1,字段名2=值2… where 条件;

注意: 没有条件整张表数据全部更新

  • 更新所有记录

update dept1 set loc = ‘x’, dname = ‘y’;

24. 删除数据

  • 语法格式:

delete from 表名 where 条件;

注意: 没有条件全部删除

  • 删除所有记录?

delete from dept1;

  • 怎么删除大表中的数据?(重点)

truncate table 表名; // 表被截断,不可回滚,永久丢失

  • 删除表

drop table 表名; // 这个通用。
drop table if exists 表名; // oracle不支持这种写法

对于表结构的修改,这里不讲了,大家使用工具完成即可,因为在实际开发中表一旦 设计好之后,对表结构的修改是很少的,修改表结构就是对之前的设计进行了否定,即使 需要修改表结构,我们也可以直接使用工具操作。修改表结构的语句不会出现在Java代码当中。 出现在java代码当中的sql包括:insert delete update select(这些都是表中的数据操作)

  • 增删改查有一个术语:CRUD操作

Create(增) Retrieve(检索) Update(修改) Delete(删除)