7.索引
通过索引(index)帮组我们高效获得数据的结构
:提取句子主干,可以得到索引的本质:索引是数据结构
7.1 索引的分类
一个表中主键索引只有一个,唯一索引可以不只一个
-
主键索引(primary key)
-
- 唯一的标识,不能重复,只有一个列是主键
-
唯一索引(unique key)
-
- 避免重复的列出现,可以重复,多个列可以标识唯一索引
-
常规索引(key/index)
-
- 默认的 index,key 关键字来设置
-
全文索引:(fulltext)
-
- 在特定的数据库引擎才有,
- 快速定位数据
基础语法
--索引的使用:
--在创建表的时候给字段增加索引
--创建完毕时,增加索引
--显示所有的索引信息
show index from table1
--增加一个全文索引(索引名)列名
1. alert 数据库.table add fulltext index 索引名 (列名)
2. create index 索引名 on table (字段 )
explain 分析sql执行情况
explain select * from table1; ---非全文索引
explain select * from table1 where match (索引名) against ('要锁定的字符')
7.2 测试索引
delilmiter $$ --写函数必须写,标志
create function mock_data()
return int
begin
end
索引在大数据时,区别十分明显,特别快
7.3 索引原则
- 索引不是越多越好
- 小数据不需要索引
- 索引一般加在查询的字段上
- 不要对进程变动的字段加索引
索引的数据结构:
INNodb:Btree
8.权限管理和备份
8.1 用户管理
SQLyog可视化用户管理
SQL命令:
用户表:mysql.user
本质:对用户表增删改查
--创建用户
create user用户名 identitfied by 密码
--修改密码
--1.当前用户
set password = password('mima')
--2.指定用户
set password for 用户 = password('mima')
-- 重命名
rename user 原用户 to 新用户
--用户授权
--all privileges:全部的权限 ,除了给别人授权;
--*.*:全部的库,表,
grant all privileges on *.* to 用户
--查看指定用户权限
show grants for 用户
--查看主机权限
show grants for root@localhost
--撤销权限
revoke all privileges on *.* from 用户
8.2 数据库备份
- 保证重要的数据不丢失
- 数据转移
备份方式:
-
直接拷贝物理文件(data)
-
在sqlyog可视化工具中手动导出
-
命令行导出:mysqldump
-
mysqldump -h 主机 -u 用户名 -p 密码 数据库 表名 > 导出的位置 --导出一张表 mysqldump -h 主机 -u 用户名 -p 密码 数据库 表名1,表2,表3 > 导出的位置 --导出多张表 mysqldump -h 主机 -u 用户名 -p 密码 数据库 > 导出的位置 --导出数据库 --导入 --登陆的情况下,切换到数据库的位置 --source 备份文件 source 文件
9 规范数据库设计
当数据库比较复杂的时候,需要设计
差的数据库设计:
-
数据冗余,浪费空间
数据插入和删除麻烦,异常多
程序性能差
优秀的数据库:
- 节省内存
- 保证数据库的完整性
- 方便开发
设计:
- 分析需求:分析业务和处理的数据库的需求
- 概要设计:设计关系图,e_r图
步骤(博客网站):
-
收集信息,分析需求
-
-
用户表(用户登录,个人信息,写博客,创建分类)
-
分类表(文章分类)
-
评论表
-
文章表(文章的信息)
-
友链表(友链信息)
-
自定义表
-
-
标识实体(把需求落地字段)
-
标识实体之间的关系:
-
- 写博客: user-> blog
- 创建分类:user->category
- 关注:user ->user
- 友链:links
- 评论表 user-> user -blog
数据库的三大范式
第一范式(1NF):原子性,每一列不可分
第二范式:前提:满足第一范式,每张表只描述一件事
第三范式:前提是第二范式:,确保每个属性都和主键直接相关。
10 JDBC
应用程序 – JDBC----数据库驱动 --数据库
对于开发人员说,jdbc要学习
java.sql
javax.sql
- 安装JDBC,导入jar包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WJPeAcER-1592360936599)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200616204152174.png)]
-
先复制到自己建立的lib文件夹,然后在ADD as library
-
测试代码:
//1 .加载驱动 Class.forName("com.mysql.jdbc.Driver") //2.用户信息和URL jdbc:mysql://主机地址:3306/数据库名?参数1&参数2&参数3. String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&charaterEncoding" String username = "root"; String password = "123"; //3 连接成功,connection:数据库对象 //connection 数据库对象,可以有 事务提交,回滚,,,, Connection connection = DriverManager.getConnection(url,username,password); //4.执行sql对象,statement :执行sql的对象 Statement statement = connection.createStatement(); //5. SQL语句 String sql = "select * from users" //6 根据sql语句导入statement对象,执行,返回查询的结果集 ResultSet resultset = statement.executeQuery(sql);//返回结果集 // 7释放连接 result.closes(); statement.close(); connection.close(); //connection 数据库对象,可以在数据库级别执行 事务提交,回滚,,,, //statement:sQL对象 statement.executeQuery()//查询,返回结果集 statement.execute();//执行任何语句 statement.executeUpdate();//更新,插入,删除,返回受影响行数 // resultset 结果集 resultset.getObject();//不知道列的类型执行,知道列的类型就执行具体的方法。 resultset.getString(); resultset.getInt(); ...
// resultset 遍历: resultset.next():移动到下一个数据 resultset.previous():移动到前一行 resultset.absolute(row):移动指定行
statement对象
jdbc中:statement对象用于向数据库发送SQL语句,想完成数据库的增删改查,只需要这个对象向数据库发送查询语句即可。
// 增删改------executeUpdate
//executeUpdate完成数据插入
Statement st = connection.createStatement();
String sql = "insert into user(...)values(....)";
int num = st,executeUpdate(sql);
if (num>0){
system.out.ptint("插入成功")
}
————————————————————————————————————————————
//executeUpdate完成数据删除
Statement st = connection.createStatement();
String sql = "delete from user where id = 1";
int num = st,executeUpdate(sql);
if (num>0){
system.out.ptint("删除成功")
}
______________________________________________
//executeUpdate数据修改
Statement st = connection.createStatement();
String sql = "update user set name = "hhh" where name = "dd";
int num = st,executeUpdate(sql);
if (num>0){
system.out.ptint("修改成功")
}
//查询用executeQuery,返回数据集
Statement st = connection.createStatement();
String sql = "select * from users"
ResultSet resultset = st.executeQuery(sql);//返回结果集
常规写法:
在java上src文件目录下创建properties配置文件
//第一步配置文件db.propeties
driver = com.mysql.jdbc.Driver
url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&charaterEncoding"
username = "root";
password = "123";
//第二写工具类,加载配置文件,加载驱动
public class jdbcUtils{
private static String driver = null; //提升作用域,下面用的static,这里也用
private static String url = null;
private static String usename = null;
private static String password = null;
static{
try{
IntpuStream in = jdbcUtils.class.getClassLoader().getResourceAsStream("db.propeties");
//利用反射读取jdbcUtils类所在目录的配置文件的信息
Properties properties = new Properties();//创建配置对象流
properties.load(in);//加载输入流
driver = properties.getProperty("driver");
url = properties.getProperty("driver");
usename = properties.getProperty("driver");
password = properties.getProperty("driver");
class.forName("driver");//加载驱动
}catch(Exception e){
e.printStackTrace ();
}
}
//获取连接
public static Connection getConnection() throws SQLException{
return DriverManager.getConnection(url,username,password);
}
//释放资源
public void static release(Connection conne,Statement st,ResultSet rs ){
if(rs!=null){
rs.close();
} if(st!=null){
st.close();
}
}if(conn!=null)
{
conn.close();
}
}
//第三部,java调用数据库
SQL 注入问题
sql存在漏洞,导致数据泄露 :SQL语句被拼接or,
PreparedStatement:防止SQL注入,效率高
是Statement 的子类
//第一步配置文件db.propeties
driver = com.mysql.jdbc.Driver
url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&charaterEncoding"
username = "root";
password = "123";
//第二写工具类,加载配置文件,加载驱动
public class jdbcUtils{
private static String driver = null; //提升作用域,下面用的static,这里也用
private static String url = null;
private static String usename = null;
private static String password = null;
static{
try{
IntpuStream in = jdbcUtils.class.getClassLoader().getResourceAsStream("db.propeties");
//利用反射读取jdbcUtils类所在目录的配置文件的信息
Properties properties = new Properties();//创建配置对象流
properties.load(in);//加载输入流
driver = properties.getProperty("driver");
url = properties.getProperty("driver");
usename = properties.getProperty("driver");
password = properties.getProperty("driver");
class.forName("driver");//加载驱动
}catch(Exception e){
e.printStackTrace ();
}
}
//获取连接
public static Connection getConnection() throws SQLException{
return DriverManager.getConnection(url,username,password);
}
//释放资源
public void static release(Connection conne,Statement st,ResultSet rs ){
if(rs!=null){
rs.close();
} if(st!=null){
st.close();
}
}if(conn!=null)
{
conn.close();
}
}
//第三步,java调用数据库插入
public class testInsert{
public static void main(string [] args){
Connection conn = null;//扩大作用域
PrepareStatement st = null;//创建PrepareStatement对象
try{
conn = jdbcUtils.getConnection();
//区别
//使用?占位符代替参数
String sql = "insert into user (id,name,password,birthday) values (?,?,?,?)"
st = conn.prepareStatement(sql);//预编译SQL,先写,然后先不执行
//手动给参数赋值
st.setInt(1,4);
st.setString(2,"手动");
st.setString(3,"123");
//注意:下面的参数需要的是数据库的date,先要在java程序中
//获得new Date().getTime()时间戳。
st.setDate(4,new java.sql.Date(new Date().getTime()));
//执行
int i = st.executeUpdate();
if (i>0){
System.out.print("执行成功")
}
}catch(Excetipn e){
e.printStackTrae();
}finally{
jdbcUtils.release(conn,st.rs);
}
}
}
//第四步java调用数据库删除
public class testInsert{
public static void main(string [] args){
Connection conn = null;//扩大作用域
PrepareStatement st = null;//创建PrepareStatement对象
try{
conn = jdbcUtils.getConnection();
//区别
//使用?占位符代替参数
String sql = "delete from user where id =?"
st = conn.prepareStatement(sql);//预编译SQL,先写,然后先不执行
//手动给参数赋值
st.setInt(1,4);
int i = st.executeUpdate();
if (i>0){
System.out.print("执行成功")
}
}catch(Excetipn e){
e.printStackTrae();
}finally{
jdbcUtils.release(conn,st.rs);
}
}
}
//第⑤步java调用数据库更新
public class testInsert{
public static void main(string [] args){
Connection conn = null;//扩大作用域
PrepareStatement st = null;//创建PrepareStatement对象
try{
conn = jdbcUtils.getConnection();
//区别
//使用?占位符代替参数
String sql = "update user set name = ? where id = ?"
st = conn.prepareStatement(sql);//预编译SQL,先写,然后先不执行
//手动给参数赋值
st.setString(2,"手动");
st.setString(3,"123");
//执行
int i = st.executeUpdate();
if (i>0){
System.out.print("执行成功")
}
}catch(Excetipn e){
e.printStackTrae();
}finally{
jdbcUtils.release(conn,st.rs);
}
}
}
//java查询
public class testInsert{
public static void main(string [] args){
Connection conn = null;//扩大作用域
PrepareStatement st = null;//创建PrepareStatement对象
ResultSet rs = null;
try{
conn = jdbcUtils.getConnection();
//区别
//使用?占位符代替参数
String sql = "select * from user where id = ?"
st = conn.prepareStatement(sql);//预编译SQL,先写,然后先不执行
//手动给参数赋值
st.setInt(1,4);
rs = st.executeQuery();
while (rs.next()){
System.out.print(rs.getString("name"));
}
}catch(Excetipn e){
e.printStackTrae();
}finally{
jdbcUtils.release(conn,st.rs);
}
}
}
prepareStatement防止注入的本质:把传递的参数当做字符
存在转义字符直接忽略
数据库连接池
数据库 - -连接 – 释放资源:十分浪费资源
池化技术:
准备预先的资源,过来就连接准备好的。
最小连接数
最大连接数
等待时间
编写连接池,实现一个接口DataSource
开源数据源实现
- DBcp
- C3p0
- Druid:阿里
使用这些数据库连接池,就不要在项目开发中编写连接数据库的代码
DBCP
先导入对应jar包,然后利用对应的方法加载驱动,