概述
数据库(DB,DataBase)
分类
关系型数据库
- MySQL、Oracle、Sql Server、SQLite
- 表和表、行和列之间有关系
非关系型数据库
- Redis、MongoDB
- 对象存储、通过对象的属性决定
DBMS 数据库管理系统,即数据库管理软件
安装
- 下载zip文件
- 解压到D:Environment下
- 配置环境变量,在path中加入D:Environmentmysql-5.7.31in
- 压缩包默认没有配置文件,在安装目录下 创建 my.ini 文件,并且添加如下内容
[mysqld]
basedir=D:Environmentmysql-5.7.31
datadir=D:Environmentmysql-5.7.31data
port=3306
skip-grant-tables
- 启动管理员模式cmd,进入bin目录下
mysqld -install
- 再输入
mysqld --initialize-insecure --user=mysql
初始化数据文件 - 启动
net start mysql
- 进入数据库
mysql -uroot -p
,无需密码enter进入 - 修改密码
update mysql.user set authentication_string=password('123456') where user='root' and Host ='localhost';
- 刷新权限
flush privileges;
- 修改my.ini文件,注释 skip-grant-tables
- 重启mysql
SQLyog 注册
版本 12.0.8
注册名:kuangshen
注册码:8d8120df-a5c3-4989-8f47-5afc79c56e7c
使用
- 连接
- 创建数据库(字符集 utf8 、 utf8_general_ci)
- 创建表(引擎:默认InnoDB ,字符集:同上)
建表数据类型
- 数值
- 字符串
- 日期
- null
字段属性
unsigned
- 无符号整数
- 不能为负数
zerofill
- 0填充
- 不足的位数补0
自增
非空
拓展
/* 每一个表,都必须存在下列5个字段,未来做项目用的,表示一个记录存在的意义
id 主键
version 乐观锁
is_delete 伪删除
gmt_create 创建时间
gmt_update 修改时间
*/
建表模板
--单表创建
CREATE TABLE IF NOT EXISTS `student` (
`id` INT(4) NOT NULL AUTO_INCREMENT COMMENT '学号',
`name` VARCHAR(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',
`pwd` VARCHAR(20) NOT NULL DEFAULT '123456' COMMENT '密码',
`sex` VARCHAR(2) NOT NULL DEFAULT '女' COMMENT '行呗',
`birthday` DATETIME DEFAULT NULL COMMENT '生日',
`address` VARCHAR(100) DEFAULT NULL COMMENT '地址',
`email` VARCHAR(50) DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
--外键表
CREATE TABLE IF NOT EXISTS `grade`(
`gradeid` INT(10) NOT NULL AUTO_INCREMENT COMMENT '年级id',
`gradename` VARCHAR(30) NOT NULL COMMENT '年级名称',
PRIMARY KEY(`gradeid`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
CREATE TABLE IF NOT EXISTS `student` (
`id` INT(4) NOT NULL AUTO_INCREMENT COMMENT '学号',
`name` VARCHAR(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',
`pwd` VARCHAR(20) NOT NULL DEFAULT '123456' COMMENT '密码',
`sex` VARCHAR(2) NOT NULL DEFAULT '女' COMMENT '行呗',
`birthday` DATETIME DEFAULT NULL COMMENT '生日',
`gradeid` INT(10) NOT NULL COMMENT '年级',
`address` VARCHAR(100) DEFAULT NULL COMMENT '地址',
`email` VARCHAR(50) DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY(`id`),
KEY `FK_gradeid` (`gradeid`),
CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade` (`gradeid`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
常用命令
--查看
SHOW CREATE DATABASE school 查看创建数据库语句
SHOW CREATE TABLE student 查看创建表的语句
DESC student 查看表的结构
--修改
ALTER TABLE teacher RENAME AS teacher1 修改表名
ALTER TABLE teacher1 ADD age INT(3) 添加字段
ALTER TABLE teacher1 MODIFY age VARCHAR(20) 修改字段类型
ALTER TABLE teacher1 CHANGE age age1 INT(4) 修改字段名和类型
--删除
ALTER TABLE teacher1 DROP age1 删除表的字段
DROP TABLE IF EXISTS teacher1 删除表
--外键
ALTER TABLE student
ADD CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade` (`gradeid`) 给没有外键的表,添加外键
--插入
INSERT INTO `grade`(`gradeid`,`gradename`) VALUES(2,'大数据') 插入一个记录
--修改
UPDATE `grade` SET `gradename`='Java' WHERE gradeid = 1 修改单个字段得值
UPDATE `grade` SET `gradename`='Java',`gradeid`=3 WHERE gradeid = 1 修改多个字段的值
--删除
DELETE FROM `grade` WHERE gradeid = 2 删除一个记录
清空表
TRUNCATE `student` 清除自增,delete不清除
DQL查询数据(最重点)
指定字段查询
SELECT * FROM student 查询全部信息
SELECT `name`,`sex` FROM student 查询指定字段信息
SELECT `name` AS 姓名,`sex` AS 性别 FROM student 给字段起别名
SELECT DISTINCT `name`,`sex` FROM student 去重显示
SELECT VERSION() 查看mysql版本
select 100*3-1 as 计算结果 --用来计算
SELECT @@auto_increment_increment 查询自增的步长
where条件查询
--where
SELECT studentNo,'StudentResult' FROM result WHERE StudentResult>=95 AND StudentResult<=100 --查询成绩在95~100分之间
SELECT studentNo,'StudentResult' FROM result WHERE StudentResult BETWEEN 95 AND 100 --同上
--除了1000号学生之外的同学的成绩
SELECT studentNo,'StudentResult' FROM result WHERE studentNo!=1000
SELECT studentNo,'StudentResult' FROM result WHERE not studentNo =1000
--查询姓刘的同学
--like结合 %(代表0到任意个字符)(一个字符)
SELECT `StudentNo`,`StudentName` FROM `student` WHERE StudentName LIKE '刘%'
--查询姓刘的同学,名字后面只有一个字的
SELECT `StudentNo`,`StudentName` FROM student WHERE StudentName LIKE '刘_'
--查询1001,1002,1003号学员
SELECT `StudentNo`,`StudentName` FROM `student` WHERE StudentNo IN (1001,1002,1003);
--查询地址为空的学生null
SELECT `StudentNo`,`StudentName` FROM `student` WHERE address='' OR address IS NULL
联表查询
要求:两张或多张表,且有关联字段
--查询父子信息:把一张表看为两个一模一样的表
SELECT a.`categoryName` As '父栏日',b.`categoryName` As '子栏目'
FROM `category` AS a,`category` AS b WHERE a.`categoryid`=b.`pid`
--查询两张表的字段值,通过员工编号
SELECT e.`emp_no`,e.`first_name`,e.`gender`,d.`dept_no`
FROM employees e
INNER JOIN `dept_emp` d
ON e.`emp_no`=d.`emp_no`
--三张表联合查询,通过 INNER JOIN 加入表、ON 绑定关联的字段
SELECT e.`emp_no`,e.`first_name`,e.`gender`,d.`dept_no`,dp.`dept_name`
FROM employees e
INNER JOIN `dept_emp` d
ON e.`emp_no`=d.`emp_no`
INNER JOIN `departments` dp
ON d.`dept_no` = dp.`dept_no`
分页和排序
--排序 (ASC 升序 、DESC 降序)
SELECT e.`emp_no`,e.`first_name`,e.`gender`,d.`dept_no`,dp.`dept_name`
FROM employees e
INNER JOIN `dept_emp` d
ON e.`emp_no`=d.`emp_no`
INNER JOIN `departments` dp
ON d.`dept_no` = dp.`dept_no`
WHERE dept_name = '生产部'
ORDER BY emp_no ASC
--分页(limit 起始页,页面大小) 规律--(n-1)*5,6 --
select e.`emp_no`,e.`first_name`,e.`gender`,d.`dept_no`,dp.`dept_name`
from employees e
inner join `dept_emp` d
on e.`emp_no`=d.`emp_no`
inner join `departments` dp
on d.`dept_no` = dp.`dept_no`
where dept_name = '生产部'
order by emp_no ASC
limit 0,6
分组和过滤
group by e.gender
分组字段
having 工资>5300 条件和where一样
MySQL函数
常用函数
--数学运算
SELECT ABS(-8)--绝对值
SELECT CEILING(9.4)--向上取整SELECT FLOOR(9.4)--向下取整SELECT RAND()--返回一个0~1之间的随机数SELECT SIGN(10)--判断一个数的符号0-0负数返回-1,正数返回1
字符串
--字符串函数
SELECT CHAR LENGTH('即使再小的帆也能远航’)--字符串长度
SELECT CONCAT('我’,’爱’,你们!)--拼接字符串
SELECT INSERT('我爱编程helloworld',1,2,’超级热爱1)--查询,从某个位置开始替换某个长度
SELECT LOWER('KuangShen')--小写字母
SELECT UPPER(KuangShen')--大写字母SELECT INSTR(I kuangshen','h')--返回第一次出现的子串的索引
SELECT REPLACE('狂神说坚持就能成功,,坚持,努力’)--替换出现的指定字符串
SELECT SUBSTR('狂神说坚持就能成功,4,6)--返回指定的子字符串(源字符串,截取的位置,截取的长度)
SELECT REVERSE('清晨我上马)--反转
--查询姓 周的同学,名字 邹
SELECT REPLACE(studentname,'周','邹')
FROM student
WHERE studentname LIKE '周%'
--时间和日期函数(记住)
SELECT CURRENT DATE()--获取当前日期
SELECT CURDATE()--获取当前日期
SELECT NOW()--获取当前的时间
SELECT LOCALTIME()--本地时间
SELECT SYSDATE()--系统时间
SELECT YEAR(NOW())
SELECT MONTH(NOW())
SELECT DAY(NOW())
SELECT HOUR(NOW())
SELECT MINUTE(NOW())
SELECT SECOND(NOW())
--系统
SELECT SYSTEM_USER()
SELECT USER()
SELECT VERSION()
聚合函数
函数名称 | 描述 |
---|---|
COUNT() | 计数 |
SUM() | 求和 |
AVG() | 平均 |
MAX() | 最大值 |
MIN() | 最大值 |
.... | .... |
MD5加密
增强算法复杂度、不可逆
--MD5加密
UPDATE user1 SET pwd = MD5(pwd) WHERE id = 1
--校验
select * from user1 where name = 'dudu' and pwd = md5('123456')
事务管理(ACID)
一、原子性(atomicity)
一个事务要么全部提交成功,要么全部失败回滚,不能只执行其中的一部分操作,这就是事务的原子性
二、一致性(consistency)
事务的执行不能破坏数据库数据的完整性和一致性,一个事务在执行之前和执行之后,数据库都必须处于一致性状态。
如果数据库系统在运行过程中发生故障,有些事务尚未完成就被迫中断,这些未完成的事务对数据库所作的修改有一部分已写入物理数据库,这是数据库就处于一种不正确的状态,也就是不一致的状态
三、隔离性(isolation)
事务的隔离性是指在并发环境中,并发的事务时相互隔离的,一个事务的执行不能不被其他事务干扰。不同的事务并发操作相同的数据时,每个事务都有各自完成的数据空间,即一个事务内部的操作及使用的数据对其他并发事务时隔离的,并发执行的各个事务之间不能相互干扰。
四、持久性(durability)
一旦事务提交,那么它对数据库中的对应数据的状态的变更就会永久保存到数据库中。--即使发生系统崩溃或机器宕机等故障,只要数据库能够重新启动,那么一定能够将其恢复到事务成功结束的状态
事务提交
--mysq1是默认开启事务自动提交的
SET autocommit=0 /*关闭*/
SET autocommit=1 /*开启(默认的)*/
--手动处理事务
SET autocommit=0 --关闭自动提交
--事务开启
START TRANSACTION --标记一个事务的开始,从这个之后的sql都在同一个事务内INSERTXxINSERTxx
--提交:持久化(成功!)COMMIT
--回滚:回到的原来的样子(失败!)ROLLBACK
--事务结束
SET autocommit=1 --开启自动提交
--了解
SAVEPOINT保存点名 --设置一个事务的保存点
ROLLBACK TO SAVEPOINT 保存点名 --回滚到保存点
RELEASE SAVEPOINT 保存点名 --撤销保存点
索引
索引的分类
- 主键索引(PRIMARY KEY)
- 唯一索引(UNIQUE KEY)
- 常规索引(KEY/INDEX)
- 全文索引(FullText)
原则
- 索引不是越多越好
- 索引一般加在经常被查询的字段上
数据结构
Hash 类型的索引
Btree:InnoDB 的默认数据结构
权限管理和备份
权限
用户在mysql.user表下,可修改相应的权限
--创建用户CREATE USER用户名IDENTIFIEDBY’密码!
CREATE USER kuangshen IDENTIFIED BY'123456'
--修改密码(修改当前用户密码)
SET PASSWORD=PASSWORD('123456')
--修改密码(修改指定用户密码)
SET PASSWORD FOR kuangshen =PASSWORD('123456')
--重命名RENAME USER原来名字TO新的名字
RENAME USER kuangshen To kuangshen2
--用户授权ALL PRIVILEGES全部的权限,库.表
--ALLPRIVILEGES除了给别人授权,其他都能够干
GRANT ALL PRIVILEGES ON*.*TO kuangshen2
--查询权限
SHOW GRANTS FOR kuangshen2 --查看指定用户的权限
SHOW GRANTS FOR root@localhost
--ROOT用户权限
GRANT ALL PRIVILEGES ON*.*TO'root'0'localhost'WITH GRANT OPTION
--撤销权限REVOKE哪些权限,在哪个库撤销,给谁撤销
REVOKE ALL PRIVILEGES ON*.*FROM kuangshen2
--删除用户
DROP USER kuangshen
备份
- 可视化工具 导入导出sql文件
- 命令行
#导出
#mysqldump-h主机-u用户名-p密码数据库表名>物理磁盘位置/文件名
mysqldump-hlocalhost-uroot-p123456 school student >D:/a.sql
#导入
进入mysql命令行
使用数据库
source 路径
例:source d:/a.sql
规范数据库设计
良好的数据库
- 节省内存空间
- 保证数据库完整
- 方便开发系统
设计
- 分析需求:分析业务和需要处理的数据库的需求
- 概要设计:设计关系图E-R图
设计步骤
- 收集信息
- 标识实体
- 实体之间的联系
三大范式
第一范式:每一列都是原子数据项,不可分割
第二范式:每张表之描述一个事情
第三范式:每一列都和主键直接相关,不能间接相关
JDBC
使用方法
- 下载 mysql-connnect-java
- 在项目中新建lib目录
- 放入jar包
- 右击lib,选择 add as Library
实例
public class JDBCDemo {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// 1.加载驱动,静态资源
Class driver = Class.forName("com.mysql.jdbc.Driver");
// 2.用户信息
String url = "jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf8&userSSL=true";
String user = "root";
String pwd = "123456";
// 3.连接成功,数据对象 connection数据库对象(即管理数据库所有操作)
Connection connection = DriverManager.getConnection(url, user, pwd);
// 4.创建sql语句对象 statement专门执行sql语句
Statement statement = connection.createStatement();
// 5.执行sql,返回结果集
String sql = "select * from user1";
ResultSet resultSet = statement.executeQuery(sql); //结果集
while (resultSet.next()){
System.out.println("id:"+resultSet.getObject("id"));
System.out.println("name:"+resultSet.getObject("name"));
System.out.println("pwd:"+resultSet.getObject("pwd"));
System.out.println("=====================");
}
// 6.释放对象
resultSet.close();
statement.close();
connection.close();
}
}
注:prepareStatement , 可以使用 占位符 插入语句,有效防止SQL注入问题
SQL注入
在 ' ' 中插入 ' or '1=1
实现账号密码全部获取
SELECT * FROM users WHERE Name='' or '1=1' AND password ='' or '1=1';
使用idea连接数据库
在 Schemas 选择需要添加的数据库
Statement对象
- 新建db.properties 配置文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf8&userSSL=true
username=root
password=123456
- 编写 JdbcUtils 类
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**
* 数据库连接工具,方便连接,减少冗余
*/
public class JdbcUtils {
private static String driver = null;
private static String url = null;
private static String username = null;
private static String password = null;
// 读取静态配置文件数据
static {
try{
InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
Properties properties = new Properties();
properties.load(in);
driver = properties.getProperty("driver");
url = properties.getProperty("url");
username = properties.getProperty("username");
password = properties.getProperty("password");
Class.forName(driver);
} catch (Exception e) {
e.printStackTrace();
}
}
// 获取连接
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, username, password);
}
// 关闭所有连接
public static void release(Connection connection, Statement statement, ResultSet resultSet){
if(resultSet != null){
try {
resultSet.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(statement != null){
try {
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(connection != null){
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
测试插入
public class TestInsert {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
connection = JdbcUtils.getConnection();
statement = connection.createStatement();
String sql = "insert into user1 values(3,'dudu','1234'),(4,'fdsaf','546')";
int i = statement.executeUpdate(sql);
if(i > 0){
System.out.println("插入成功");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JdbcUtils.release(connection,statement,null);
}
}
}
事务
/**
* 事务: 账户收入和支出
*/
public class TestTransaction {
public static void main(String[] args) {
Connection conn = null;
ResultSet rs = null;
PreparedStatement st = null;
try {
conn = JdbcUtils.getConnection();
// 关闭数据库自动提交,自动会开启事务
conn.setAutoCommit(false);
String sql1 = "update account set money = money-100 where name = 'dudu'";
st = conn.prepareStatement(sql1);
st.executeUpdate();
String sql2 = "update account set money = money+100 where name = 'gangan'";
st = conn.prepareStatement(sql2);
st.executeUpdate();
// 业务完毕,提交事务
conn.commit() ;
System.out.println("成功!");
} catch (SQLException throwables) {
throwables.printStackTrace();
try {
conn.rollback(); //如果失败,则回滚
} catch (SQLException e) {
e.printStackTrace();
}
}finally {
JdbcUtils.release(conn,st,rs);
}
}
}
数据库连接池
数据库连接 ==》执行 ==》释放 浪费系统资源
因此,采用 连接池 技术
池化: 开门 == 》 服务 == 》 关门 特点容纳一批人
- 最小连接数 10
- 最大连接数 15
- 等待超时 100ms
编写连接池 , 实现接口 DataSource
开源数据源实现
- DBCP
- C3P0
- Druid:阿里巴巴
注:使用这些不用写连接数据库的代码了
DBCP
需要两个jar包 : commons-dbcp-1.4、commons-pool-1.6
下载网址
http://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi
http://commons.apache.org/proper/commons-pool/download_pool.cgi
- 配置 dbcp.properties
#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf8&userSSL=true
username=root
password=123456
#<!-- 初始化连接 -->
dataSource.initialSize=10
#<!-- 最大空闲连接 -->
dataSource.maxIdle=20
#<!-- 最小空闲连接 -->
dataSource.minIdle=5
#最大连接数量
dataSource.maxActive=50
#是否在自动回收超时连接的时候打印连接的超时错误
dataSource.logAbandoned=true
#是否自动回收超时连接
dataSource.removeAbandoned=true
#超时时间(以秒数为单位)
#设置超时时间有一个要注意的地方,超时时间=现在的时间-程序中创建Connection的时间,如果maxActive比较大,比如超过100,那么removeAbandonedTimeout可以设置长一点比如180,也就是三分钟无响应的连接进行回收,当然应用的不同设置长度也不同。
dataSource.removeAbandonedTimeout=180
#<!-- 超时等待时间以毫秒为单位 -->
#maxWait代表当Connection用尽了,多久之后进行回收丢失连接
dataSource.maxWait=1000
- JdbcUtils_DBCP
/**
* DBCP
*/
public class JdbcUtils_DBCP {
private static DataSource dataSource = null;
// 读取静态配置文件数据
static {
try{
InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("dbcpConfig.properties");
Properties properties = new Properties();
properties.load(in);
// 创建数据源,工厂模式 --》 创建
dataSource = BasicDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
// 获取连接
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
// 关闭所有连接
public static void release(Connection connection, Statement statement, ResultSet resultSet){
if(resultSet != null){
try {
resultSet.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(statement != null){
try {
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(connection != null){
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
测试同 Statement对象中的插入一样
C3P0
需要一个jar :c3p0-0.9.5.2.jar
https://pan.baidu.com/s/1o9cBkMVb_kZmAksZjjoZYg 密码:c7pr
- 配置 c3p0-config.xml
<c3p0-config>
<default-config>
<property name="user">root</property>
<property name="password">123456</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/school</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">10</property>
</default-config>
<named-config name="MySQL">
<property name="user">root</property>
<property name="password">123456</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/school</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">10</property>
</named-config>
</c3p0-config>
-
comboPooledDataSource = new ComboPooledDataSource("MySQL");