MySQL关系型数据库 , 保存的就是实体之间的关系
ER模型图: E :Entity R :Relational
关系型数据都有 [ MySQL , Oracle , SQLServer , DB2 , SyBase ]
服务器就是 硬件 和 软件 两个方面 [ 安装了MySQL , 这台电脑就是MySQL数据库服务器了 ]
硬件 : 指的就是一台计算机 [ 配置很高的计算机 ]
软件 : 需要在这台电脑上安装数据库服务器
如何存储数据mysql -u root -p
默认链接本地服务器:省略了两个参数:
-h : hostname
-p : port
在数据库服务器的内部,通过数据库储存数据,通常情况下一个应用创建一个数据库
在数据库中,一般用表储存数据,在一个系统中,通常为每个实体创建一个表
流程 : 数据库 --> 数据库表 ---> 表中插入多条数据
crud : 增 , 删 , 改 , 查
SQL的分类结构化查询语言 [ ]
DDL:数据定义语言Create , Drop , Alter
DCL:数据控制语言Grant [ 授予权限 ] , if
DML:数据操纵语言insert , update , delete
DOL:数据查询语言select
创建数据库create database 数据库名称 ;
指定字符集 和 校对规则 :
create database 数据库名称 [ character set 字符集 collate 字符集校对规则 ]
查看数据库查看所有的数据库 show database ;
查看某个 [ 字符集,校对规则 ] 数据库的定义信息 :
show create database 数据库名称 ;
修改数据库修改字符集 [ utf8... ] 和校对规则
alter database 数据库名称 character set 字符集 collate 校对规则
删除数据库drop database 数据库名称 ;
切换数据库use 数据库名称 ;
查看当前正在使用的数据库select database ( ) ;
创建表创建一个c表
create table 表名称 (
字段名称 字段类型 ( 长度 ) 约束
) ;
创建多个表
create table 表名称 (
字段名称 字段类型 ( 长度 ) 约束 ,
字段名称 字段类型 ( 长度 ) 约束 ,
.....等等
) ;
约束作用 : 保证数据的完整性
单表约束分类 :
主键约束 : primary key 主键约束默认就是唯一 非空的
唯一约束 : unique [ 唯一的,不能有重复 ]
非空约束 : not null [ 不能为空 ]
自动增长 : auto_increment [ 1,2,3,4,5....等等 ]
创建数据库,表创建数据库
create database web_test1;
use web_test1;
创建表
create table user (
id int primary key auto_increment,
username varchar(20) unique,
password varchar(20) not null,
age int,
birthday date
)查看表查看某个数据库下的所有的表
show tables ;
查看某个表的结构信息
desc 表名称 ;
跳转到表use 表名称 : 切换到表
删除表drop table 表名称 ;
修改表Update
添加列 alter table 表名称 add 列名称 类型 ( 长度 ) 约束 ;
修改列类型 , 长度 , 约束 alter table 表名称 modify 列名称 类型 ( 长度 ) 约束;
删除列 Alter table 表名称 drop 列名称
修改列名称 alter table 表名称 change 旧列名称 新列名称 类型 ( 长度 ) 约束 ;
修改表名称 rename table 表名称 to 新表名称 ;
修改表的字符集 alter table 表名称 character set 字符集 ;
常用的列也叫字段
添加列 , 修改列类型和长度 ,
重点!!!!!!添加表中记录 向表中插入某些列:
insert into 表名称 ( 列明1 , 列明2 .... ) values ( 值1 , 值2 ....);
insert into user ( id, username,password ) values ( null,'aaa','123' ) ;
向表中插入所有列
insert into 表名称 values ( 值1 , 值2 ,....) ;
insert into user values ( null ,'bbb','123',23,'1996-1-1' ) ;
注意 :
值的类型需要与列的类型一致
值的顺序需要与列的顺序一致
值的最大长度不能超过列设置的最大长度
值的类型是字符串或者日期类型,就要使用单引号引起来
select * from 表名称 ;
中文乱码问题查看数据库与字符集相关参数
show variables like ' character% ' ;
file://C:\Users\ADMINI~1\AppData\Local\Temp\1525487887092.png?lastModify=1525851464
需要将数据类客户端字符集改成gbk [ my.ini的文件里面[ client ] ]
然后重启MySQL
修改表中记录 update 表名称 set 列名称=值 , 列名称=值 [ where 条件 ] ;
注意: 值的类型与列的类型一致
值的最大长度不能超过列设置的最大长度
字符串类型和日期类型单引号引起来
修改某一列所有值
update user set password = 'abc' ;
把用户名为username的用户密码改为 abc
update user set password ='abc' where username = ' bbb ' ;
把用户名为username的用户密码改为 abc,年龄改为24
update user set password ='abc' , age =24 where username = 'bbb' ;
where条件,把谁里面的什么东西改成什么,比如[ id=1 里面的username的值改成别的 ]
删除表中记录删除的时候,要带条件删除,要不然就把整个表中全部的数据删除了
delete from 表名称 [ where 条件 ] ;
删除某一条记录
delete from user where id = 2 ;
删除表中所有记录
delete from 表名称 ;
[ 属于DML语句,一条记录一条记录删除,事务可以作用在DML语句上的 ]
truncate table 表名称 ;
[ 属于DDL语句,将表删除,然后创建一个结构一样的,事务不能控制DDL的 ]
start transaction ; 开启事务
rollback ; 恢复
注意 :
删除的是记录,一行记录
删除如果没有条件,默认删除表中全部记录
重点!!!!!!查看表中记录 查询表中所有记录
select * from 表名称 ;
基本查询 select [ distinct ] *| 列名称 from 表名称 [ 条件 ] ;
查询某些列的值
select 列名称,列名称...等等 from 表名称 ;
去掉重复值的查询
select distinct 列名称 from 表名称 ;
查询多列的总和
select 列名称+列名称 +列名称..等等 from 表名称 ;
别名查询
select 列名称+列名称 +列名称..等等 as 别名 from 表名称 ;
条件查询 使用where子句
条件 : > , < , >= , <= , <> , =
like:范围查询
下划线只能代替一个字符,而%可以标识任意个字符
like '李_' :名字中必须是两个自字,并且是姓李
like '李%' :名字中姓李,后面可以是一个或者多个
like '%李' :已李结尾的
like '%李%' :任意位置是李的
in :范围查询
条件关联 : and , or , not
排序查询 使用order by
查询姓李学生,英语成绩降序排序
select * from 表名 where 列名 like '李%' order by 列名;
分组统计查询 select * from 表名称 order by 列名;
聚合函数查询 sum ( ) 获取总和
select sum ( 列名 ) from 表名 ;
英语和数学的总和
ifnull (English,0 )
count ( ) 获取个数
select count ( * ) from 表名 ;
max ( ) 获取最高分
select max ( 列名 ) from 表名 ;
min ( ) 获取最小值
select min ( 列名 ) from 表名 ;
avg ( ) 获取平均值
select avg ( 列名 ) from 表名 ;
分组查询 group by 字段名称 ;
按照列 查询个数 select 列名 , count (*) from 表名 group by 列名 ;
按照记录名称统计个数, 每类记录金额总金额在 5000元以上的商品
select 列名 ,sum (列名) from 表名 group by 列名 having sum( 列名) > 5000;
上面的语句,改成了升序
select 列名 ,sun (列名 ) from 表名 group by 列名 having sum( 列名) > 5000 order by sum (列名) asc;
总结 :顺序 :
S(select)...F(from)...W(where)...G(group by)...H(having)...O(order by);
数据库备份 1 ,打开cmd的命令行窗口
mysqldump -u root -p 数据库名称 >路径file://C:\Users\ADMINI~1\AppData\Local\Temp\1525511157747.png?lastModify=1525851464
数据库还原 1 ,进入数据库
2 ,创建一个数据库
3 ,mysql -u root -p 数据库名称 <路径
第二种:
1 ,进入数据库
2 ,创建一个数据库
3,在命令行打 source 路径,
多表约束 外键约束,用来保证数据完整性 ( 多表之间 ) [ 表与表之间的连系 ]
foreign key ()
alter table 表名称 add foreigh key (列名称) references did () ;
设置外键[一个表指向另一个表]alter bable 表名 add foreigh key (列名) references key dept(列名);
表与表之间的关系一对多的关系 例如 : 一个部门下可以有多个员工,一个员工只能属于某一个部门
建表原则 : 在多的一方创建外键指向一的一方的主键 [ 多的外键指向一的主键 ]
多对多的关系 例如 : 一个学生可以选择多门课程,一门课程可以被多个学生选择
建表原则 : 需要创建第三种表 ( 中间表 ) , 在中间表中至少两个字段分别作为作为外键 , 指向多对多双发的主键
一对一的关系 例如 : 一个公司可以有一个注册地址,一个注册地址只能对应一个公司
建表原则 :
假设一对一是一个一对多的关系,需要在多的一方创建外键指向一的一方的主键,将外键设置为唯一 ( unique )
班级,学生,课程
多表查询的分类连接查询交叉连接[cross join]查询到的是连哥哥表的笛卡尔积
select * from 表1 cross join 表2;
select * from 表1,表2;
内连接[inner join]inner 是可以省略的
显示内连接 在SQL中显示的调用 inner join 关键字
select * from 表1 别名 inner join 表2 别名 on 关联条件;
隐式内连接 在SQL中没有调用 inner join 关键字
外连接[outer join]outer 可以省略
左外连接 以左表为基准,根据关联条件去右表查询,如果匹配上了则返回匹配上的数据,如果匹配不是则返回null
右外连接子查询 一个查询语句条件需要依赖另一个查询结果
带in的子查询 意思 : 范围
例如查询学生生日在91年之后的班级信息
select * from classes where cid in ( 把下面的语句放进来 ) ;
select * from student where birthday > '1991-01-01' ;
带exists的子查询 意思 : 存在 [ 相当于 if ]
例如查询学生生日大于91年,如果记录存在,前面的SQL语句就会执行
select * from classes where exists ( 把下面的语句放进来 ) ;
select * from student where birthday > '1991-01-01' ;
带any的组查询 意思 : 任意一个
例如
select * from classes where cid > any ( select cno from student ) ;
带all的子查询 意思 : 所有
例如
select * from classes where cid > all ( select cno from student ) ;
事务[ 在财务上 , 比如支付宝转账 , A转账给B , B接收到才算成功 , 要不然就没有转过去 ]
指的是逻辑上的一组操作,组成这组操作的各个逻辑单元,要么全成功,要么全失败
开启事务 start transaction ;
提交事务 commit ;
回滚事务 rollback ;
事务的特性原子性 事务的不可分割 , 组成事务的各个逻辑单元不可分割 [ 每一个步骤都不可分割 ]
一致性 事务执行的前后 , 数据完整性保持一致
隔离性 必须要做的 , 控制并发
事务执行不应该受到数据库中其他事务的干扰
持久性 事务一旦提交 ( 结束或者回滚) , 数据就持久化到数据库中 [ 硬盘中 ]
ACID [原子性 ,一致性 ,隔离性 ,持久性 ]
隔离级别出现的安全问题 脏读 : 一个事务读到了另一个事务未提交的数据 , 导致查询结果不一致
不可重复读:一个事务读到了另一个事务已经提交到update的数据 , 导致多次查询结果不一致
虚度/幻读 : 一个事务读到了另一个事务已经提交到insert的数据 , 导致多次查询结果不一致
解决这些安全性问题 read uncommitted : 脏读 , 不可重复读 ,虚度都有可能发生 [ 读到未提交的]
read committed : 避免脏读 , 但是不可重复读和虚读是有可能发生 [ 读到提交的]
repeatable read : 避免脏读和不可重复读 ,但是虚读有可能发生 [ 读到了insert的]
serializable : 避免脏读,不可重复读 ,虚读 [ 排队来]
一般采取中间两个级别 , 两端太极端 ,
file://C:\Users\ADMINI~1\AppData\Local\Temp\1525684555196.png?lastModify=1525851475
设置事务的隔离级别
set session transaction isolation level 隔离级别 ;
查看当前的隔离级别
select @@tx_isolation ;
JDBC Java Data Base Connectivity ( Java数据库连接 )
数据库驱动 连各个设备 ( 应用 ) 之间通信的桥梁
JDBC的开发步骤第一步 : 加载驱动第二步 : 获得连接第三步 : 基本操作第四步 : 释放资源工具类package JDBCUtils;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class JDBCUtils {
private static final String driverClassName;
private static final String url;
private static final String username;
private static final String password;
static{
Properties properties= new Properties();
try {
properties.load(new FileInputStream("src/db.properties"));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
driverClassName=properties.getProperty("driverClassName");
url=properties.getProperty("url");
username=properties.getProperty("username");
password=properties.getProperty("password");
}
/**
* 注册驱动的方法
*/
public static void loadDriver(){
try {
Class.forName(driverClassName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获得连接的方法
*/
public static Connection getConnection(){
Connection conn = null;
try{
// 将驱动一并注册:
loadDriver();
// 获得连接
conn = DriverManager.getConnection(url,username, password);
}catch(Exception e){
e.printStackTrace();
}
return conn;
}
/**
* 释放资源的方法
*/
public static void release(Statement stmt,Connection conn){
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
public static void release(ResultSet rs,Statement stmt,Connection conn){
// 资源释放:
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}配置文件dcName=com.mysql.jdbc.Driver
url=jdbc:mysql:///web_test3
username=root
password=123查询多条数据@Test
/**
* 查询操作
*/
public void demo4(){
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try{
// 获得连接:
conn = JDBCUtils.getConnection();
// 编写SQL:
String sql = "select * from user";
// 预编译SQL:
pstmt = conn.prepareStatement(sql);
// 设置参数:
// 执行SQL:
rs = pstmt.executeQuery();
// 遍历结果集:
while(rs.next()){
System.out.println(rs.getInt("id")+" "+rs.getString("username")+" "+rs.getString("password")+" "+rs.getString("nickname"));
}
}catch(Exception e){
e.printStackTrace();
}finally{
JDBCUtils.release(rs, pstmt, conn);
}
}查询一条记录在like模糊查询后面直接写 ? ,如何在设置参数哪里在写 % 或者 _
@Test
public void demo4(){
Connection conn = null;
statement stmt = null;
ResultSet rs = null;
try{
注册驱动:
Class.forName("com.mysql.jdbc.Driver");
获得连接:
conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/web_test3","root","123");
执行操作:
创建执行SQL语句对象
stmt = conn.preparedStatement ();
编写SQL语句:
String sql = "select * from user where id=4"; [如果能确定查出一条记录,可以不用while循环,如果不确定用while循环也可以]
执行SQL语句:
rs = stmt.executeUpdate (sql);
//[可以在这里写循环]
if(num > 0){
syso(rs.getInt("id")+" ");
syso(rs.getString("username")+" ");
syso(rs.getString("password")+" ");
syso(rs.getString("nickame")+" ");
syso(rs.getString("age")+" ");
}
}catch(Execption e){
e.prinStackTrace()
} }finally{
标准资源释放代码;
if(stmt != null){
try{
stmt.close();
}catch(SQLException e){
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try{
conn.close();
}catch(SQLException e){
e.printStackTrace();
}
conn = null;
}
if(rs != null){
try{
rs.close();
}catch(SQLException e){
e.printStackTrace();
}
rs = null;
}
}添加操作@Test
/**
* 保存操作
*/
public void demo1(){
Connection conn = null;
PreparedStatement pstmt = null;
try{
// 获得连接:
conn = JDBCUtils.getConnection();
// 编写SQL语句:
String sql = "insert into user values (null,?,?,?,?)";
// 预编译SQL:
pstmt = conn.prepareStatement(sql);
// 设置参数:
pstmt.setString(1, "eee");
pstmt.setString(2, "abc");
pstmt.setString(3, "旺财");
pstmt.setInt(4, 32);
// 执行SQL
int num = pstmt.executeUpdate();
if(num > 0){
System.out.println("保存成功!");
}
}catch(Exception e){
e.printStackTrace();
}finally{
JDBCUtils.release(pstmt, conn);
}
}修改操作@Test
/**
* 修改操作
*/
public void demo2(){
Connection conn = null;
PreparedStatement pstmt = null;
try{
// 获得连接:
conn = JDBCUtils.getConnection();
// 编写SQL语句:
String sql = "update user set username = ?,password =?,nickname=?,age = ? where id = ?";
// 预编译SQL:
pstmt = conn.prepareStatement(sql);
// 设置参数:
pstmt.setString(1, "abc");
pstmt.setString(2, "1234");
pstmt.setString(3, "旺旺");
pstmt.setInt(4, 23);
pstmt.setInt(5, 6);
// 执行SQL:
int num = pstmt.executeUpdate();
if(num > 0){
System.out.println("修改成功!");
}
}catch(Exception e){
e.printStackTrace();
}finally{
JDBCUtils.release(pstmt, conn);
}
}删除操作@Test
/**
* 删除操作
*/
public void demo3(){
Connection conn = null;
PreparedStatement pstmt = null;
try{
// 获得连接:
conn = JDBCUtils.getConnection();
// 编写SQL语句:
String sql = "delete from user where id = ?";
// 预编译SQL
pstmt = conn.prepareStatement(sql);
// 设置参数:
pstmt.setInt(1, 4);
// 执行SQL:
int num = pstmt.executeUpdate();
if(num > 0){
System.out.println("删除成功!");
}
}catch(Exception e){
e.printStackTrace();
}finally{
JDBCUtils.release(pstmt, conn);
}
}工具类测试public void JDBCDemo3{
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try{
获得连接
conn = JDBCUtils.getConntion();
创建执行SQL语句对象
stmt = conn.preparedStatement ();
编写SQL
String sql = "select * from user";
执行查询
re.stmt.executeQuery(sql);
遍历结果集
while(rs.next()){
syso(rs.getInt("id")+" ");
syso(rs.getString("username")+" ");
syso(rs.getString("password")+" ");
syso(rs.getString("nickame")+" ");
syso(rs.getString("age")+" ");
}
}catch(Exception e){
e.printStackTrace();
}finally{
释放资源
JDBCUtils.release(rs,stmt,conn);
}
}批量处理API介绍DriverManager 驱动管理类
作用一注册驱动 Class.forName("com.mysql.jdbc.Driver"); [ 固定写法 ]
作用二获得连接 getConnection (url , user , password ) ;
url : 与数据库连接的路径
user :与数据库连接的用户名
password:与数据库连接的密码
url 的写法
jdbc:mysql://localhost:3306/web_test3
jdbc :连接数据库的协议
mysql :是jdbc的子协议
localhost :连接的MySQL数据库服务器的主机地址 ( 连接是本机就可以写成localhost ) 如果连接不是本机的,就需要写上连接主机的IP地址
3306 :MySQL数据库服务器的端口号
web_test3 :
Connection 数据库连接对象
作用一创建执行SQL语句的对象 名字 . preparedStatement ( "这里写SQL语句" ) ; [ 有返回值,用sql的那个接收,起个变量名字 ]
执行SQL语句对象 statement :执行SQL
CallableStatement :执行数据库中存储过程
PreparedStatement :执行SQL对SQL进行预处理 , 解决SQL注入漏洞 [常用的]
作用二管理事务 setAutoCommit :指定事务管理
commit ( ) :提交
rollback ( ) :回滚
Statement 执行SQL语句
作用一执行SQL语句 boolean execute ( sql语句 )
执行查询 , 修改 , 添加 , 删除的SQL语句 [ 返回true ]
ResultSet executeQuery ( sql语句 )
执行查询 ( 执行select语句 )
int executeUpdate ( sql语句 )
执行修改 , 添加 , 删除的SQL语句
作用二执行批处理 addBatch :添加批处理
clearBatch :清除批处理
executeBatch :执行批处理
在的代码里实际用的Statement 是 PreparedStatement 的父接口
PreparedStatement : ps
执行查询:
ResultSet rs = ps . executeQuery ( ) ;
执行增 , 删, 改
int row = ps . executeUpdate ( ) ;
ResultSet 结果集 通过 select 语句的查询结果
结果集遍历 next ( ) :将光标移到下一行
while(rs.next()){
syso(rs.getInt("id")+" ");
syso(rs.getString("username")+" ");
syso(rs.getString("password")+" ");
syso(rs.getString("nickame")+" ");
syso(rs.getString("age")+" ");
}结果集获取 getXXX ( ) :方法通常都会有一个重载的方法
getXXX ( int columnlndex列号 ) :传入列号
getXXX ( String columnName列名 ) :传入列名
getObject ( String columnName ) :通用
while (rs.next){
rs.getXXX (String columnName列名) ;
XXX 是 int string 等等;
columnName默认使用列名,如果起了别名,就用别名
}JDBC资源释放 JDBC城西执行完之后,要释放资源,通常是 ResultSet , Statement , Connection
Connection对象是非常稀有的. 这个对象一定要做到尽量晚创建,今早释放掉
将资源释放的代码写到 finally
finally{
标准资源释放代码;
if( rs != null ){
try{
rs.close();
}catch( SQLException e ){
e.printStackTrace();
}
rs = null;
}
}