下述部分内容来自
ACID
DCL
mysql
我只是做了一个总结、若侵则删。
DB、DBMS、SQL
DB(database)
长期保存在计算机的存储设备上,按照一定规则组织起来,可以被用户或应用共享的数据集合。
DBMD(database management system)
一种操作和管理数据库的大型软件,用于建立、使用和维护数据库,对数据库进行统一管理和控制,以保证数据库的安全性和完整性。用户通过数据库管理系统访问数据库中的数据。
SQL(Structure Query Language)
构化查询语言。关系型数据库中进行操作标准语言。编程语言。
SQL对大小写不敏感;结尾需要使用分号
SQL的四大组成
名称 | 作用 |
---|---|
DDL(Data Definition Language)数据定义语言 | 用来定义数据库对象:库、表、列等。包括创建表,修改表,删除表。 |
DML(Data Manipulation Language)数据操纵语言 | 用来定义数据库记录:是对表中数据的操作。包括插入,更新,删除数据 |
DCL(Data Control Language )数据控制语言 | 用来定义访问权限和安全级别 |
DQL(Data QueryLanguage)数据查询语言 | 用来查询记录(数据):只有SELECT语句 |
DDL(Data Definition Language)数据定义语言
DDL操作数据库
创建数据库
CREATE DATABASE 数据库名称; – 创建数据库
CREATE DATABASE 数据库名 SET GBK; – 创建数据库并设置为gbk编码格式
CREATE DATABASE 数据库名 SET GBK COLLATE gbk_chinede_ci; – 创建一个使用gbk字符集,并带校对规则的数据库
查询数据库
SHOW DATABASES; – 查看当前数据库服务器中的所有数据库
SHOW CREATE DATABASE 数据库名; --查看创建数据库时的定义信息
删除数据库
DROP DATABASE 数据库名; – 删除指定数据库
修改数据库
ALTER DATABASE 数据库名 CHARACTER SET utf8; – 将数据库的字符集改为utf8
数据库编码
character_set_client为客户端编码方式;
character_set_connection为建立连接使用的编码;
character_set_database数据库的编码;
character_set_results结果集的编码;
character_set_server数据库服务器的编码;
如果数据乱码,可以show variables like ‘character%’; 查看编码,如果不为utf8,自行百度如何解决。
DDL操作数据表
在创建表格之前需要先选择表格创建的数据库,所以需要选择数据库:
USE 数据库名; – 使用数据库
SELECT DATABASE(); – 选中数据库
创建数据表
语法: CREATE TABLE 表名(
字段1 字段类型,
字段2 字段类型,
…
字段n 字段类型
);
常用数据类型:
int:整型
double:浮点型;
char:固定长度字符串类型;
varchar:可变长度字符串类型;
text:字符串类型;
blob:字节类型;
date:日期类型,格式为:yyyy-MM-dd;
time:时间类型,格式为:hh:mm:ss
timestamp:时间戳类型 yyyy-MM-dd hh:mm:ss 会自动赋值
datetime:日期时间类型 yyyy-MM-dd hh:mm:ss
常用操作 (默认表为employee) | 代码 |
---|---|
显示当前数据库中所有表 | SHOW TABLES; |
查看表的字段信息 | DESC employee; |
在表中插入一个image列,此列为字节类型(插入列的时必须指定列的类型) | ALTER TABLE employee ADD image BOLB; |
修改job列,使其长度为60 | ALTER TABLE employee MODIFY job VARCHAR(60); |
删除image列,一次只能删一列 | ALTER TABLE employee DROP image; |
表名改为user | RENAME TABLE employee TO user; |
查看表格的创建细节 | SHOW CREATE TABLE employee; |
修改表的字符集为gbk | ALTER TABLE employee CHARACTER SET GBK; |
列名name修改为username | ALTER TABLE employee CHANGE name username VARCHAR(100); |
删除表 | DROP TABLE emoloyee; |
DML(Data Manipulation Language)数据操纵语言
DML是对表中的数据进行增、删、改的操作
INSERT增加操作:
插入一条记录的语法:
INSERT INTO 表名(字段1,字段2,…) VALUES(值1,值2,…);
插入操作中要注意:字段和值要一一对应,字段相当java中的形参,值相当于实参,值数可以少于字段数,但不能多。插入空值使用null。插入字符串和日期需要使用单引号括起来。
UPDATE更新操作:
语法: UPDATE 表名 SET 列名1=列值1,列名2=列值2,… WHERE 列名=列值;
DELETE删除操作:
语法:DELETE FROM 表名 (WHERE 列名=值);
DQL(Data QueryLanguage)数据查询语言
数据库执行DQL语句不会对数据进行改变,二十让数据库发送结果集给客户端。查询发挥的结果集是一张虚拟表。
基本语法: SELECT 列名 FROM 表名
语法:
SELECT selection_list /要查询的列名称/
FROM table_list /要查询的表名称/
WHERE condition /行条件/
GROUP BY grouping_columns /对结果分组/
HAVING condition /分组后的行条件/
ORDER BY sorting_columns /对结果分组/
LIMIT offset_start, row_count /结果限定/
条件查询
条件查询就是在查询时给出WHERE子句,在WHERE子句中可以使用如下运算符及关键字:
=、!=、<>、<、<=、>、>=;
BETWEEN…AND;
IN(set);
IS NULL; IS NOT NULL
AND;
OR;
NOT;
说明:
<>的作用与!=的作用完全相同,只是<>出现的比较早。
BETWEEN…AND 还可以查日期的范围
IN中的参数为查询范围,各值之间用逗号隔开
IS NULL 是进行非空判断,与之相对的是IS NOT NULL
模糊查询(LIKE)
模糊查询使用通配符补充模糊地方。通配符有两个:’_‘表示一个任意字符,’%'表示任意多个字符。使用模糊查询需要用到关键字:LIKE。
举例:(比如我们要找的是s开头后面两位任意,第四位为0后面任意长度的学生姓名~)
SELECT * FROM emp WHERE sname LIKE 's__0%';
字段控制查询(DISTINCT)
比如我们要查emp表中sal,想了解一下员工的薪水档次都有那些,就不想看每个人的薪水,字段控制不要查询重复的薪水:
SELECT DISTINCT sal FROM emp;
排序(ORDER BY)
ASC:升序(默认值)
DESC:降序
分组查询
比如说我们需要按照部门来查询每个部门的工资和,就需要按照部门来分组。
子句:GROUP BY
查询每个部门的编号,人数以及每个部门的工资和:
SELECT deptno,COUNT(*) num,SUM(sal) SUM FROM emp GROUP BY deptno ;
子句:HAVING 作用是分组后对数据进行过滤,区别于WHERE
聚合函数
聚合函数是用来做纵向运算的函数。
COUNT():统计指定列不为NULL的记录行数;
MAX():计算指定列的最大值,如果指定列是字符串类型,那么使用字符串排序运算;(字典比较)
MIN():计算指定列的最小值,如果指定列是字符串类型,那么使用字符串排序运算;(字典比较)
SUM():计算指定列的数值和,如果指定列类型不是数值类型,那么计算结果为0;
AVG():计算指定列的平均值,如果指定列类型不是数值类型,那么计算结果为0;
MySQL方言——LIMIT
LIMIT 用来限定查询结果的起始行以及总行数。
与编程语言相同,这里的起始行索引也是从0开始的。
从0行开始查询5行记录:
SELECT * FROM emp LIMIT 0,5;
查询代码的书写顺序和执行顺序
查询语句的书写顺序:SELECT-FROM-WHERE-GROUP BY-HAVING-ORDER BY-LIMIT
查询语句的执行顺序:FROM-WHERE-GROUP BY-HAVING-SELECT-ORDER BY-LIMIT
DCL(Data Control Language )数据控制语言
用户管理
查询用户
MySQL把用户的数据存放在 “mysql” 数据库的 “user” 表中。
SELECT * FROM user;
创建用户
CREATE USER ‘用户名’@‘主机名’ IDENTIFIED BY ‘密码’; /*
主机名为 localhost 时仅限本地登陆,填写 % 时任何机器都可以登陆 */
删除用户
DROP USER ‘用户名’@‘主机名’;
修改用户密码
UPDATE USER SET PASSWORD = PASSWORD(‘新密码’) WHERE USER = ‘用户名’; – 普通方式
SET PASSWORD FOR ‘用户名’@‘主机名’ = PASSWORD(‘新密码’); – 特有的简化方式
重置 root 用户密码
1) 命令提示符在管理员模式下停止 MySQL 服务: net stop mysql
2) 管理员模式下使用无验证方式启动MySQL服务: mysqld --skip-grant-tables
3) 开启新的命令行窗口进入MySQL: mysql
4) 进入 ‘mysql’ 数据库: USE mysql;
5) 使用修改用户密码语句对root密码进行重置。
6) 启动"运行"窗口,运行命令结束"mysqld"进程: taskkill /im mysqld.exe /f
7) 命令提示符在管理员模式下启动 MySQL 服务: net start mysql
8) 可以用新密码登陆 root 用户。
权限管理
查询用户权限
SHOW GRANTS FOR ‘用户名’@‘主机名’;
授予权限
GRANT 权限列表 ON 数据库名.表名 TO ‘用户名’@‘主机名’;
GRANT ALL ON . TO ‘用户名’@‘主机名’; – 使用通配符给用户授予全部权限
撤销权限
REVOKE 权限列表 ON 数据库名.表名 FROM ‘用户名’@‘主机号’;
数据的完整性实(实体完整性、域完整性、引用完整性)
作用:保证用户输入的数据保存到数据库中是正确的。
实现方法:在创建表时表中添加约束(也可以使用alter语句添加)。
实体完整性
实体(entity):表中的一行(一条记录)。
主键的值不能为空或部分为空的约束条件称为实体完整性。实体完整性要求每一个表中的主键字段都不能为空或者重复的值。实体完整性指表中行的完整性。要求表中的所有行都有唯一的标识符,称为主关键字。主关键字是否可以修改,或整个列是否可以被删除,取决于主关键字与其他表之间要求的完整性。
作用:表示每一行数据不重复。
分类:主键约束(PRIMARY KEY) 唯一约束(UNIQUE) 自动增长列(AUTO-INCREMENT)
一个列表可以有多个约束,约束之间用空格隔开。
PRIMARY KEY主键约束:数据唯一(数据不能重复),且不能为null
一个表中只能有一个PK约束,联合PK约束算是一个PK约束。
主键约束的格式:[CONSTRAINT <约束名>] PRIMARY KEY [字段名]
方式一:
CREATE TABLE student(
sid INT PRIMARY KEY,
sname VARCHAR(20)
);
方式二:这种方式的优点在于可以创建联合主键——同时参照所有主键,都完全相同视为数据不唯一,所有键联合为一个主键。
– 创建单主键表
CREATE TABLE student1(
sid INT,
sname VARCHAR(20),
PRIMARY KEY(sid)
);
-- 创建联合主键表
CREATE TABLE student1_1(
sid INT,
sname VARCHAR(20),
score DOUBLE,
PRIMARY KEY(sid,score)
);
方式三:这种方式的优点是可以给已经存在的表添加主键且可以添加联合主键
– 在表格外部给表添加单主键
CREATE TABLE student2(
sid INT,
classid INT,
sname VARCHAR(20)
);
ALTER TABLE student2 ADD CONSTRAINT PRIMARY KEY(sid);
– 在表格外部给表格添加联合主键
CREATE TABLE student2_1(
sid INT,
classid INT,
sname VARCHAR(20)
);
ALTER TABLE student2_1 ADD PRIMARY KEY(sid,classid);
UNIQUE唯一约束:数据唯一,可以有null
唯一约束在MySQL中可以有多个null(可以看成bug了),在ORACLE中只能有一个null,否则报错。
创建UNQUE约束的方法:
方法一
CREATE TABLE student3(
sid INT ,
sname VARCHAR(20) UNIQUE
);
方法二
CREATE TABLE student3_1(
sid INT ,
sname VARCHAR(20) UNIQUE,
sage VARCHAR(5) UNIQUE
);
方法三
CREATE TABLE student3_2(
sid INT ,
sname VARCHAR(20),
sage VARCHAR(5)
);
ALTER TABLE student3_2 ADD UNIQUE (sname);
删除唯一约束的方法:
ALTER TABLE student3_2 DROP INDEX sname; -- 这样可以删除sname作为的唯一约束
AUTO-INCREMENT自动增长列
sqlserver数据库 (identity) oracle数据库( sequence)
自动增长列的约束是用来给键添加自动增加(只针对整数)的。如果没有定义键使用AUTO-INCREMENT,会报出一下错误:Incorrect table definition; there can be only one auto column and it must be defined as a key
需要注意的是:我们在插入数据的时候sid因为被自动增长约束而整数加加,那么,如果在插入记录的时候,如果删除了插入的记录,那么编号会继续随着删除的记录的号加加,不会因为删除记录而退回重新加。
域完整性
域完整性是针对某一具体关系数据库的约束条件,它保证表中某些列不能输入无效的值。域完整性指列的值域的完整性。如数据类型、格式、值域范围、是否允许空值等。
域完整性约束:数据类型 非空约束(NOT NULL)默认约束(DEFAULT) 检查约束(CHECK这个MySQL不支持)
非空约束NOT NULL
约束添加在一个字段的定义中,约束这个字段红不能有null。
默认值约束DEFAULT
约束添加在一个字段的定义中,约定这个字段的默认填充为DEFAULT 后的内容。后面在插入数据时,如果插入的值与默认值相同,那么值处填写DEFAULT,否则填写输入的值:
可以在创建表的时候直接给字段添加默认值,也可以在创建表后使用下面的方法:
ALTER TABLE USER ADD COLUMN gender CHAR(3) DEFAULT '男';
插入的值与默认值相同:
INSERT INTO USER
VALUES(5,'高七','012','[email protected]','2000-5-1',DEFAULT);
引用完整性(参照完整性)——外键约束
外键约束关键字: FOREIGN KEY
外键约用来在两个表之间建立连接,它可以是一列或者多列。一个表可以有一个或者多个外键。外键对应的是参照完整性,一个表的外键为空值,若不为空值,则每个外键值必须等于另一个表中主键的某个值。
外键:首先外键是表中的一个字段,可以不是本表的主键,但对应另外一个表的主键。外键的主要作用是保证数据引用完整性,定义外键后,不允许删除在另外一个表种的具有关联关系的行,外键的作用是保持数据的一致性,完整性。
主表(父表):相关联字段中,主键所在的表。
从表(字表):相关联字段种,外键所在的表。
语法:[CONSTRAINT <外键名>] FOREIGN KEY 字段名1 [,字段名2,…] REFERENCES <主键列1> [,主键列2,…]
一个主外键sid约束的Demo:
CREATE TABLE connStudent(
sid INT PRIMARY KEY,
sname VARCHAR(20),
sbirthday DATE
);
CREATE TABLE connScore(
id INT,
sid INT,
sscore DOUBLE,
CONSTRAINT fk_connScore_connStudent FOREIGN KEY(sid) REFERENCES connStudent(sid)
);
可以看到主表与从表的关系
第二种添加外键的方式:
ALTER TABLE connScore ADD CONSTRAINT fk_connStudent_connScore FOREIGN KEY(sid) REFERENCES connStudent(sid);
表与表的关系
表与表的关系有三种:一对一,一对多(多对一),多对多。在确定表与表的关系的时候需要确定主表和从表,依赖性更强的是从表,必须存在的是主表,这样就可以知道外键该设置在那个表中了。
一对多
一个部门可以有多个员工,一个员工只能属于一个部门; 一个客户对应多个联系人,一个联系人只能属于某一个客户。
一对多建表原则:在多的一方创建外键对应一的一方的主键。
多对多
一个学生可以选择多门课程,一门课程可以被多个学生选择;一个订单可以包含多个商品,一个商品可以在多个订单中;一个用户可以选择多个角色,一个角色可以被多个用户选择。
多对多建表原则:创建中间表,中间表中至少有两个字段分别作为外键指向多对多双方的主键。(主键对应)
一对一
一般都建一张表。
一对一建表原则:唯一外键对应/主键对应。(不常用,且可合并)
多表查询
连接查询
连接查询就是求出多个表的乘积,例如t1连接t2,那么查询出的结果就是t1*t2
内连接
SELECT e.ename,e.sal,e.comm,d.dname FROM emp e INNER JOIN dept d ON e.deptno=d.deptno;
这里INNER 和 NO 关键字都是可以省略的。
外连接
外连接可以分为左连接和右连接,两种连接方式大同小异,只是左连接按照条件查询时参照左边的表的值,右连接按照参照条件参照右边表的值。当两个表的查询条件都满足时,查询出来的结果与内连接相同;当查询只满足左边查询时,使用左查询可以查出表,右表部分使用null填充,使用右连接无法查询出这条记录;当查询只满足左边查询时道理相似。
例子来说明:表中emp表中“张三”这条记录中,部门编号为50,而dept表中不存在部门编号为50的记录,所以“张三”这条记录,不能满足e.deptno=d.deptno这条件。但在左连接中,因为emp表是左表,所以左表中的记录都会查询出来,即“张三”这条记录也会查出,但相应的右表部分显示NULL。
自然连接
自然连接无需你去给出主外键等式,它会自动找到这一等式。找到这一等式需要两张连接的表中名称和类型完全一致的列作为条件,这样就可以被自然找到。
子查询
一个select语句中包含另一个完整的select语句。
子查询就是嵌套查询,即SELECT中包含SELECT,如果一条语句中存在两个,或两个以上SELECT,那么就是子查询语句了。
1.子查询出现的位置:
where后,作为条为被查询的一条件的一部分;
from后,作表;
2.当子查询出现在where后作为条件时,还可以使用如下关键字:
any
all
3.子查询结果集的形式:
单行单列(用于条件)
单行多列(用于条件)
多行单列(用于条件)
多行多列(用于表)
MySQL中的函数
四大天王 ACID
事务具有4个特征,分别是原子性、一致性、隔离性和持久性,简称事务的ACID特性;
一、原子性(atomicity)
一个事务要么全部提交成功,要么全部失败回滚,不能只执行其中的一部分操作,这就是事务的原子性
二、一致性(consistency)
事务的执行不能破坏数据库数据的完整性和一致性,一个事务在执行之前和执行之后,数据库都必须处于一致性状态。
如果数据库系统在运行过程中发生故障,有些事务尚未完成就被迫中断,这些未完成的事务对数据库所作的修改有一部分已写入物理数据库,这是数据库就处于一种不正确的状态,也就是不一致的状态
三、隔离性(isolation)
事务的隔离性是指在并发环境中,并发的事务时相互隔离的,一个事务的执行不能不被其他事务干扰。不同的事务并发操作相同的数据时,每个事务都有各自完成的数据空间,即一个事务内部的操作及使用的数据对其他并发事务时隔离的,并发执行的各个事务之间不能相互干扰。
在标准SQL规范中,定义了4个事务隔离级别,不同的隔离级别对事务的处理不同,分别是:未授权读取,授权读取,可重复读取和串行化
1、读未提交(Read Uncommited),该隔离级别允许脏读取,其隔离级别最低;比如事务A和事务B同时进行,事务A在整个执行阶段,会将某数据的值从1开始一直加到10,然后进行事务提交,此时,事务B能够看到这个数据项在事务A操作过程中的所有中间值(如1变成2,2变成3等),而对这一系列的中间值的读取就是未授权读取
2、授权读取也称为已提交读(Read Commited),授权读取只允许获取已经提交的数据。比如事务A和事务B同时进行,事务A进行+1操作,此时,事务B无法看到这个数据项在事务A操作过程中的所有中间值,只能看到最终的10。另外,如果说有一个事务C,和事务A进行非常类似的操作,只是事务C是将数据项从10加到20,此时事务B也同样可以读取到20,即授权读取允许不可重复读取。
3、可重复读(Repeatable Read)
就是保证在事务处理过程中,多次读取同一个数据时,其值都和事务开始时刻是一致的,因此该事务级别禁止不可重复读取和脏读取,但是有可能出现幻影数据。所谓幻影数据,就是指同样的事务操作,在前后两个时间段内执行对同一个数据项的读取,可能出现不一致的结果。在上面的例子中,可重复读取隔离级别能够保证事务B在第一次事务操作过程中,始终对数据项读取到1,但是在下一次事务操作中,即使事务B(注意,事务名字虽然相同,但是指的是另一个事务操作)采用同样的查询方式,就可能读取到10或20;
4、串行化
是最严格的事务隔离级别,它要求所有事务被串行执行,即事务只能一个接一个的进行处理,不能并发执行。
四、持久性(durability)
一旦事务提交,那么它对数据库中的对应数据的状态的变更就会永久保存到数据库中。–即使发生系统崩溃或机器宕机等故障,只要数据库能够重新启动,那么一定能够将其恢复到事务成功结束的状态
JDBC
事务提交
自动提交事务
系统默认自动提交事务,但是也带来了许多不方便(回滚和异常)。
手动提交事务
事务隔离级别(针对多线程下的数据安全问题)
JDBC源码
package P2020_05_21;/*
@author:Qian
@time:2020/5/22
*/
import java.sql.*;
public class mysqlTest {
//连接数据库
static Connection connection;
//mysql执行
static PreparedStatement preparedStatement;
//数据库返回的结果
static ResultSet resultSet;
//数据库地址
static String url = "jdbc:mysql://localhost:3306/xxx?characterEncoding=utf-8";
//数据库名称
static String user = "xxx";
//数据库密码
static String password = "xxx";
/*
数据库初始化
*/
public Connection getConnection() {
//加载数据库驱动类
try {
Class.forName("com.mysql.jdbc.Driver");
System.out.println("数据库驱动加载成功");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//获取数据库连接对象
try {
connection = DriverManager.getConnection(url, user, password);
System.out.println("数据库连接成功");
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
//查询
public void selectFromTable(String sql) {
try {
//设置事物隔离级别
connection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
//设置手动提交事务
connection.setAutoCommit(false);
preparedStatement = connection.prepareStatement(sql);
resultSet = preparedStatement.executeQuery();
/*
获取数据集的列数
*/
ResultSetMetaData rsmd = resultSet.getMetaData();
int columnCount = rsmd.getColumnCount();//ResultSet的总列数
/*
遍历结果集
*/
while (resultSet.next()) {
for (int i = 1; i < columnCount + 1; i++) {
if (i == columnCount) {
System.out.print(resultSet.getString(i));
} else {
System.out.print(resultSet.getString(i) + "---border---");
}
}
System.out.println();
System.out.println();
}
//提交事务
connection.commit();
} catch (SQLException throwables) {
//如果发生异常、则回滚事务 不做任何改变
try {
connection.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
throwables.printStackTrace();
}
}
//更新
public void updateFromTable(String sql) {
try {
//设置事物隔离级别
connection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
//设置手动提交事务
connection.setAutoCommit(false);
preparedStatement = connection.prepareStatement(sql);
int handleResult = preparedStatement.executeUpdate();
System.out.println("受影响的行数" + handleResult);
//提交事务
connection.commit();
} catch (SQLException throwables) {
//如果发生异常、则回滚事务 不做任何改变
try {
connection.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
throwables.printStackTrace();
}
}
public static void main(String[] args) {
mysqlTest mysqlTest = new mysqlTest();
//初始化数据库
connection = mysqlTest.getConnection();
//数据库操作
String sql = "drop table qian";
mysqlTest.updateFromTable(sql);
//关闭连接
try {
resultSet.close();
preparedStatement.close();
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
代码已经写好了
对数据库操作一次,写n行代码
对数据库操作一次,写n行代码
对数据库操作一次,写n行代码
这是我们想要的吗?
write Less,Do More(使用dbutils)
各位自行搜索dbutils