数据库的英文单词:DataBase 简称:DB
用于存储和管理数据的仓库.
特点:1.持久化存储数据的,其实数据库就是一个文件系统
2.方便存储和管理数据
3 使用了统一的方式操作数据库 SQL
结构化查询语言
其实就是定义了操作所有关系型数据库的规则.每一种数据库操作的方式存在不一样的地方,称为"方言"
1.SQL语句可以单行或多行书写,以分好结尾.
2.可使用空格和锁紧来增强语句的可读性.
3.MySQL数据库的SQL语句不区分大小写,关键字建议使用大写.
4.3种注释
单行注释: -- 注释内容 或 # 注释内容(MySQL特有)
多行注释:/*注释*/
1.DDL(Data Definition Language)数据定义语言
用来定义数据库对象:数据库,表,列等.关键字:create(增加),drop(删除),alter(修改),show(查询),modify(修改),change(修改),add(添加)等
2.DML(Data Manipulation Languat)数据操作语言
用来对数据库中表的数据进行增删改.关键字:insert,delete,update等
3.DQL(Data Query Language)数据查询语言
用来查询数据空中表的记录(数据).关键字:select,where等
4.DCL(Data CAontrol Language)数据控制语言(了解)
用来定义数据库的访问权限和安全级别,及创建用户.关键字:GRANT,REVOKE等.
1. 操作数据库:CRUD
1. C(Create):创建
* 创建数据库:
* create database 数据库名称;
* 创建数据库,判断不存在,再创建:
* create database if not exists 数据库名称;
* 创建数据库,并指定字符集
* create database 数据库名称 character set 字符集名;
* 练习: 创建db4数据库,判断是否存在,并制定字符集为gbk
* create database if not exists db4 character set gbk;
2. R(Retrieve):查询
* 查询所有数据库的名称:
* show databases;
* 查询某个数据库的字符集:查询某个数据库的创建语句
* show create database 数据库名称;
3. U(Update):修改
* 修改数据库的字符集
* alter database 数据库名称 character set 字符集名称;
4. D(Delete):删除
* 删除数据库
* drop database 数据库名称;
* 判断数据库存在,存在再删除
* drop database if exists 数据库名称;
5. 使用数据库
* 查询当前正在使用的数据库名称
* select database();
* 使用数据库
* use 数据库名称;
2. 操作表
1. C(Create):创建
1. 语法:
create table 表名(
列名1 数据类型1,
列名2 数据类型2,
....
列名n 数据类型n
);
* 注意:最后一列,不需要加逗号(,)
* 数据库类型:
1. int:整数类型
* age int,
2. double:小数类型
* score double(5,2)
3. date:日期,只包含年月日,yyyy-MM-dd
4. datetime:日期,包含年月日时分秒 yyyy-MM-dd HH:mm:ss
5. timestamp:时间错类型 包含年月日时分秒 yyyy-MM-dd HH:mm:ss
* 如果将来不给这个字段赋值,或赋值为null,则默认使用当前的系统时间,来自动赋值
6. varchar:字符串
* name varchar(20):姓名最大20个字符
* zhangsan 8个字符 张三 2个字符
* 创建表
create table student(
id int,
name varchar(32),
age int ,
score double(4,1),
birthday date,
insert_time timestamp
);
* 复制表:
* create table 表名 like 被复制的表名;
2. R(Retrieve):查询
* 查询某个数据库中所有的表名称
* show tables;
* 查询表结构
* desc 表名;
3. U(Update):修改
1. 修改表名
alter table 表名 rename to 新的表名;
2. 修改表的字符集
alter table 表名 character set 字符集名称;
3. 添加一列
alter table 表名 add 列名 数据类型;
4. 修改列名称 类型
alter table 表名 change 列名 新列别 新数据类型;
alter table 表名 modify 列名 新数据类型;
5. 删除列
alter table 表名 drop 列名;
4. D(Delete):删除
* drop table 表名;
* drop table if exists 表名 ;
1. 添加数据:
* 语法:
* insert into 表名(列名1,列名2,...列名n) values(值1,值2,...值n);
* 注意:
1. 列名和值要一一对应。
2. 如果表名后,不定义列名,则默认给所有列添加值
insert into 表名 values(值1,值2,...值n);
3. 除了数字类型,其他类型需要使用引号(单双都可以)引起来
2. 删除数据:
* 语法:
* delete from 表名 [where 条件]
* 注意:
1. 如果不加条件,则删除表中所有记录。
2. 如果要删除所有记录
1. delete from 表名; -- 不推荐使用。有多少条记录就会执行多少次删除操作
2. TRUNCATE TABLE 表名; -- 推荐使用,效率更高 先删除表,然后再创建一张一样的表。
3. 修改数据:
* 语法:
* update 表名 set 列名1 = 值1, 列名2 = 值2,... [where 条件];
* 注意:
1. 如果不加任何条件,则会将表中所有记录全部修改。
1. 语法:
select
字段列表
from
表名列表
where
条件列表
group by
分组字段
having
分组之后的条件
order by
排序
limit
分页限定
2. 基础查询
1. 多个字段的查询
select 字段名1,字段名2... from 表名;
* 注意:
* 如果查询所有字段,则可以使用*来替代字段列表。
2. 去除重复:
* distinct
3. 计算列
* 一般可以使用四则运算计算一些列的值。(一般只会进行数值型的计算)
* ifnull(表达式1,表达式2):null参与的运算,计算结果都为null
* 表达式1:哪个字段需要判断是否为null
* 如果该字段为null后的替换值。
4. 起别名:
* as:as也可以省略
3. 条件查询
1. where子句后跟条件
2. 运算符
* > 、< 、<= 、>= 、= 、<>
* BETWEEN...AND 小的放前面
* IN( 集合) 多个or使用in方便
* LIKE:模糊查询
* 占位符:
* _:单个任意字符
* %:多个任意字符
* IS NULL
* and 或 &&
* or 或 ||
* not 或 !
1.排序查询
语法:order by 子句
order by 排序字段1,排序方式2, 排序字段2,排序方式2.....
排序方式:
ASC:升序
DESC:降序
注意:如果有多个排序条件,则当前边的条件值一样时,才会判断第二条件
2.聚合函数:将一列数据作为一个整体,进行纵向的计算
1.count:计算个数 一般选择非空的列,主键
2.max:计算最大值
3.min:计算最小值
4.sum:计算和
5.avg:计算平均数
注意:聚合函数的计算,排除空null值,聚合函数后面也可以加条件
解决方案:1.选择不包含空的列进行计算 2.ifnull函数.
3.分组查询:
语法:group by 分组字段;
注意:1).分组之后查询的字段:分组字段,聚合函数(不要查找私有的数据)
2).wherehe having 的区别?
1.where在分组之前进行限定,如果不满足条件,则不参入分组,having在分组之后限定,如果不满足结果,则不会被查询出来
2.where后不可以跟聚合函数,having可以跟聚合函数
4.分页查询:
1.语法:limit 开始的索引,每页查询的条数
2.公式:开始的索引= (当前的页码 - 1)*每页显示的条数
3.分页操作是一个MySQL"方言"
1.概述:对表中的数据进行限定,保证数据的正确性,有效性和完整性.
2.分类:
1).主键约束:primary key
2).非空约束:not null
3).唯一约束:unique
4).外键约束:foreign key
1.创建表时添加非空约束.
create table 表名(
字段的名字 数据类型 not null
);
2.创建表完后,添加非空约束 要求:数据不能为空
alter table表名 modify 字段的名字 字段数据类型 not null
3.删除列的非空约束
alter table表名 modify 字段的名字 字段数据类型
1.创建表时添加唯一约束.---->注意:唯一对null没有效果
create table 表名(
字段的名字 数据类型 unique
);
注意:MySQL中,唯一约束限定的列的值可以有多个null.
2.创建表完后,添加非空约束 要求:这一列数据中不能为重复的
alter table表名 modify 字段的名字 字段数据类型 uniqur
3.删除唯一约束:alter table 表名 drop index 字段的名字.
1.在创建表时,可以添加外键 --->约束表与表的关系,从而保证数据的正确性,完整性,安全性
*语法:create table 表名(
......
外键列
constraint 外键名称 foreign key (外键列的名称) reference 主表的名称(主表列名称)
)
2.删除外键
*语法:alter table 表名 drop foreign key 外键名字;
3.添加外键
*语法:alter table 表名 add constraint 外键名称 foreign key (外键列的名称) reference 主表的名称(主表列名称)
3.1 如果没有给定外键名,我们需要<show create table 表名:> 来去查询
4.级联操作(最好不会)
*语法:alter table 表名 add constraint 外键名称 foreign key (外键列的名称) reference 主表的名称(主表列名称) on update cascade
on delete cascade;
分类:级联更新on update cascade
级联删除on delete cascade
1.多表之间的关系
*一对一(了解):
如:人和身份证 分析:一个人只有一个身份证,一个身份证只能对应一个人
*一对多(多对一)
如:部门和员工 分析:一个部门有多个员工,一个员工只能对应一个部门
*多对多:
如:学生和课程 分析:一个学生可以选择很多门课程,一个课程也可以被很多学生选择
1.一对多(多对一):
如:部门和员工
实现方式:在多的一方建立外键,指向一的一方的主键
2.多对多:
如:学生和课程
实现方式:需要借助第三张中间表,中间表至少包含两个字段,这两个字段作为第三张表的外键, 分别指向两张表的主键 联合组建一般都出现在中间表中
3.一对一(了解):
如:人和身份证
实现方式:可以在任意一方添加唯一外键指向另一方的主键
1.概念:
设计数据库时,需要遵循的一些规范.
设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范 式,各种范式呈递次规范,越高的范式数据库冗余越小。
目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。
分类:
第一范式(1NF):每一列都是不可分割的原子数据项
存在的问题:1.存在非常严重的数据冗余(重复)
2.数据添加灿在问题:添加时容易数据不合法
3.数据删除也存在问题,删除一个数据时容易将主码数据全部删除.
第二范式(2NF):在1NF的基础上,非码属性必须完全依赖与候选码(在1NF基础上消除非主属性对主码的部分函数依赖)
几个概念:
1.函数依赖:A-->B,如果通过A属性(属性组)的值,可以确定唯一B属性的值。则称B依赖于A
2.完全函数依赖:A-->B, 如果A是一个属性组,则B属性值得确定需要依赖于A属性组中所有的属性值。
3.部分函数依赖:A-->B, 如果A是一个属性组,则B属性值得确定只需要依赖于A属性组中某一些值即可。
4.传递函数依赖:A-->B, B -- >C . 如果通过A属性(属性组)的值,可以确定唯一B属性的值,在通过B属性(属性组)的值可以确定唯一C属性的值,则称 C 传递函数依赖于A
5.码:如果在一张表中,一个属性或属性组,被其他所有属性所完全依赖,则称这个属性(属性组)为该表的码
* 主属性:码属性组中的所有属性
* 非主属性:除过码属性组的属性
第三范式(3NF):在2NF的基础上,任何非主属性不依赖于其他非主属性(在2NF基础上消除传递依赖)
1.查询语法:
select 列名表名 from 表名列表 where.....
笛卡尔积:
有两个集合A,B 取这两个集合的所有组合情况.
要完成多表查询,需要取消无用的数据
2.多表查询的分类:
1.内连接查询:
a.隐式内连接:使用where条件消除无用数据(百分百用)
b.显示内连接:
语法:select 字段列表 from 表名1 [inner] join 表名2 on 条件
c.注意事项:
1.从哪些表中查询数据
2.查询的条件
2.外链接查询:
a.左外连接:
语法:select 字段列表 from 表名1 left {outer} join 表二 on 条件
查询的是左边表的所有数据及其交集部分
b.右外连接:
语法:select 字段列表 from 表名1 right {outer} join 表二 on 条件
查询的是右边表的所有数据及其交集部分
3.子查询
概述:查询中嵌套查询,称嵌套查询为子查询
不同情况:
1.子查询的结果是单行单列的:子查询可以作为条件,使用运算符做判断.
2.子查询的结果是多行单列的:子查询可以作为条件,使用运算符in来判断
3.子查询的结果是多行多列的:子查询可以作为一张虚拟表参与查询
1.事务的基本介绍
概念:如果一个包含多个步骤的业务操作,被事务管理那么这些操作要么同时成功要么同时失败
操作:
1. 开启事务: start transaction;
2. 回滚:rollback;
3. 提交:commit;
MySQL数据空中事务是自动提交的
事务提交的两种方式
手动提交:
Oracle 数据库默认是手动提交事务
需要先开启事务,在提交
自动提交
MySQL是自动提交
一条DML(增删改)语句会自动提交一次事务
修改事务的默认提交方式:
查看事务的默认提交方式:SELECT @@autocommit; -- 1 代表自动提交 0 代表手动提交
修改默认提交方式: set @@autocommit = 0;
2.事务的四大特征
a.原子性:是不可分割的最小操作单位,要么同时成功,要么同时失败
b.持久性:当事务提交或回滚后,数据库会持久化的保存数据
c.隔离性:多个事务之间,相互影响
d.一致性:事务操作前后,数据总量不变
3.事务的隔离级别(了解)
概念:多个事物之间隔离的,相互独立的.但是多个多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别可以解决这些问题
存在的问题:
a.脏读:一个书屋,读取到另一个书屋中没有提交的数据
b.不可重复读(虚读):在同一个事务中,两次读取到的数据不一样
c.幻读:一个事务操作(DML)数据表中所有记录,另一个数据添加了一条数据,则第一条事务查询不到自己的修改
隔离级别:
1.read uncommitted:读未提交
产生的问题:脏度.不可重复读.幻读
2.read committed:读已提交(Oracle)
产生的问题:不可重复读,幻读
3.repeatable read:可重复读(MySQL)
产生的问题:幻读
4.serializable:串行化
可以解决所有问题
注意:隔离级别从小到大安全性越来越高,效率越来越低
数据库查询隔离级别:
select @@tx_isolation;
数据库设置隔离级别:
set global transaction isolation level 级别字符串;
*DBA:数据库管理员
1.管理用户
a.添加用户
* 语法:CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';
b.删除用户
* 语法:DROP USER '用户名'@'主机名';
c.修改用户密码
UPDATE USER SET PASSWORD = PASSWORD('新密码') WHERE USER = '用户名';
UPDATE USER SET PASSWORD = PASSWORD('abc') WHERE USER = 'lisi';
SET PASSWORD FOR '用户名'@'主机名' = PASSWORD('新密码');
SET PASSWORD FOR 'root'@'localhost' = PASSWORD('123');
* mysql中忘记了root用户的密码?
1. cmd -- > net stop mysql 停止mysql服务
* 需要管理员运行该cmd
2. 使用无验证方式启动mysql服务: mysqld --skip-grant-tables
3. 打开新的cmd窗口,直接输入mysql命令,敲回车。就可以登录成功
4. use mysql;
5. update user set password = password('你的新密码') where user = 'root';
6. 关闭两个窗口
7. 打开任务管理器,手动结束mysqld.exe 的进程
8. 启动mysql服务
9. 使用新密码登录。
d.查询用户
1. 切换到mysql数据库
USE myql;
2. 查询user表
SELECT * FROM USER;
* 通配符: % 表示可以在任意主机使用用户登录数据库
2.授权管理
1. 查询权限:
查询权限
SHOW GRANTS FOR '用户名'@'主机名';
SHOW GRANTS FOR 'lisi'@'%';
2. 授予权限:
授予权限
grant 权限列表 on 数据库名.表名 to '用户名'@'主机名';
给张三用户授予所有权限,在任意数据库任意表上
GRANT ALL ON *.* TO 'zhangsan'@'localhost';
3. 撤销权限:
撤销权限:
revoke 权限列表 on 数据库名.表名 from '用户名'@'主机名';
REVOKE UPDATE ON db3.`account` FROM 'lisi'@'%';
1.概念:Java DataBase Connectivity Java数据库连接,Java语言操作数据库.作用:平复数据库数据的差异
2.本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口.各个数据库厂商去实现这套接口提供
数据库jar包,可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类
ps:驱动:不同程序之间相互的桥梁
3.快速入门:
步骤:
1. 导入驱动jar包
2. 注册驱动
3. 获取数据库连接对象 Connection
4. 定义sql
5. 获取执行sql语句的对象 Statement
6. 执行sql,接收返回结果
7. 处理结果
8. 释放资源
4.详解各个对象:
a.DeiverManger:驱动管理对象
*功能:注册驱动:告诉程序该使用哪一个数据库驱动jar
static void registerDriver(Driver driver) :注册与给定的驱动程序 DriverManager 。
写代码使用: Class.forName("com.mysql.jdbc.Driver");
通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块
注意:MySQL5之后的驱动jar包可以省略注册驱动的步骤
获取数据库连接:
* 方法:static Connection getConnection(String url, String user, String password)
* 参数:
* url:指定连接的路径
* 语法:jdbc:mysql://ip地址(域名):端口号/数据库名称
* 例子:jdbc:mysql://localhost:3306/db3
* 细节:如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称
* user:用户名
* password:密码
b.Connection:数据库连接对象
功能:
1. 获取执行sql 的对象
* Statement createStatement()
* PreparedStatement prepareStatement(String sql)
2. 管理事务:
* 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
* 提交事务:commit()
* 回滚事务:rollback()
c.Statement:执行SQL对象
1. 执行sql
1. boolean execute(String sql) :可以执行任意的sql 如果是true代表是查询语句,如果是false代表是增删改
2. int executeUpdate(String sql) :执行DML(insert、update、delete)语句、DDL(create,alter、drop)语句
* 返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功 返回值>0的则执行成功,反之,则失败。
3. ResultSet executeQuery(String sql) :执行DQL(select)语句
d.ResulteSet:结果集对象
* boolean next(): 游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回false,如果不是则返回true
* getXxx(参数):获取数据
* Xxx:代表数据类型 如: int getInt() , String getString()
* 参数:
1. int:代表列的编号,从1开始 如: getString(1)
2. String:代表列名称。 如: getDouble("balance")
* 注意:
* 使用步骤:
1. 游标向下移动一行
2. 判断是否有数据
3. 获取数据
//循环判断游标是否是最后一行末尾。
while(rs.next()){
//获取数据
int id = rs.getInt(1);
String name = rs.getString("name");
double balance = rs.getDouble(3);
System.out.println(id + "---" + name + "---" + balance);
}
e.PreparedStatement:执行SQL对象
SQL注入问题:因为在sql拼接,会将关键字拼接.
1. SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题
1. 输入用户随便,输入密码:a' or 'a' = 'a
2. sql:select * from user where username = 'fhdsjkf' and password = 'a' or 'a' = 'a'
2. 解决sql注入问题:使用PreparedStatement对象来解决
3. 预编译的SQL:参数使用?作为占位符
4. 步骤:
1. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar
2. 注册驱动
3. 获取数据库连接对象 Connection
4. 定义sql
* 注意:sql的参数使用?作为占位符。 如:select * from user where username = ? and password = ?;
5. 获取执行sql语句的对象 PreparedStatement Connection.prepareStatement(String sql)
6. 给?赋值:
* 方法: setXxx(参数1,参数2)
* 参数1:?的位置编号 从1 开始
* 参数2:?的值
7. 执行sql,接受返回结果,不需要传递sql语句
8. 处理结果
9. 释放资源
5. 注意:后期都会使用PreparedStatement来完成增删改查的所有操作
1. 可以防止SQL注入
2. 效率更高
目的:简化书写
分析:
1.注册抽动也抽取
2.抽取一个方法获取连接对象
*需求:不想传递参数(麻烦),还得保证工具类的通用性.
*解决方案:通过配置方案解决问题
jdbc.peoperties
url=
user=
password =
dirver =
3.抽取一个方法获取释放资源
public class JDBCUtils {
private static String url;
private static String username;
private static String password;
private static String driverClass;
//注册驱动
static {// 位置:类中方法外, 特点:只会执行一次, 随着字节码而加载
try {
//读取配置文件中的,用户名,密码,url...., 这里用Properties读取更方便,可以和io流结合!!!!load
Properties pro = new Properties();
//pro.load(new FileReader("day04/src/mysql.properties"));
// 不能直接读src下的配置文件, 因为将来给客户的字节码目录, 不是源码目录, 我们应该读字节码目录的配置文件,
// 这个配置文件放到src下,原因是, 他会帮我们拷贝一份到字节码目录下一份
// 怎么读字节码目录下的配置文件????? ----> 类加载器,因为他可以加载字节码目录下的所有东西!!!!!!!
ClassLoader classLoader = JDBCUtils.class.getClassLoader();
// 使用类加载器去加载配置文件
String path = classLoader.getResource("mysql.properties").getPath();
pro.load(new FileReader(path));
url = pro.getProperty("url");
username = pro.getProperty("username");
password = pro.getProperty("password");
driverClass = pro.getProperty("driverClass");
Class.forName(driverClass);
} catch (ClassNotFoundException e ) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//获取连接
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, username, password);
}
//释放资源
public static void close(Connection conn, Statement stmt, ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException s) {
s.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException s) {
s.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException s) {
s.printStackTrace();
}
}
}
public static void close(Connection connection, Statement statement) {
close(connection, statement, null);
}
}
1.概述:其实就是一个容器(集合),存放数据库连接的容器.
当系统初始化好后,容器被创建,容器会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,
用户访问完之后,会将对象归还给容器
2.好处:a.节约资源 b.用户访问高效.
3.实现:
1.标准接口:DataSource javax.sql包下的
方法: 获取连接:getConnextion()
归还连接:Connection.close().如果对象Connection是从连接池中实现的,那么调用Connection.close()方法,
则不会再关闭连接了,而是归还连接.
2.一般我们不去实现它,由数据库厂商来实现
1.C3P0:数据库连接池技术
2.Druid:数据库连接池实现技术,由阿里巴巴提供的
4.C3P0:数据库连接池技术
1.导入jar包 c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar ,
2.定义配置文件
*名称 c3p0.properties 或者 c3p0-config.xml
*路径:直接将文件放在src目录下即可
3.创建核心对象 数据库连接池对象 ComboPooledDataSource
4.获取连接:getConnection
5.Drvid:数据库连接池实现技术,由阿里巴巴提供
|
|