数据和信息

data数据:任何描述事物的文字或者符号都可以称为数据

数据需要保存,保存的介质有内存或者硬盘,内存中的数据是临时的,随着系统的关闭数据也会消失,硬盘中的数据是永久的,就算系统关闭数据依然保留

数据库

DataBase 称为数据库,简称DB,运行在操作系统上,按照一定的数据结构,保存数据的仓库,是一个电子化的文件柜,数据永久保存在硬盘上

数据库管理系统

DataBase Manager System 简称DBMS,通常所说的数据库 其实是指数据库管理系统,如MySQL,SQLServer,Oracle等

常见的数据库管理系统

关系型数据库

常用的关系型数据库有:MySQL,Oracle,SQLServer…

关系型数据库思主流的数据库类型 数据通过行row和列column形式(表格)保存

每行称为一条记录,每列称为一个字段,字段通常是Java中某个实体类的属性,通过这个类创建的对象就是一条记录

关系型数据库中数据表中间进行关联,能快速的查询想要的数据

  • 优点
  • 易于维护:数据都是以表的结构存储,格式一致
  • 使用方便,SQL语句通用,可用于不同的关系型数据库
  • 支持复杂查询:可以通过SQL语句在多个表之间查询出复杂数据
  • 缺点
  • 读写性能差,在处理海量数据时,频繁读写效率略低
  • 表结构不易改动,灵活性欠佳
  • 高并发读写时,硬盘I/O决定了读写速度

非关系型数据库

常用的非关系型数据库有:redis,mongoDB,Neo4j,HBASE

特点:

  • 保存数据的格式多样化
  • 对于海量数据的读写性能高
  • 不支持复杂查询

操作数据库

创建数据库

create database 数据库名;

切换数据库

use 数据库名

删除数据库

drop database 数据库名

操作数据表

创建数据表

create table 表名(
    字段名1 数据类型[字段特征],
    ...
    字段名n 数据类型[字段特征]
)

修改数据表

修改表时,要保证不影响现有数据

  • 对表重命名
alter table 旧表名 rename to 新表名;
  • 添加新字段
alter table 表名 add column 字段名1 数据类型[字段特征];
  • 修改字段
alter table 表名 change 旧字段名 新字段名 数据类型[字段特征];
  • 删除字段
alter table 表名 drop 字段名;

添加约束

  • 添加唯一约束
alter table 表名 add unique(字段名);
  • 添加主键约束
alter table 表名 add primary key (字段名);
  • 添加默认值约束
alter table 表名 alter 字段名 set default '默认值';
  • 添加外键约束
alter table 从表表名 add foreign key(从表外键字段) references 主表
表名(主表主键字段)

以上操作最好在建新表时就设置好约束

建表同时添加约束
-- 创建游戏数据库gamedb
create database gamedb;
-- 切换到游戏库
use gamedb;
-- 创建游戏任务表hero
create table hero(
    -- 编号id 主键 非空 自增
    id int not null primary key auto_increment comment '人物编号',
    -- 姓名唯一非空
    name varchar(20) unique not null,
-- 性别 默认值 男
    sex char(1) not null default '男',-- 默认值
-- 价钱 非空
    price int not null,
-- 创建时间 可以为空
    make_time date    
)
-- 在hero表中添加字段

alter table hero add column position varchar(20);


--创建战斗表 battle
create table battle(
    -- id 主键字段 非空 自增
    id int not null primary key auto_increment,
-- 出战人物编号 来自于hero表中的id字段,非空
    hero_id int not null,
-- 昵称 可以为空
    nick_name varchar(20),
-- 分路 不能为空
    way varchar(10) not null,
-- 设置外键
    foreign key(hero_id) references hero(id)
)

删除数据表

drop table 表名
-- 如果要删除有外键关联的表 要先删除从表 在删除主表

MySQL中常见的数据类型

整型

tinyint

对应Java中的short

短整型

int

对应Java中的int

整型

bigint

对应Java中的long

长整型

浮点型

float

对应Java中float

单精度浮点型

double

对应Java中的double

双精度浮点型

decimal(宽度,精度)

指定保留的小数位数和整体宽度

如decimal(4,2)如3.1415926----> 3.14

字符串

char(大小)

定长字符串

对应Java中的string,char(10)表示就算实际保存3个字符,也占10个字符

varchar(大小)

可变字符串

对应Java中string,varchar(10)表示实际保持3个字符,占3个字符

text

文本

日期

date

日期

yyyy-MM-dd

time

时间

HH:mm:ss

datetime

日期时间

yyyy-MM-dd HH:mm:ss

timestamp

毫秒

保存日期的毫秒数

数据操作CURD

C:增加create、U:修改update、R:查询read、D:删除delete

数据添加insert

数据添加都是整行添加 不能只给一个字段添加数据,如果给某个字段添加数据实际是修改

给所有字段赋值

insert into 表名 values('值1','值2',....);

给指定字段赋值

insert into 表名(字段1,字段2...) values('值1','值2',...)

批量添加

insert into 表名[(字段1,字段2...)] values
    ('值1','值2',...),
    ('值1','值2',...),
        ...
    ('值1','值2',...)

数据修改update

修改单个字段的所有制

update 表名 set 字段='值';

修改多个字段的所有值

update 表名 set 字段1='值',字段2='值',...;

根据条件修改(where子句)

update 表名 set 字段='值',字段='值'...where 条件;

指定值

update 表名 set 字段='值',字段='值'...where 字段='值';

指定范围

  • 使用>,<,>=,<=表示范围,使用and,&&,or,||将多个条件关联
  • 使用“字段 between A and B”表示字段在[A,B]范围内
  • 使用!=或者<>表示不等于

指定集合

  • 某个字段的值在某个集合中时:字段in(‘值1’,‘值2’…)
  • 某个字段的值不在某个集合中时:字段not in(‘值1’,‘值2’,…)

空间匹配

  • 某个字段为空:字段is null
  • 某个字段不为空:字段 is not null

模糊查询

  • %表示未知长度字符串
  • __表示一个字符
-- 字段 like '%琳%'   --表示带有琳字的

-- 字段 Like ’张%‘   --表示有姓张的

-- 字段 like '%儿' --以儿结尾

-- 字段 like '__'  --    表示两个字的


-- 字段 like '%的_'   --表示倒数第二个字为的

数据删除delete

删除数据是删除一条或者多条记录

删除所有

delete from 表名;
-- 或者
truncate table 表名;
  • delete会保留自增列删除前的值,删除后再添加时自动从删除前的值开始自增
  • truncate会重置自增列的值,删除所有数据时效率更高
  • 如果要删除主从关系并且设置了外键中的表中的数据,从表中如果有数据,不能直接删除主表中相关关键的数据,要先删除从表数据,在删除主表数据

条件删除

delete from 表名 where 条件;

数据查询select

查询所有字段

select *from 表名;

查询指定字段

select 字段名1,字段名2.....from 表名; --在实际开发中,很少使用*查询,因为*查询的效率
远低指定字段查询于

字段重命名

select 字段1 as '自定义名称',字段2 as’自定义名称‘...from 表名;

查询指定条数

-- 查询前n条记录
select *from 表名 limit N;
-- 查询从索引n开始的m条记录
select * from 表名 limit n,m;
-- 每页显示size条记录 第page页
select *from 表名 limit (page-1)*size,size

条件查询

select *from 表名 where 条件

排序

select *from 表名 where 条件 order by 排序字段,排序规则....
  • 排序默认是升序
  • 排序规则不写或写asc表示升序
  • 排序规则写desc表示降序
  • 排序时如果有条件,排序写在条件语句之后
  • 多字段排序时,在order by 之后写多个字段及排序规则,用逗号隔开

统计函数(聚合函数)

select 统计函数(字段) from 表名;

函数名

作用

sum(字段)

求和

avg(字段)

平均值

count(字段)

计数

max(字段)

最大值

min(字段)

最小值

数学相关函数

函数名

作用

abs(值或字段)

绝对值

pow(值或字段)

次幂

sqrt(值或字段)

开平方

round(值或字段)

四舍五入取整

ceil(值或字段)

向上取整

floor(值或字段)

向下取整

字符串相关函数

函数名

作用

length(字符串或者字段)

得到字符串长度

substr(字符串或字段,start)

从start开始截取字符串到末尾

substr(字符串或字段,start,len)

从start开始截取len个字符串

left(字符串或者字段,len)/right(字符串或字段,len)

从首/尾开始截取len个字符

reverse(字符串或字段)

反转字符串

concat(字符串1,字符串2…)

将所有字符串拼接

replace(字符串或字段,旧字符串,新字符串)

将字符串中的旧字符串替换为新字符串

时间相关函数

函数名

作用

now()

得到当前的日期时间

current_date()/curdate()

得到当前日期

current_time()/curtime()

得到当前时间

year(日期)/month(日期)/day(日期)

得到年/月/日部分

datediff(时间1,时间2)

得到时间1与时间2相隔的天数

timediff(时间1,时间2)

得到时间1与时间2相隔的时分秒

timestampdiff(时间单位,时间1,时间2)

分组

select 分组字段,统计函数 from 表名 group by 分组字段 having 统计函数条件;

按指定的字段进行分组,会将该字段值相同的记录归纳到同一组中没分组通常配合统计函数使用,如果统计函数作为条件,不能使用where,而是使用having子句,将整个having子句放在分组之后

group_concat()函数

将分组后的数据拼接成字符串

group_concat(字段或者字符串,字段或者字符串,....)

--根据图书类型分组,查看每组下的图书名和作者
select group_concat(book_name,'--',book_author) from book_into group by type_id

连接查询

交叉查询(笛卡尔积)

将两张表中的数据两两组合,得到的结果就是交叉连接的结果,也成为笛卡尔积

select *from 表1,表2;
select*from 表1 cross join 表2;
select *from 表1 inner join 表2;

以上三种方式都能将两张表的数据互相组合,其中有很多无效数据

内连接

在交叉连接的基础上,赛选出关联的数据

select *from 表1,表2 where 表1.字段=表2.字段;
select*from 表1 inner join 表2 on 表1.字段=表2.字段;
-- 比如查询所有图书详情和类型名
select*from 图书详情表 t1,图书类型表 t2 where t1.类型编号=t2.类型编号;
select*from 图书详情表 t1 inner join 图书类型表 t2 on t1.类型编号=t2.类型编号
  • 通常是通过主表的主键字段关联从表的外键字段,如果两张表中关联的字段名一致,一定要通过表名.字段名来进行区分来,通常还会给表重命名
  • 如果使用inner join 带条件时,需要加入where子句,如果使用,隔开了多个表,带条件时需要使用and拼接条件
  • 内连接只会显示两张表中有关联的数据

左连接

-- 保证坐标数据显示完整的情况下,9关联右表的数据,没有关联的用null表示
select *from 表1 left join 表2 on 表1.字段=表2.字段
最终显示表1 中的所有数据,关键表2的数据,

右连接

-- 保证右表数据显示完整的情况下,关联左表中的数据,没有关联的用null表示
select * from 表1 right join 表2 on 表1.字段 = 表2.字段
最终显示表2中的所有数据,关键表1的数据,

嵌套查询

将查询出的结果继续使用在另一个查询语句中

-- 查询价格最低的图书信息
select * from book_info where book_price = (select min(book_price) 
from book_info)
-- 按类型分组,查询每组中图书价格大于平均价格的图书
select * from book_info bi inner join 
(select type_id,avg(book_price) as avg from book_info group by 
type_id)temp on bi.type_id = temp.type_id  where book_price > avg

JDBC

Java database connectivity :Java数据库连接,用于Java程序中连接不同的数据库

核心接口

  • Connection:用于设置连接的数据库的地址,账号,密码
  • PreparedStatement:用于预处理、执行SQL语句
  • ResultSet:用于保存查询后的数据

单表查询

import java.sql.*;

   public class Main {
     public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //连接mysql数据库实现单表查询
        //1.加载连接MySQL的驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
        //2.连接数据库,提供要连接的数据库的URL、用户名、密码
        String url = "jdbc:mysql://localhost:3306/gamedb?serverTimezone=Asia/Shanghai";
        Connection conn = DriverManager.getConnection(url, "root", "root");
        //3.构造查询的sql语句
        String sql = "select * from hero";
        //4.处理sql语句
        PreparedStatement pst = conn.prepareStatement(sql);
        //5.处理执行sql语句后的结果
        ResultSet rs = pst.executeQuery();
        //6.循环遍历读取查询后的数据
        while (rs.next()) {
            //根据字段名获取
            int id = rs.getInt("id");
            //根据字段顺序获取
            String name = rs.getString(2);
            String sex = rs.getString(3);
            int price = rs.getInt(4);
            String makeTime = rs.getString(5);
            String position = rs.getString(6);
            System.out.println(id+"\t"+name+"\t"+sex+"\t"+price+"\t"+makeTime+"\t"+position);
        }
        //7.关闭连接
        rs.close();
        pst.close();
        conn.close();
    }
}

简化JDBC

import java.sql.*;

/*
 * 定义数据库工具类,简化JDBC操作
 * 可以简化的操作
 * 1.加载驱动   √
 * 2.连接数据库 √
 * 6.关闭   √
 * */
public class DBUtil {
    /*
     * 定义静态代码块用于加载驱动
     * */
    static {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            System.out.println("驱动不存在" + e);
        }
    }

    //定义静态常量保存连接数据库的字符串
    private final static String URL = "jdbc:mysql://localhost:3306/gamedb?serverTimezone=Asia/Shanghai";
    private final static String USERNAME = "root";
    private final static String PASSWORD = "root";

    /*
     * 定义静态方法获取连接对象
     * */
    public static Connection getConn() {
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
        } catch (SQLException e) {
            System.out.println("连接数据库信息异常" + e);
        }
        return connection;
    }

    /*
     * 定义静态方法释放资源
     * */
    public static void release(Connection conn, PreparedStatement pst, ResultSet rs) {
        //使用了哪个接口就关闭那个接口
        try {
            if (rs != null) {
                rs.close();
            }
            if (pst != null) {
                pst.close();
            }
            if (conn != null) {
                conn.close();
            }
        } catch (SQLException e) {
            System.out.println("关闭异常" + e);
        }
    }
}

实体关系模型

实体:entity,关系:relationship,实体与实体之间的关系

实体关系模型也成为ER模型,ER图

矩形表示实体,椭圆表示实体的属性,菱形表示实体之间的关系,用直线连接

ER图例子

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a3bhUzD3-1680569599474)(C:\Users\asus\AppData\Roaming\marktext\images\2023-04-01-19-58-26-image.png)]

当有两个实体时,需要我们判断这两个实体之间是什么关系,是一对一、一对多/多对一,还是多对多关系

步骤:

  • 首先创建两个实体的属性表
  • 再判断两个实体表的关系,关系判定后,将关系表展示出来,有两种方式:
  • 方式一:将两个表中有关联的比如编号字段,将其设置为唯一,如果没有编号就在表中添加编号,将其设置为唯一
-- 这里在领导人表中添加国家编号字段为例
create table leader(
leader_id int not null primary key auto_increment,
leader_name varchar(20) not null,
leader_sex varchar(2) not null,
leader_birthday date,
country_id int not null unique,
foreign key (country_id) references country(country_id)
)
  • 方式二:创建第三张表,关系表,将各自的id编号设置为外键约束
create table relation(
relation_no int not null primary key auto_increment,
country_id int not null unique,
leader_id int not null unique,
foreign key (country_id) references country(country_id),
foreign key (leader_id) references leader(leader_id)
)

总结

  • 一对一:创建各自的实体表,在任意一张表中添加另一张表的主键字段,将其设置为唯一
  • 一对多/多对一:先创建主表(一),在创建从表(多),在从表中添加主表的主键字段,外键可选
  • 多对多:创建各自的实体表,在创建第三张表“关系表”,在关系表中添加两个实体表中的主键字段,外键可选

练习1

医院信息管理系统:

医生模块:医生表

病人模块:病人表

诊断模块:记录哪个医生在什么时间诊断了哪个病人,记录信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5KpASwSR-1680569599480)(C:\Users\asus\AppData\Roaming\marktext\images\2023-04-01-20-12-49-image.png)]

-- 医生表
create table doctor(
id int not null primary key auto_increment,
section varchar(20) not null,
name varchar(20) not null,
phone varchar(20) not null
)
-- 病人表
create table patient(
id int not null primary key auto_increment,
name varchar(20) not null,
age int not null,
address varchar(20) not null
)
--诊断表
create table diagnosis(
id int null primary key auto_increment,
doctor_id int not null,
patient_id int not null,
diagnosis_time datetime not null
)

Java部分

// 医生实体部分
public class Doctor{
private int id;
private String name;
private String section;
private String phone;
//省略get/set/构造方法/toString()
}
// 病人实体部分
public class Patient{
private int id;
private String name;
private int age;
private String address;
//省略get/set/构造方法/toString()
}
// 诊断实体部分
section varchar(20) not null,
 name varchar(20) not null,
 phone varchar(20) not null
 )
 – 病人表
 create table patient(
 id int not null primary key auto_increment,
 name varchar(20) not null,
 age int not null,
 address varchar(20) not null
 )
 –诊断表
 create table diagnosis(
 id int null primary key auto_increment,
 doctor_id int not null,
 patient_id int not null,
 diagnosis_time datetime not null
 )
Java部分

```java
// 医生实体部分
public class Doctor{
private int id;
private String name;
private String section;
private String phone;
//省略get/set/构造方法/toString()
}
// 病人实体部分
public class Patient{
private int id;
private String name;
private int age;
private String address;
//省略get/set/构造方法/toString()
}
// 诊断实体部分