一、SQL语句分类
- DQL(数据查询语言):查询语句
- DML(数据操作语言):insert delete update,对表当中的数据进行增删改
- DDL(数据定义语言):create drop alter,对表结构的增删改
- TCL(事务控制语言):commit提交事务,rollback回滚事务。
- DCL(数据控制语句):grant授权、revoke撤销权限等。
二、对数据库操作
- show databases; 查看有哪些数据库
- create database xxxxx;创建数据库
- use xxxxx;使用数据库
- show tables;查看有哪些表
- show tables from xxxx 查看其他库中的表
- source 文件全路径 初始化数据
- drop database xxxxx; 删除数据库操作
- desc xxx; 查看表结构
- select database();查看当前使用的是哪个数据库
- select version(); 查看mysql的版本号
- exit 退出mysql
- show create table xxxx 查看创建表的语句
三、DQL 对数据查询
-
条件查询
语法格式: select 5 字段,字段... from 1 表名 where 2 条件 group by 3 分组 having 4 条件 order by 6 字段 排序方式; limit 7 ......
-
between…and…
- 使用在数字方面(闭区间)
select ename,sal from emp where sal between 1100 and 3000;
- 使用在字符串方面(左闭右开)
select ename from emp where ename between 'A' and 'B';
-
is null 、is not null
- null为空,没有数据,不是为0
-
and和or的优先级
- and和or在一块查询,and的优先级大于or
-
in的使用
//查询工作岗位是SALESMAN和SALESMAN的员工 select ename,job form emp where sal in ('SALESMAN','MANAGER'); //查询工作岗位不是SALESMAN和SALESMAN的员工 select ename,job form emp where sal not in ('SALESMAN','MANAGER');
-
模糊查询like
- %表示任意多个字符,_代表任意1个字符
//查询名字中带o字母的 select ename from emp where ename like '%o%'; //查询名字中第二个字母是A的 select ename from emp where ename like '_A%'; //查询名字中带下划线的 select ename from emp where ename like '%\_%';
-
排序
//默认升序 select eanme , sal from emp order by sal; //升序 select ename , sal from emp order by sal asc; //降序 select ename ,sal from emp order by sal desc; //按照工资的降序排列,当工资相同的时候在按照名字的升序排列 select ename ,sal from emp order by sal desc,ename asc; //根据第几个字段排序 select ename,sal from emp order by 3 desc; //随机根据某个字段排序 select ename,sal from emp order by rand() ;//select rand()返回0-1中的一个小数,这里自动取第一个数字,字段数不够则为1
-
ifnull()
//所有数据库都是这样规定的,只要有NULL参与的运算结果一定的null //如果comm为空就当做0来计算 ifnull(comm,0)
-
多行处理函数,会自动忽略null
-
当一条语句中有group by 的话,select 后面只能跟分组函数和参与分组的字段
-
distinct去重
//去除重复的job select distinct job from emp; //联合去重,放在字段最前面 select distinct deptno ,job from emp; //统计岗位的数量 select count(distinct job) from emp;
-
等值连接
//查询每个员工的部门,要求显示员工名和部门名 select e.ename,d.dname from emp e join dept d on e.deptno = d.deptno;
-
非等值连接
//查询每个员工的薪资等级 select e.ename,s.grade from emp e inner join //inner可以省略 salgrade s on e.sal between s.losal and s.hisal ;
-
自连接
//找出每个员工的上级领导 select e1.eanme as '员工',e2.ename as '领导' from emp e1 inner join emp e2 on e1.mgr = e2.empno;
-
外连接
//找出每个员工的上级领导(包括老板) select e1.ename as '员工',e2.ename as '领导' from emp e1 left outer join //outer可以省略 emp e2 on e1.mgr = e2.empno;
-
where子句中使用查询
//查询高于平均工资的员工信息 select * from emp where sal > (select avg(sal) from emp);
-
from 后嵌套子查询
//找出每个部门平均薪水的薪资等级 select t.deptno ,s.grade from (select deptno , avg(sal) as avgsal from emp group by deptno) t join salgrade s on t.avgsal between s.losal and s.hisal;
-
select 后嵌套子查询
//找出每个员工所在的部门名称,要求显示员工名和部门名 select //通过e.ename 的信息去后面的子查询里去查 e.eanme,(select d.dname from dept d where e.deptno = d.deptno) as dname from emp e;
-
union(可以将查询结果集相加)
select ename,job from emp where job = 'MANAGER' union select ename,job from emp where job = 'SALESMAN';
-
limit
//取出工资前5名的员工 select ename,sal from emp order by sal desc limit 0,5; //取出工资排名在第4到第9名的员工 select ename,sal from emp order by sal desc limit 3,6;
四、DML 对表当中的数据进行增删改
-
insert语句插入数据
//字段的数量和值的数量相同,并且数据类型要对应相同。 insert into 表名 //字段可以忽略不写,但是后面的value对数量和顺序都有要求 (字段名1,字段名2,字段名) values //可以插入多行数据 (值1,值2,值3), (值1,值2,值3), (值1,值2,值3); //当一条insert语句执行成功之后,表格当中必然会多一行记录 //即使多的这一行记录当中的某些字段的NULL,后期也没有办法在执行insert语句插入数据了,只能使用update进行更新
-
将查询结果插入到一张表中
//有表结构的要求 insert into 表名 select语句
-
修改表中的数据
//没有where就是修改所有记录 update 表名 set 字段名1=值2,字段名2=值2....where 条件;
-
删除数据
//没有where就是删除所有记录 delete from 表名 where 条件; //删除大表 truncate table 表名; //表被截断,不可回滚,永久丢失
五、DDL 对表结构的增删改
-
建表语句
create table 表名( //默认为null(可以不写,也可以修改默认值) 字段名1 数据类型 default null, 字段名2 数据类型, 字段名3 数据类型, ...... );
-
MySQL当中字段的数据类型
1. int 整数型
2. bigint 长整型(java中的long)
3. float 浮点型 (java中的flaot和double)
4. char 定长字符串(java中的String)
5. varchar 可变长字符串 255个字符(java中的StringBuffer和StringBuilder)
6. data 日期类型(java中java.sql.Data类型)
7. BLOB 二进制大对象(图片,视频等)
8. CLOB 字符大对象(存储大文本) -
删除表
//如果该表存在就删除 drop table if exists 表名;
-
复制表
//将查询结果当作表创建出来 create table 表名 as select语句;
六、约束
-
常见约束
- 非空约束(not null)约束的字段不能为null
- 唯一约束(unique)约束的字段不能重复
- 主键约束(primary key)约束的字段既不能为null也不能重复(简称PK)
- 外键约束(foreign key)(简称FK)
- 检查约束(check)Oracle数据库支持,mysql不支持
-
非空约束 not null
drop table if exists t_user; create table t_user( id int, username varchar(255) not null,//只能加到字段后面 password varchar(255) );
-
唯一性约束(不能重复但是可以为null)
drop table if exists t_user; create table t_user( id int, username varchar(255) unique//列级约束 ); drop table if exists t_user; create table t_user( id int, username varchar(255), usercode varchar(255), //两个字段联合不重复(看作一个字段),表级约束 unique(username,usercode) );
-
主键约束
drop table if exists t_user; create table t_user( //主键,不能为null,也不能重复 id int primary key,//列级约束 username varchar(255), email varchar(255) ); drop table if exists t_user; create table t_user( id int , username varchar(255), email varchar(255), primary key (id)//表级约束 );
-
主键分类
- 通过主键字段的字段数量分类
- 单一主键
- 复合主键(多个字段联合起来添加一个主键约束)
- 通过主键性质来分类
- 自然主键(跟业务没有任何关系的自然数)
- 业务主键(主键值跟系统的业务挂钩)
- 通过主键字段的字段数量分类
-
主键自增
drop table if exists t_user; create table t_user( //id字段自动维护一个自增的数字,从1开始,以1递增 id int primary key auto_increment, );
-
-
外键约束
drop table if exists t_student; drop table if exists t_class; create table t_class( cno int, cname varchar(255), primary key(cno) ); create table t_student( sno int, sname varchar(255), classno int, primary key(sno), //以t_class表中的cno字段为约束 foreign key(classno) references t_classs(cno) );
- 外键可以为null
- 外键字段引用其他表的某个字段的时候,被引用的字段不一定是主键,但必须有唯一性约束unique
七、 存储引擎
- MyISAM存储引擎
- 不支持事务
- mysql最常用的存储引擎,但不是默认的
- 可被压缩,节省存储空间。并且可以转换为只读表,提高检索效率
- 采用三个文件组织一张表
- xxx.frm(存储格式的文件)
- xxx.MYD(存储表中数据的文件)
- xxx.MYI(存储表中索引的文件)
- InnoDB存储引擎
- mysql默认缺省的存储引擎
- 支持事务、行级锁、外键,这种存储引擎数据最安全
- 数据存储在tablespace这样的表空间中(逻辑概念),无法被压缩,无法转换成只读
- 数据库崩溃之后提供自动恢复机构
- MEMORY存储引擎
- 不支持事务
- 数据容易丢失,因为所有数据和索引都是存储在内存当中
- 查询速度最快
八、TCL 事务
-
和事务相关的只有DML语句(insert delete update)
-
四大特征:ACID
- 原子性:事务是最小的工作单元,不可再分
- 一致性:事务必须保证多条DML语句同时成功或者同时失败
- 隔离性:各个事务之间具有隔离
- 持久性:持久性说的是最终数据必须持久化到硬盘文件中,事务才算成功的结束。
-
隔离性级别
- 读未提交(read uncommitted)
对方事务好没有提交,我们当前事务可以读取到对方未提交的数据,存在脏读现象,表示读到了脏的数据 - 读已提交(read committed)(oracle默认)
对方事务提交之后的数据我方可以读到
读已提交存在的问题:不可重复读 - 可重复读(repeatable read)(mysql默认)
解决了不可重复读
只读到开启事务时的数据
存在的问题:读取到的数据是幻象 - 序列化读/串行化读(serializable)
效率低,需要事务排队
- 读未提交(read uncommitted)
-
关闭musql自动提交
start transaction;
-
设置全局的事务隔离级别
set global transaction isolation level 级别;
-
查看隔离级别
select @@global.tx_isolation;
-
提交事务
commit;
-
回滚事务
rollback;
九、索引
-
什么时候考虑给字段添加索引
- 数据量庞大
- 该字段很少的DML操作
- 该字段经常出现在where子句中
-
主键和具有uniqe约束的字段会自动添加索引
-
查看sql语句的执行计划
explain sql语句;
-
添加索引
//给emp表中的sal字段创建索引 create index emp_sal_index on emp(sal);
-
索引底层采用的数据结构是:B+Tree
-
索引的实现原理
-
索引的分类
- 单一索引:给单个字段添加索引
- 复合索引:给多个字段联合添加索引
- 主键索引:主键上会自动添加索引
- 唯一索引:有unique约束的字段上会自动添加加索引
-
什么时候失效
模糊查询的时候,第一个通配符使用的是%,这个时候索引会失效
十、视图
-
创建和删除
//创建,以DQL语句创建视图 create view myview as select empno ,ename from emp; //删除 drop view myview;
-
对试图增删改查会影响到原表数据
-
视图可以隐藏表的实现细节
十二、DBA命令
- 将数据库当中的数据导出(在DOS命令窗口下)
- 导出指定库
mysqldump 数据库名>路径 -uroot -p333 - 导出指定表
mysqldump 数据库名 表名>路径 -uroot -p333
- 导出指定库
- 导入数据
source 文件
十三、数据库设计三范式
- 第一范式:任何一张表都应该有主键,并且每一个字段原子性不可再分
- 第二范式:建立在第一范式的基础之上,所有非主键字段完全依赖主键,不能产生部分依赖。
多对多三张表,关系表两个外键 - 第三范式:建立在第二范式的基础上,非主键字段不能传递依赖于主键字段(不能产生传递依赖 )
一对多两张表,多的表加外键 - 在实际开发中,以满足客户的需求为主,有时候会拿冗余换执行速度
- 一对一设计 两种方案
- 主键共享
- 外键唯一
十四、乐观锁和悲观锁
- 乐观锁
可以多个事务并发对某些记录进行操作,但是记录后面会有版本号 - 悲观锁
select ename,job,sal from emp where ename='zhangsan' //当前事务没有结束的时候,其他事务不能修改eame为张三 这条数据(会等待当前事务提交) for update;
十五、JDBC
-
六个步骤
- 注册驱动
- 获取连接(表示JVM进程和数据库进程之间的通道打开了,者属于进程之间的通信,重量级的,使用完之后一定要去关闭)
- 获取数据库操作对象
- 执行SQL语句
- 处理查询结果集
- 释放资源
-
注册驱动
//第一中方式 java.sql.Driver driver = new com.mysql.jdbc.Driver(); DriverManager.registerDriver(driver); //第二种方式 通过类加载的方式注册驱动(静态代码块执行完成驱动的注册) Class.forName("com.mysql.jdbc.Driver");
-
获取连接
/* url:统一资源定位符,包括协议、IP、PORT、资源名 url:jdbc:mysql://127.0.0.1:3306/wangxiangqian jdbc:mysql:// 协议 127.0.0.1 IP地址 3306 mysql数据库端口号 wangxiangqian 具体数据库实例名 */ Connection conn = DriverManager.getConnection(url,user,password);
-
获取数据库操作对象
//第一种方式 Statement stmt = conn.createStatement(); //第二种方式 //预编译的数据库操作对象,预先对sql语句框架进行编译,然后再传值(避免了sql注入现象) //?不能用单引号括起来 String sql = "select * from t_user where loginName = ? and loginPwd = ?" PreparedStatement ps = conn.prepareStatement(sql); //给占位符?传值,下标从1开始 ps.setString(1,loginName); ps.setString(2,loginPwd); //执行sql语句,获取结果集 ResultSet rs = ps.executeQuery();
-
执行SQL语句
String sql = "insert into dept(deptno,dname,loc) values(50,'人事部','北京')"; //专门执行DML语句,返回值是影响记录条数 int count = stmt.executeUpdate(sql); String sql = "select empno,ename,sal from emp " //执行查询语句,返回查询结果集 ResultSet rs = stmt.executeQuery(sql);
-
处理查询结果集
while(rs.next()){ //不管数据库中是什么类型,都以String的形式取出 String s = rs.getString(列的下标);//JDBC中的下标从1开始 //以列的名字获取数据,sql语句中的名字 int i = rs.getInt(列的名字); }
-
释放资源
//从小到大依次关闭 if(rs!=null){ rs.close(); } if(stmt!=null){ stmt.close(); } if(conn!=null){ conn.close(); }
-
PreparedStatement和Statement比较
- Statement存在sql注入问题
- Statement编译一次运行一次,PreparedStatement编译一次,运行n次 效率高
- PreparedStatement会在编译阶段做类型的安全检查
-
JDBC事务机制
//获取连接后,将自动提交机制修改为手动提交 conn.setAutoCommit(false);//开启事务 //提交事务 conn.commit(); //回滚事务 conn.rollback();