[Crazy God habla sobre Java] Notas detalladas de MySQL (completas)

Directorio de artículos

1. Primera introducción a MySQL

JavaEE: desarrollo de Java a nivel empresarial Fondo
de front-end web (página: visualización: datos)
(punto de conexión: conectarse a la base de datos JDBC, conectarse al front-end (controlar el salto de vista, pasar datos al front-end))
base de datos (almacenamiento de datos, Txt, Excel, Word)

Solo puedo escribir código, aprender bien las bases de datos y básicamente ganarme la vida:

¡Sistemas operativos, estructuras de datos y algoritmos! ¡Sé un buen programador!

Matemáticas discretas, circuitos digitales, arquitectura, principios de compilación. + Experiencia práctica, excelente programador.

1.1 ¿Por qué aprender la base de datos?

1. Requisitos laborales
2. En el mundo actual, en la era del big data, quienes obtienen los datos ganan el mundo
3. Demanda forzada: almacenar datos
4. La base de datos es la existencia central de DBA en todos los sistemas de software

1.2 ¿Qué es una base de datos?


Base de datos: concepto (DB, DataBase) : almacén de datos, software, instalado en uno de los sistemas operativos (Windows, Linux, Mac). SQL puede almacenar una gran cantidad de datos (¡es necesario optimizar más de 5 millones)!
Función: almacenar datos, administrar datos Excel

1.3 Clasificación de bases de datos

Base de datos relacional: (SQL)

  • MySQL, Oracle, SQL Server, DB2, SQLite
  • Los datos se almacenan a través de relaciones entre tablas y entre filas y columnas.

Base de datos no relacional: (NoSQL) No solo SQL

  • Redis y MongDB
  • Las bases de datos no relacionales y el almacenamiento de objetos están determinados por las propiedades del propio objeto.

DBMS (sistema de gestión de bases de datos)

  • El software de gestión de bases de datos gestiona, mantiene y obtiene de forma científica y eficaz nuestros datos.
  • MySQL, sistema de gestión de datos!

1.4 Introducción a MySQL

MySQL es un sistema de gestión de bases de datos relacionales
Vida anterior: empresa sueca MySQL AB
Vida actual: un producto de Oracle
MySQL es uno de los mejores software de aplicación RDBMS (sistema de gestión de bases de datos relacionales).
El software de base de datos de código abierto
es pequeño en tamaño, rápido en velocidad, bajo en costo total de propiedad y relativamente bajo en costos de contratación.
Sitios web pequeños y medianos, o sitios web grandes,
sitio web oficial de clusters:

1.5 Conectarse a la base de datos

¡Conexión de línea de comando!

mysql -u root -p --连接数据库
输入密码

#设置管理员密码的
update mysql.user set authentication_string=password('root') where user='root' and Host='localhost';  --修改密码

flush privileges;--刷新权限
--------------------------------------------------
--所有语句使用;结尾--

show databases;--查看所有的数据库
use school--切换数据库, use 数据库名
--
show tables;--查看数据库中所有的表
describe student;--显示数据库中所有的表的信息
create database westos;--创建一个数据库
exit;--退出连接

--单行注释(sql本来注释)
/*
多行注释
*/

imagen.png
imagen.png

2. Base de datos de operaciones

Operar la base de datos》Operar las tablas en la base de datos》Operar los datos de las tablas en
la base de datosMySQL no distingue entre mayúsculas y minúsculas

2.1 Base de datos de operación

Crear base de datos

CREATE DATABASE IF NOT EXISTS student;

Eliminar base de datos

DROP DATABASE student;

Usar base de datos

USE student;

Ver base de datos

SHOW DATABASES;

2.2 Tipos de columnas de base de datos

valor numérico

  • tinyint datos muy pequeños 1 byte
  • Smallint datos más pequeños 2 bytes
  • mediumint tamaño mediano 3 bytes
  • int entero estándar de 4 bytes (de uso común)
  • bigint datos más grandes 8 bytes
  • flotante punto flotante número 4 bytes
  • número de coma flotante doble 8 bytes (problema de precisión)
  • decimal es un número de punto flotante en forma de cadena, generalmente utilizado en cálculos financieros.

cadena

  • cadena de caracteres tamaño fijo 0-255
  • cadena de variable varchar 0-65535 (de uso común)
  • texto pequeño texto pequeño 2^8-1
  • texto cadena de texto 2^16-1 (guardar texto grande)

hora Fecha

java.util.Fecha

  • fecha AAAA-MM-DD, fecha
  • hora HH:mm:ss formato de hora
  • fecha y hora AAAA-MM-DD HH:mm:ss el formato de hora más utilizado
  • marca de tiempo El número de milisegundos desde la marca de tiempo 1970.1.1 hasta ahora
  • el año representa el año

nulo

  • Sin valor, desconocido
  • Tenga en cuenta que no utilice nulo para la operación , el resultado será nulo

2.3 Tipos de campos de la base de datos (puntos clave)

sin firmar:

  • entero sin signo
  • Declarar que la columna no puede declarar números negativos

relleno cero:

  • 0 acolchado
  • La longitud de 10 es 1 – 0000000001. Los dígitos que faltan se rellenan con ceros.

Autoincremento:

  • Generalmente entendido como incremento automático, agrega automáticamente +1 al registro anterior.
  • Generalmente se usa para diseñar un índice de clave primaria único, que debe ser de tipo entero
  • Puede personalizar el valor inicial y el tamaño del paso del incremento automático de la clave principal.

no nulo no nulo

  • Suponiendo que esté configurado como no nulo, si no le asigna un valor, se informará un error.
  • NULL Si no se completa, el valor predeterminado es NULL

por defecto:

  • ¡Establezca el valor predeterminado!

Extensiones:

/* 每一个表,都必须存在以下五个字段!未来做项目用的,表示一个记录存在意义!
id            主键
version       乐观锁
is_delete     伪删除
gmt_create    创建时间
gmt_update    修改时间
*/

2.4 Crear tabla de base de datos

--目标:创建一个schoo1数据库
--创建学生表(列,字段)使用SQL 创建
--学号int   登录密码varchar(20)   姓名,性别varchar(2)  出生日期(datatime)  家庭住址,emai1
--注意点使用英文(),表的名称和字段尽量使用括起来

-- AUTO_ INCREMENT 自增
-- COMMENT 属性注释
-- DEFAULT 默认值
-- NUT NULL 必须不为空
-- 字符串使用单引号括起来!
-- ENGINE=INNODB 设置引擎
-- 所有的语句后面加,(英文的),最后一个不用加

-- PRIMARY KEY 主键,一般一个表只有一个唯一的主键!
CREATE DATABASE school
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


SHOW CREATE DATABASE school -- 查看建立数据库的语句
SHOW CREATE TABLES student -- 查看建立数据表的语句

DESC student --显示表的结构

2.5 Tipo de tabla de datos (motor de base de datos)

MISAM INNODB
Soporte de transacciones no apoyo apoyo
Bloqueo de fila de datos no apoyo apoyo
restricciones de clave externa no apoyo apoyo
Índice de texto completo apoyo no apoyo
tamaño del espacio de la tabla menor Más grande, aproximadamente el doble que MYISAM.

Operaciones de uso generales:

  • MYISAM ahorra espacio y es más rápido.
  • INNODB tiene alta seguridad, procesamiento de transacciones y operaciones multitabla y multiusuario.

ubicación en el espacio físico

Todos los archivos de la base de datos se almacenan en el directorio de datos y una carpeta corresponde a una base de datos. La
esencia sigue siendo el almacenamiento de archivos.
La diferencia entre los archivos físicos del motor MySQL

  • InnoDB tiene solo un archivo *.frm en la tabla de la base de datos y el archivo ibdata1 en el directorio de nivel superior
  • Archivos correspondientes a MYISAM
    • *.frm - archivo de definición de estructura de tabla
    • *.MYD - archivo de datos
    • *.MYI - archivo de índice

Establecer la codificación del juego de caracteres de la base de datos

Si no se establece, será la codificación del juego de caracteres predeterminado de mysql - (no se admite el chino)
Puede configurar la codificación predeterminada en my.ini (no recomendado)character-set-server=utf8

2.6 Modificar y eliminar tabla

Revisar

-- 修改表名 ALTER TABLE 旧表面 AS 新表名
ALTER TABLE student RENAME AS student1
-- 增加表的字段 ALTER TABLE 表名 ADD 字段名 列属性
ALTER TABLE student1 ADD age INT(11)
-- 修改表的字段(重命名,修改约束)
ALTER TABLE student1 MODIFY age VARCHAR(11)  -- 修改约束
ALTER TABLE student1 CHANGE age age1 INT(1)  -- 字段重命名,也可修改约束

-- 删除表的字段
ALTER TABLE student1 DROP age1

Eliminar tabla

DROP TABLE IF EXISTS `student1`

Todas las operaciones de creación y eliminación deben juzgarse tanto como sea posible para evitar errores.Nota
:

  • `` nombre de campo, use este paquete
  • Comentario – ​​/**/
  • Las palabras clave SQL no distinguen entre mayúsculas y minúsculas, se recomienda escribirlas en minúsculas
  • Todos los símbolos están en inglés.

3. Gestión de datos MySQL

3.1 Claves externas (comprensión)

Método 1: agregar restricciones al crear una tabla (problemático, más complicado)

use school;
CREATE TABLE `grade`(
  `gradeid` INT(10) NOT NULL AUTO_INCREMENT COMMENT '年级id',
  `gradename` VARCHAR(50) NOT NULL COMMENT '年级名称',
  PRIMARY KEY (`gradeid`)
);
-- 学生表的 gradeid 字段 要去引用年级表的gradeid
-- 定义外键KEY
-- 给这个外键添加约束(执行引用) references 引用
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`),
  FOREIGN KEY (`gradeid`) REFERENCES `grade` (gradeid)
)ENGINE=INNODB DEFAULT CHARSET=utf8

imagen.png

Al eliminar una tabla con una relación de clave externa, primero debe eliminar la tabla referenciada (tabla esclava) y luego eliminar la tabla referenciada (tabla maestra) Método 2: agregue la
clave externa después de crear correctamente la tabla.

CREATE TABLE `grade`(
  `gradeid` INT(10) NOT NULL AUTO_INCREMENT COMMENT '年级id',
  `gradename` VARCHAR(50) NOT NULL COMMENT '年级名称',
  PRIMARY KEY (`gradeid`)
)ENGINE=INNODB DEFAULT CHARSET=utf8

-- 学生表的 gradeid 字段 要去引用年级表的gradeid
-- 定义外键KEY
-- 给这个外键添加约束(执行引用) references 引用
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`)
 )ENGINE=INNODB DEFAULT CHARSET=utf8

-- 创建表的时候没有外键关系
ALTER TABLE `student` ADD CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade`(`gradeid`);

-- ALTER TABLE`表`  ADD CONSTRAINT 约束名 FOREIGN KEY(作为外键的列) 引用到哪个表的哪个字段

Las operaciones anteriores son todas claves externas físicas y claves externas a nivel de base de datos, que no se recomiendan. (Evitar problemas causados ​​por demasiadas bases de datos)
Mejores prácticas

  • Una base de datos es una tabla simple, que solo se usa para almacenar datos, con solo filas (datos) y columnas (campos).
  • Queremos utilizar datos de varias tablas y utilizar claves externas (implementadas por programa)

3.2 lenguaje DML (recordar todo)

Significado de base de datos : almacenamiento de datos, gestión de datos
Lenguaje DML : lenguaje de manipulación de datos

  • insertar
  • actualizar
  • borrar

3.3 Insertar

insert

-- 插入语句(添加)
-- insert into 表名([字段一], [字段二])values('值1','值2')

INSERT INTO `grade` (`gradename`) VALUES('大四')

-- 一般写插入语句,我们一定要数据和字段一一对应。(不写字段默认全部字段)
-- 插入多行,针对一个字段,每行一个括号
INSERT INTO `grade`(`gradename`) VALUES ('大二'),('大一');
--gradeid无默认值 要插入这个数据
INSERT INTO `student`(`id`,`name`,`pwd`,`sex`,`gradeid`) VALUES (1,'张三','aaaaa','男',1)

Gramática:-- insert into 表名([字段一], [字段二])values('值1','值2')
Notas:

  1. Separar campos con comas
  2. Los campos se pueden omitir, pero los valores posteriores deben corresponder uno a uno.
  3. Se pueden insertar varios datos al mismo tiempo. Los valores después de VALORES deben usarse. Se pueden separar por valores ('valor 1'), ('valor 2')

3.4 Modificación

update

-- 修改学员名字
UPDATE `student` SET `name`='aaa' WHERE id =1;
-- 不指定条件的情况下,会改动所有表
UPDATE `student` SET `name`='bbb'
-- 语法;
-- UPDATE 表名 set column_name = value,[column_name = value,...] where [条件]

Condición: donde la identificación del operador de cláusula es igual a un valor determinado, es mayor que un valor determinado y se modifica dentro de un rango determinado.
El operador devuelve un valor booleano
imagen.png
. Nota:

  • nombre_columna es la columna de la base de datos, con ``
  • La condición es la condición de filtrado. Si no se especifica, se modificarán todas las columnas.
  • El valor es un valor específico o una variable.
  • Utilice comas para separar varios atributos establecidos.
UPDATE `student` SET `birthday`=CURRENT_TIME where `name`='bbb' AND SEX = '男'

3.5 Eliminar

delete
Sintaxis: eliminar del nombre de la tabla [donde condición]

-- 删除数据 (避免这样写)
DELETE FROM `student`
-- 删除指定
DELETE FROM `student` where id= 1

TRUNCATE
Función: Borrar completamente una base de datos, la estructura y el índice de la tabla no cambiarán.
Similitud: Ambos pueden eliminar datos, pero la estructura de la tabla no se eliminará
. Diferencia:

  • TRUNCATE restablece el contador de columna de incremento automático a cero
  • TRUNCATE no afecta las transacciones
-- 测试delete 和 truncate 区别
CREATE TABLE `test`(
   `id` INT(4) NOT NULL AUTO_INCREMENT,
   `coll` VARCHAR(20) NOT NULL,
   PRIMARY KEY (`id`)
 )

INSERT INTO `test`(`coll`) VALUES('1'),('2'),('3')

DELETE FROM `test` -- 删除后不会影响自增

TRUNCATE TABLE `test` -- 自增会归零

4. Datos de consulta DQL (lo más importante)

4.1DQL

( Lenguaje de consulta de datos ): lenguaje de consulta de datos.
Se utiliza para todas las operaciones de consulta. Select
Puede realizar consultas simples y consultas complejas. Es
el lenguaje central de la base de datos y el
lenguaje más utilizado
. Nota: [] Los paréntesis representan opcionales, { } Los corchetes representan las selecciones requeridas

create database if not exists `school`;
-- 创建一个school数据库
use `school`;-- 创建学生表
drop table if exists `student`;
create table `student`(
   `studentno` int(4) not null comment '学号',
   `loginpwd` varchar(20) default null,
   `studentname` varchar(20) default null comment '学生姓名',
   `sex` tinyint(1) default null comment '性别,0或1',
   `gradeid` int(11) default null comment '年级编号',
   `phone` varchar(50) not null comment '联系电话,允许为空',
   `address` varchar(255) not null comment '地址,允许为空',
   `borndate` datetime default null comment '出生时间',
   `email` varchar (50) not null comment '邮箱账号允许为空',
   `identitycard` varchar(18) default null comment '身份证号',
   primary key (`studentno`),
   unique key `identitycard`(`identitycard`),
   key `email` (`email`)
 )engine=myisam default charset=utf8;

-- 创建年级表
drop table if exists `grade`;
create table `grade`(
   `gradeid` int(11) not null auto_increment comment '年级编号',
   `gradename` varchar(50) not null comment '年级名称',
   primary key (`gradeid`)
 ) engine=innodb auto_increment = 6 default charset = utf8;

-- 创建科目表
drop table if exists `subject`;
create table `subject`(
   `subjectno`int(11) not null auto_increment comment '课程编号',
   `subjectname` varchar(50) default null comment '课程名称',
   `classhour` int(4) default null comment '学时',
   `gradeid` int(4) default null comment '年级编号',
   primary key (`subjectno`)
 )engine = innodb auto_increment = 19 default charset = utf8;

-- 创建成绩表
drop table if exists `result`;
create table `result`(
   `studentno` int(4) not null comment '学号',
   `subjectno` int(4) not null comment '课程编号',
   `examdate` datetime not null comment '考试日期',
   `studentresult` int (4) not null comment '考试成绩',
   key `subjectno` (`subjectno`)
 )engine = innodb default charset = utf8;

-- 插入学生数据 其余自行添加 这里只添加了2行
insert into `student` (`studentno`,`loginpwd`,`studentname`,`sex`,`gradeid`,`phone`,`address`,`borndate`,`email`,`identitycard`)
values(1000,'123456','张伟',0,2,'13800001234','北京朝阳','1980-1-1','[email protected]','123456198001011234'),
(1001,'123456','赵强',1,3,'13800002222','广东深圳','1990-1-1','[email protected]','123456199001011233');

-- 插入成绩数据  这里仅插入了一组,其余自行添加
insert into `result`(`studentno`,`subjectno`,`examdate`,`studentresult`)
values(1000,1,'2013-11-11 16:00:00',85),
(1000,2,'2013-11-12 16:00:00',70),
(1000,3,'2013-11-11 09:00:00',68),
(1000,4,'2013-11-13 16:00:00',98),
(1000,5,'2013-11-14 16:00:00',58);

-- 插入年级数据
insert into `grade` (`gradeid`,`gradename`) values(1,'大一'),(2,'大二'),(3,'大三'),(4,'大四'),(5,'预科班');
insert into `subject`(`subjectno`,`subjectname`,`classhour`,`gradeid`)values
(1,'高等数学-1',110,1),
(2,'高等数学-2',110,2),
(3,'高等数学-3',100,3),
(4,'高等数学-4',130,4),
(5,'C语言-1',110,1),
(6,'C语言-2',110,2),
(7,'C语言-3',100,3),
(8,'C语言-4',130,4),
(9,'Java程序设计-1',110,1),
(10,'Java程序设计-2',110,2),
(11,'Java程序设计-3',100,3),
(12,'Java程序设计-4',130,4),
(13,'数据库结构-1',110,1),
(14,'数据库结构-2',110,2),
(15,'数据库结构-3',100,3),
(16,'数据库结构-4',130,4),
(17,'C#基础',130,1);

4.2 Especificar campos de consulta

-- 查询所有学生
select * from student;

-- 查询指定字段
select `studentno`, `studentname` from student;

-- 给结果取名字 字段或表名
select `studentno` as '学号', `studentname` as '名字' from student as s;

-- 函数 Concat(a, b)
select concat('姓名:', studentname) as 新名字 from student;

imagen.png
imagen.png
Sintaxis: SELECT campo... FROM tabla
A veces, los nombres de las columnas no son tan obvios. Usamos alias AS, nombre de campo AS, alias nombre de tabla AS, alias
distinctpara eliminar duplicados
imagen.png
imagen.png

-- 查询所有学生
select * from student;

-- 查询指定字段
select `studentno`, `studentname` from student;

-- 给结果取名字 字段或表名
select `studentno` as '学号', `studentname` as '名字' from student as s;

-- 函数 Concat(a, b)
select concat('姓名:', studentname) as 新名字 from student;

-- 查询同学
select * from result;

select `studentno` from result;

-- 去重
select distinct `studentno` from result;

select version(); -- 版本

select 100*3 as 计算结果;

select @@auto_increment_increment;  --步长

-- 学院考试成绩 + 1
SELECT `studentno` , `studentresult` + 1 as '提分后' from result;

Expresiones en la base de datos: valores de texto, columnas, nulos, funciones, expresiones calculadas, variables del sistema...
seleccione expresión de la tabla

4.3 donde cláusula condicional

Función: recuperar valores calificados en los datos, el resultado es un
operador lógico booleano

operador gramática resultado
y && a y ba && b lógico Y
o || a o ba ||b lógico o
no ! no un !a negación lógica
-- 查询成绩在95~100之间
select studentno,studentresult from result 
where studentresult >= 95 && studentresult <= 100;

select studentno,studentresult from result 
where studentresult >= 95 and studentresult <= 100;

-- 模糊查询 (区间)
select studentno,studentresult from result 
where studentresult between 95 and 100;

select studentno,studentresult from result 
where studentno != 1000;

select studentno,studentresult from result 
where not studentno = 1000;

Consulta difusa: operadores de comparación

operador gramática describir
es nulo a es nulo a es nulo, el resultado es verdadero
No es nulo a no es nulo a no es nulo, el resultado es verdadero
entre a entre b y c a está entre b y c, el resultado es verdadero
como un me gusta b Coincidencia de SQL, si a coincide con b, el resultado es verdadero
en un en (a1, a2, a3…) Si a está entre (a1, a2, a3...), el resultado es verdadero.
-- like

-- 模糊查询 %(代表0到任意个字符) _一个字符 不能用等号 like
-- 姓张的
select studentno, studentname from student where studentname like '张%';

-- 张 名字只有一个字
select studentno, studentname from student 
where studentname like '张_';

-- 查询名字中有三的 %三%
select studentno, studentname from student 
where studentname like '%三%';

-- in
-- 查询 1001 1002 1003号学员
select studentno, studentname from student 
where studentno in (1001,1002,1003);

select studentno, studentname from student 
where address in ('%深圳%','北京');

select studentno, studentname from student 
where borndate is not null;

4.4 Consulta de tabla conjunta

unirse a la comparación
imagen.png
imagen.png

funcionar describir
unir internamente Si hay al menos una coincidencia en la tabla, devuelve la fila
unirse a la izquierda Devuelve todos los valores de la tabla de la izquierda incluso si no hay ninguna coincidencia en la tabla de la izquierda
unirse a la derecha Devuelve todos los valores de la tabla derecha incluso si no hay ninguna coincidencia en la tabla derecha
-- 联表查询

-- 查询参加了考试的同学(学号,姓名,科目编号,分数)
select * from student;
select * from  result;

/*
1. 分析需求,分析查询的字段来自哪些表
2.确定使用哪种连接查询?7种
确定交叉点(这两个表中哪个数据是相同的)
判断的条件: 学生表中 studentNo = 成绩表中 studentNo 
*/

-- join on(条件判断) 连接查询   on在取表之前判断
-- where 等值查询              where在取表之后才过滤

-- inner join

select s.studentno, studentname, subjectno, studentresult 
from student as s 
inner join result as r
on s.studentno = r.studentno

-- right join
select s.studentno, studentname, subjectno, studentresult 
from student s 
right join result r
on s.studentno = r.studentno

-- left join
select s.studentno, studentname, subjectno, studentresult 
from student s 
left join result r
on s.studentno = r.studentno

-- 查询缺考的同学
select s.studentno, studentname, subjectno, studentresult 
from student s 
left join result r
on s.studentno = r.studentno
where studentresult is null

-- 思考题(查询了参加考试的同学信息:学号 姓名 科目 分数)

/*
1. 分析需求,分析查询的字段来自哪些表 student result subject
2.确定使用哪种连接查询?7种
确定交叉点(这两个表中哪个数据是相同的)
判断的条件: 学生表中 studentNo = 成绩表中 studentNo 
*/

select s.studentno,studentname,subjectname,studentresult
from student s 
right join result r
on r.studentno = s.studentno
inner join `subject` sub on r.subjectno = sub.subjectno

-- 查询学员所属的年级(学号,姓名,年级)
select studentno,studentname,gradename
from student s
inner join grade g
on s.gradeid = g.gradeid

-- 查询参加c语言-2考试的同学信息 学号 姓名 科目名 分数
select s.studentno,studentname,subjectname,studentresult
from student s
inner join result r
on s.studentno = r.studentno
inner join subject sub
on r.subjectno = sub.subjectno
where sub.subjectname = 'C语言-2'

-- 我要查询哪些数据 select ....
-- 从哪几个表中查 from 表 xxx join 连接的表 on 交叉条件
-- 假设存在一中多张表查询,先查询两章表,然后再慢慢增加

-- from a left join b   左为准
-- from a right join b	右为准

autoconexión

CREATE TABLE `category`(
  `categoryid` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主题id',
  `pid` INT(10) NOT NULL COMMENT '父id',
  `categoryname` VARCHAR(50) NOT NULL COMMENT '主题名字',
  PRIMARY KEY (`categoryid`) 
) ENGINE=INNODB  AUTO_INCREMENT=9 DEFAULT CHARSET=utf8; 

INSERT INTO `category` (`categoryid`, `pid`, `categoryname`) 
VALUES ('2','1','信息技术'),
('3','1','软件开发'),
('5','1','美术设计'),
('4','3','数据库'),
('8','2','办公信息'),
('6','3','web开发'),
('7','5','ps技术');

imagen.png
Conecte su propia mesa con su propia mesa. El núcleo: dividir una mesa en dos mesas idénticas.
Clase para padres

categoria ID nombre de la categoría
2 tecnologías de la información
3 desarrollo de software
5 diseño artístico

Subclase

pid categoria ID nombre de la categoría
3 4 base de datos
2 8 Información de la oficina
3 6 desarrollo web
5 7 diseño artístico

Operación: consultar la relación entre la clase principal y la subclase

padre Subclase
tecnologías de la información Información de la oficina
desarrollo de software base de datos
desarrollo de software desarrollo web
diseño artístico tecnología ps
-- 查询父子信息 子类的pid等于父类的id
select a.categoryname as '父栏目',b.categoryname as '子栏目'
from category as a, category as b
where a.categoryid = b.pid

4.5 Paginación y clasificación

clasificar

--  排序 升序asc 降序 desc 
-- order by 通过哪个字段排序 顺序
select s.studentno,studentname,subjectname,studentresult
from student s
inner join result r
on s.studentno = r.studentno
inner join subject sub
on r.subjectno = sub.subjectno
where sub.subjectname = 'C语言-2'
order by studentresult asc

Paginación

-- 为什么要分页
-- 缓解数据库压力,给人的体验更好
-- 分页,每页显示五条数据

-- 语法: limit 起始页,页面的大小
-- limit 0,5 -- 1-5
-- limit 1,5 -- 2-6
-- limit 6,5
SELECT s.`StudentNo`,`StudentName`,`SubjectName`,`StudentResult`
FROM student s
INNER JOIN `result` r
ON s.`StudentNo`=r.`StudentNo`
INNER JOIN `subject` sub
ON r.`subjectNo`=sub.`subjectNo`
WHERE subjectName='数据结构-1'
ORDER BY StudentResult ASC
LIMIT 0,5

-- 第一页 limit 0,5
-- 第二页 limit 5,5
-- 第三页 limit 10,5
-- 第N页 limit pagesize*(n-1),pagesize
-- [pagesize*(n-1),pagesize]
-- pagesize 页面大小
-- n 当前页
-- 【数据总数/页面大小=总页数】

Límite de sintaxis (subíndice inicial de consulta, tamaño de página)

select s.studentno,studentname,subjectname,studentresult
from student s
inner join result r
on s.studentno = r.studentno
inner join subject sub
on r.subjectno = sub.subjectno
where subjectname = '高等数学-1' and studentresult >= 80
order by studentresult desc
limit 0,10

4.6 Subconsulta

Donde (este valor se calcula)
esencia: anida una declaración de subconsulta en la declaración donde

/*============== 子查询 ================
什么是子查询?
在查询语句中的WHERE条件子句中,又嵌套了另一个查询语句
嵌套查询可由多个子查询组成,求解的方式是由里及外;
子查询返回的结果一般都是集合,故而建议使用IN关键字;
*/

-- 查询 数据库结构-1 的所有考试结果(学号,科目编号,成绩),并且成绩降序排列
-- 方法一:使用连接查询
SELECT studentno,r.subjectno,StudentResult
FROM result r
INNER JOIN `subject` sub
ON r.`SubjectNo`=sub.`SubjectNo`
WHERE subjectname = '数据库结构-1'
ORDER BY studentresult DESC;

-- 方法二:使用子查询(执行顺序:由里及外)
SELECT studentno,subjectno,StudentResult
FROM result
WHERE subjectno=(
   SELECT subjectno FROM `subject`
   WHERE subjectname = '数据库结构-1'
 )
ORDER BY studentresult DESC;

-- 查询课程为 高等数学-2 且分数不小于80分的学生的学号和姓名
-- 方法一:使用连接查询
SELECT s.studentno,studentname
FROM student s
INNER JOIN result r
ON s.`StudentNo` = r.`StudentNo`
INNER JOIN `subject` sub
ON sub.`SubjectNo` = r.`SubjectNo`
WHERE subjectname = '高等数学-2' AND StudentResult>=80

-- 方法二:使用连接查询+子查询
-- 分数不小于80分的学生的学号和姓名
SELECT r.studentno,studentname 
FROM student s
INNER JOIN result r 
ON s.`StudentNo`=r.`StudentNo`
WHERE StudentResult>=80

-- 在上面SQL基础上,添加需求:课程为 高等数学-2
SELECT r.studentno,studentname 
FROM student s
INNER JOIN result r 
ON s.`StudentNo`=r.`StudentNo`
WHERE StudentResult>=80 AND subjectno=(
   SELECT subjectno FROM `subject`
   WHERE subjectname = '高等数学-2'
 )

-- 方法三:使用子查询
-- 分步写简单sql语句,然后将其嵌套起来
SELECT studentno,studentname FROM student WHERE studentno IN(
   SELECT studentno FROM result WHERE StudentResult>=80 AND subjectno=(
      SELECT subjectno FROM `subject` WHERE subjectname = '高等数学-2'
    )
 )

4.7 Agrupación y filtrado

-- 查询不同课程的平均分,最高分,最低分
-- 前提:根据不同的课程进行分组

SELECT subjectname,AVG(studentresult) AS 平均分,MAX(StudentResult) AS 最高分,MIN(StudentResult) AS 最低分
FROM result AS r
INNER JOIN `subject` AS s
ON r.subjectno = s.subjectno
GROUP BY r.subjectno
HAVING 平均分>80;

/*
where写在group by前面.
要是放在分组后面的筛选
要使用HAVING..
因为having是从前面筛选的字段再筛选,而where是从数据表中的>字段直接进行的筛选的
*/

4.8 seleccionar resumen

SELECCIONAR sintaxis

SELECT [ALL | DISTINCT]
{* | table.* | [table.field1[as alias1][,table.field2[as alias2]][,...]]}
FROM table_name [as table_alias]
[left | right | inner join table_name2]  -- 联合查询
[WHERE ...]  -- 指定结果需满足的条件
[GROUP BY ...]  -- 指定结果按照哪几个字段来分组
[HAVING]  -- 过滤分组的记录必须满足的次要条件
[ORDER BY ...]  -- 指定查询记录按一个或多个条件排序
[LIMIT {[offset,]row_count | row_countOFFSET offset}];
-- 指定查询的记录从哪条至哪条

5. Funciones MySQL

Sitio web oficial: https://dev.mysql.com/doc/refman/8.0/en/built-in-function-reference.html

5.1 Funciones de uso común

-- 数学运算

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('2323232') -- 返回字符串长度
SELECT CONCAT('我','233') -- 拼接字符串
SELECT INSERT('java',1,2,'cccc') -- 从某个位置开始替换某个长度 (str,pos,len,newstr) -->ccccva
SELECT INSTR('kuangshen','h') --返回首次出现的位置7
SELECT UPPER('abc') 
SELECT LOWER('ABC')
SELECT SUBSTR('123456',4,6) -- 返回从4开始的长度为6的字符串

SELECT REPLACE('坚持就能成功','坚持','努力')
-- 查询姓 周 的同学 ,改成邹
SELECT REPLACE(studentname,'周','邹') FROM student WHERE studentname LIKE '周%'

-- 时间跟日期函数(记住)
SELECT CURRENT_DATE() -- 获取当前日期
SELECT CURDATE() -- 获取当前日期
SELECT NOW() -- 获取当前日期
SELECT LOCATIME()  -- 本地时间
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()

5.2 Funciones de agregación (de uso común)

nombre de la función describir
CONTAR() contar
SUMA() Suma
AVG() valor promedio
MÁXIMO() valor máximo
MÍN() valor mínimo
-- 聚合函数
/*COUNT:非空的*/
SELECT COUNT(studentname) FROM student; -- 会忽略null
SELECT COUNT(*) FROM student;  -- 不会忽略null
SELECT COUNT(1) FROM student;  /*推荐*/ -- 会忽略null

-- 从含义上讲,count(1) 与 count(*) 都表示对全部数据行的查询。
-- count(字段) 会统计该字段在表中出现的次数,忽略字段为null 的情况。即不统计字段null 的记录。
-- count(*) 包括了所有的列,相当于行数,在统计结果的时候,包含字段为null 的记录;
-- count(1) 用1代表代码行,在统计结果的时候,包含字段为null 的记录 。
/*
很多人认为count(1)执行的效率会比count(*)高,原因是count(*)会存在全表扫描,
而count(1)可以针对一个字段进行查询。其实不然,count(1)和count(*)都会对全表进行扫描,
统计所有记录的条数,包括那些为null的记录,因此,它们的效率可以说是相差无几。而
count(字段)则与前两者不同,它会统计该字段不为null的记录条数。

下面它们之间的一些对比:

1)在表没有主键时,count(1)比count(*)快
2)有主键时,主键作为计算条件,count(主键)效率最高;
3)若表格只有一个字段,则count(*)效率较高。
*/

SELECT SUM(StudentResult) AS 总和 FROM result;
SELECT AVG(StudentResult) AS 平均分 FROM result;
SELECT MAX(StudentResult) AS 最高分 FROM result;
SELECT MIN(StudentResult) AS 最低分 FROM result;

5.3 数据库级别的MD5加密(扩展)

MD5简介
MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。
实现数据加密
新建一个表 testmd5

CREATE TABLE `testmd5` (
  `id` INT(4) NOT NULL,
  `name` VARCHAR(20) NOT NULL,
  `pwd` VARCHAR(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8

-- 插入一些数据
INSERT INTO testmd5 VALUES(1,'kuangshen','123456'),(2,'qinjiang','456789')

-- 如果我们要对pwd这一列数据进行加密,语法是:
update testmd5 set pwd = md5(pwd);

-- 如果单独对某个用户(如kuangshen)的密码加密:
INSERT INTO testmd5 VALUES(3,'kuangshen2','123456')
update testmd5 set pwd = md5(pwd) where name = 'kuangshen2';

-- 插入新的数据自动加密
INSERT INTO testmd5 VALUES(4,'kuangshen3',md5('123456'));

-- 查询登录用户信息(md5对比使用,查看用户输入加密后的密码进行比对)
SELECT * FROM testmd5 WHERE `name`='kuangshen' AND pwd=MD5('123456');

5.4 小结

-- ================ 内置函数 ================
-- 数值函数
abs(x)            -- 绝对值 abs(-10.9) = 10
format(x, d)    -- 格式化千分位数值 format(1234567.456, 2) = 1,234,567.46
ceil(x)            -- 向上取整 ceil(10.1) = 11
floor(x)        -- 向下取整 floor (10.1) = 10
round(x)        -- 四舍五入去整
mod(m, n)        -- m%n m mod n 求余 10%3=1
pi()            -- 获得圆周率
pow(m, n)        -- m^n
sqrt(x)            -- 算术平方根
rand()            -- 随机数
truncate(x, d)    -- 截取d位小数

-- 时间日期函数
now(), current_timestamp();     -- 当前日期时间
current_date();                    -- 当前日期
current_time();                    -- 当前时间
date('yyyy-mm-dd hh:ii:ss');    -- 获取日期部分
time('yyyy-mm-dd hh:ii:ss');    -- 获取时间部分
date_format('yyyy-mm-dd hh:ii:ss', '%d %y %a %d %m %b %j');    -- 格式化时间
unix_timestamp();                -- 获得unix时间戳
from_unixtime();                -- 从时间戳获得时间

-- 字符串函数
length(string)            -- string长度,字节
char_length(string)        -- string的字符个数
substring(str, position [,length])        -- 从str的position开始,取length个字符
replace(str ,search_str ,replace_str)    -- 在str中用replace_str替换search_str
instr(string ,substring)    -- 返回substring首次在string中出现的位置
concat(string [,...])    -- 连接字串
charset(str)            -- 返回字串字符集
lcase(string)            -- 转换成小写
left(string, length)    -- 从string2中的左边起取length个字符
load_file(file_name)    -- 从文件读取内容
locate(substring, string [,start_position])    -- 同instr,但可指定开始位置
lpad(string, length, pad)    -- 重复用pad加在string开头,直到字串长度为length
ltrim(string)            -- 去除前端空格
repeat(string, count)    -- 重复count次
rpad(string, length, pad)    --在str后用pad补充,直到长度为length
rtrim(string)            -- 去除后端空格
strcmp(string1 ,string2)    -- 逐字符比较两字串大小

-- 聚合函数
count()
sum();
max();
min();
avg();
group_concat()

-- 其他常用函数
md5();
default();

6. 事务

6.1 什么是事务

  • 事务就是将一组SQL语句放在同一批次内去执行
  • 如果一个SQL语句出错,则该批次内的所有SQL都将被取消执行
  • MySQL事务处理只支持InnoDB和BDB数据表类型

SQL执行, A给B转账 A 1000–> 200 B 200
SQL 执行, B收到A的钱 A 800 — B 400
将一组SQL放在一个批次中执行


事务原则 : ACID原则 原子性,一致性,隔离性,持久性 (脏读,幻读…)

原子性(Atomicity)
要么都成功,要么都失败,不能只发生一个
一致性(Consistency)
事务前后的数据完整性要保持一致(ab互相赚钱,钱不会到因为到银行而流失,AB的总价值一直不变)
持久性(Durability)
事务没有提交,恢复到原状(宕机),事务一旦提交就不可逆转,被持久化到数据库中
隔离性(Isolation)
事务产生多并发时,互不干扰

隔离产生的问题

脏读:
指一个事务读取了另外一个事务未提交的数据。
不可重复读:
在一个事务内读取表中的某一行数据,多次读取结果不同。(这个不一定是错误,只是某些场合不对)
虚读(幻读)
是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。
(一般是行影响,多了一行)

6.2 执行事务

-- mysql 默认自动开启事务提交
SET autocommit=0 -- 关闭
SET autocommit=1 -- 开启(默认的)

-- 手动处理事务
SET autocommit =0 -- 关闭自动提交

-- 事务开启
START TRANSACTION -- 标记一个事务的开始,从这个之后的SQP都在同一个事务内

-- sql
INSERT XX
INSERT XX

-- 提交 : 持久化(成功)
COMMIT 
-- 回滚:  回到原来的样子(失败)
ROLLBACK
-- 事务结束(提交,回滚)
SET autocommit = 1 -- 开启自动提交

-- 了解
SAVEPOINT 保存点名称 -- 设置一个事务的保存点
ROLLBACK TO SAVEPOINT 保存点名 -- 回滚到保存点
RELEASE SAVEPOINT 保存点 -- 删除保存点

imagen.png
测试

/*
课堂测试题目

A在线买一款价格为500元商品,网上银行转账.
A的银行卡余额为2000,然后给商家B支付500.
商家B一开始的银行卡余额为10000

创建数据库shop和创建表account并插入2条数据
*/

CREATE DATABASE `shop`CHARACTER SET utf8 COLLATE utf8_general_ci;
USE `shop`;

CREATE TABLE `account` (
   `id` INT(11) NOT NULL AUTO_INCREMENT,
   `name` VARCHAR(32) NOT NULL,
   `cash` DECIMAL(9,2) NOT NULL,
   PRIMARY KEY (`id`)
 ) ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT INTO account (`name`,`cash`)
VALUES('A',2000.00),('B',10000.00)

-- 转账实现
SET autocommit = 0; -- 关闭自动提交
START TRANSACTION;  -- 开始一个事务,标记事务的起始点
UPDATE account SET cash=cash-500 WHERE `name`='A';
UPDATE account SET cash=cash+500 WHERE `name`='B';
COMMIT; -- 提交事务,就被持久了,不能回滚了
rollback; --回滚
SET autocommit = 1; -- 恢复自动提交

7. 索引

MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度。
索引的作用

  • 提高查询速度
  • 确保数据的唯一性
  • 可以加速表和表之间的连接 , 实现表与表之间的参照完整性
  • 使用分组和排序子句进行数据检索时 , 可以显著减少分组和排序的时间
  • 全文检索字段进行搜索优化.

7.1 索引的分类

在一个表中,主键索引只能有一个,唯一索引可以有多个

  • 主键索引 (PRIMARY KEY)
    • 唯一的标识,主键不可重复,只能有一个列作为主键
  • 唯一索引 (UNIQUE KEY)
    • 避免重复的列出现,唯一索引可以重复,多个列都可以标识唯一索引
  • 常规索引(KEY/INDEX)
    • 默认的,index,key关键字来设置
  • 全文索引(FULLTEXT)
    • 在特点的数据库引擎下才有,MyISAM
    • 快速定位数据
#方法一:创建表时
CREATE TABLE 表名 (
字段名1 数据类型 [完整性约束条件…],
字段名2 数据类型 [完整性约束条件…],
[UNIQUE | FULLTEXT | SPATIAL ]   INDEX | KEY
[索引名] (字段名[(长度)] [ASC |DESC])
);


-- 方法二:CREATE在已存在的表上创建索引
CREATE [UNIQUE | FULLTEXT | SPATIAL ] INDEX 索引名
ON 表名 (字段名[(长度)] [ASC |DESC]) ;


#方法三:ALTER TABLE在已存在的表上创建索引
ALTER TABLE 表名 ADD [UNIQUE | FULLTEXT | SPATIAL ] INDEX
索引名 (字段名[(长度)] [ASC |DESC]) ;


#删除索引:DROP INDEX 索引名 ON 表名字;
#删除主键索引: ALTER TABLE 表名 DROP PRIMARY KEY;
#显示索引信息: SHOW INDEX FROM student;

/*增加全文索引*/
ALTER TABLE `school`.`student` ADD FULLTEXT INDEX `studentname` (`StudentName`);

/*EXPLAIN : 分析SQL语句执行性能*/
EXPLAIN SELECT * FROM student WHERE studentno='1000';

/*使用全文索引*/
-- 全文搜索通过 MATCH() 函数完成。
-- 搜索字符串作为 against() 的参数被给定。搜索以忽略字母大小写的方式执行。对于表中的每个记录行,MATCH() 返回一个相关性值。即,在搜索字符串与记录行在 MATCH() 列表中指定的列的文本之间的相似性尺度。
EXPLAIN SELECT * FROM student WHERE MATCH(studentname) AGAINST('love');

/*
开始之前,先说一下全文索引的版本、存储引擎、数据类型的支持情况

MySQL 5.6 以前的版本,只有 MyISAM 存储引擎支持全文索引;
MySQL 5.6 及以后的版本,MyISAM 和 InnoDB 存储引擎均支持全文索引;
只有字段的数据类型为 char、varchar、text 及其系列才可以建全文索引。
测试或使用全文索引时,要先看一下自己的 MySQL 版本、存储引擎和数据类型是否支持全文索引。
*/

7.3 测试索引

CREATE TABLE `app_user` (
  `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(50) DEFAULT '',
  `email` VARCHAR(50) NOT NULL,
  `phone` VARCHAR(20) DEFAULT '',
  `gender` TINYINT(4) UNSIGNED DEFAULT '0',
  `password` VARCHAR(100) NOT NULL DEFAULT '',
  `age` TINYINT(4) DEFAULT NULL,
  `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
  `update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8

-- 插入100万数据
DELIMITER $$ --  写函数之前必写
CREATE FUNCTION mock_data()
RETURNS INT 
BEGIN
  DECLARE num INT DEFAULT 1000000;
  DECLARE i INT DEFAULT 0;
  
  WHILE i<num DO
    -- 插入语句
    INSERT INTO app_user(`name`,`email`,`phone`,`gender`,`password`,`age`)
    VALUE(CONCAT('用户',i),'[email protected]',CONCAT('18',FLOOR(RAND()*9999999)),FLOOR(RAND()*2),
           UUID(),FLOOR(RAND()*100));
    SET i = i+1;
  END WHILE;
  RETURN i;
END;

SELECT mock_data(); -- 执行函数

SELECT * FROM app_user WHERE `name`='用户9999' -- 接近1秒
--分析一下上一条语句,发现查询了99999条数据
EXPLAIN SELECT * FROM app_user WHERE `name`='用户9999'  -- 查询99999条记录

-- 索引名 id_表名_字段名
-- create index 索引名 on 表名(字段)
CREATE INDEX id_app_user_name ON app_user(`name`); 
EXPLAIN SELECT * FROM app_user WHERE `name`='用户9999'  -- 0.001 s

索引在小数据的时候,用处不大,但是在大数据的时候,区别十分明显

7.3 索引原则

  • 索引不是越多越好
  • 不要对经常变动的数据加索引
  • 小数据量的表不需要加索引
  • 索引一般加在常用来查询的字段上

8. 权限管理和备份

8.1 用户管理

Navicat可视化管理
SQL命令操作
用户表:mysql.user
本质:对这张表进行,增删改查

-- 创建用户  CREATE USER 用户名 IDENTIFIED BY '密码'
CREATE USER sanjin IDENTIFIED BY '123456'

-- 修改密码(修改当前密码)
SET PASSWORD = PASSWORD('111111')


-- 修改密码(修改指定用户密码)

SET PASSWORD FOR sanjin = PASSWORD('111111')


-- 重命名  rename user 原名字 to 新名字
RENAME USER sanjin TO sanjin2

-- 用户授权   ALL PRIVILEGES 全部的权限   库,表
-- ALL PRIVILEGES 除了给别人授权,其他都能干
GRANT ALL PRIVILEGES ON *.* TO sanjin2

-- 查询权限
SHOW GRANTS FOR sanjin2  -- 查看指定用户的权限
SHOW GRANTS FOR root@localhost


-- 撤销权限 REVOKE 哪些权限,在哪个库撤销,给谁撤销
REVOKE ALL PRIVILEGES ON *.* FROM sanjin2

-- 删除用户
DROP USER sanjin2

8.2 MySQL备份

为什么备份:

  • 保证重要数据不丢失
  • 数据转移

MySQL数据库备份的方式

  • 直接拷贝物理文件
  • 数据库管理工具- 在想要导出的表或者库中,右键选择备份和导出
  • 直接拷贝数据库文件和相关配置文件

mysqldump客户端
作用 :

  • 转储数据库
  • 搜集数据库进行备份
  • 将数据转移到另一个SQL服务器,不一定是MySQL服务器
-- 导出
1. 导出一张表 -- mysqldump -uroot -p123456 school student >D:/a.sql
mysqldump -u用户名 -p密码 库名 表名 > 文件名(D:/a.sql)
2. 导出多张表 -- mysqldump -uroot -p123456 school student result >D:/a.sql
mysqldump -u用户名 -p密码 库名 表123 > 文件名(D:/a.sql)
3. 导出所有表 -- mysqldump -uroot -p123456 school >D:/a.sql
mysqldump -u用户名 -p密码 库名 > 文件名(D:/a.sql)
4. 导出一个库 -- mysqldump -uroot -p123456 -B school >D:/a.sql
mysqldump -u用户名 -p密码 -B 库名 > 文件名(D:/a.sql)

可以-w携带备份条件

-- 导入
1. 在登录mysql的情况下:-- source D:/a.sql
source 备份文件
2. 在不登录的情况下
mysql -u用户名 -p密码 库名 < 备份文件

9. 规范数据库设计

9.1 为什么需要数据库设计

当数据库比较复杂时我们需要设计数据库
糟糕的数据库设计 :

  • 数据冗余,存储空间浪费
  • 数据更新和插入的异常
  • 程序性能差

良好的数据库设计 :

  • 节省数据的存储空间
  • 能够保证数据的完整性
  • 方便进行数据库应用系统的开发

软件项目开发周期中数据库设计 :

  • 需求分析阶段: 分析客户的业务和数据处理需求
  • 概要设计阶段:设计数据库的E-R模型图 , 确认需求信息的正确和完整.

设计数据库步骤

  • 收集信息
  • 与该系统有关人员进行交流 , 座谈 , 充分了解用户需求 , 理解数据库需要完成的任务.
  • 标识实体[Entity]–>把需求落地到每个字段
  • 标识数据库要管理的关键对象或实体,实体一般是名词
  • 标识每个实体需要存储的详细信息[Attribute]
  • 标识实体之间的关系[Relationship]

9.2 三大范式

问题 : 为什么需要数据规范化?
不合规范的表设计会导致的问题:

  • 信息重复
  • 更新异常
  • 插入异常
    • 无法正确表示信息
  • 删除异常
    • 丢失有效信息

三大范式
第一范式 (1st NF)
第一范式的目标是确保每列的原子性,如果每列都是不可再分的最小数据单元,则满足第一范式
第二范式(2nd NF)
第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。
第二范式要求每个表只描述一件事情
第三范式(3rd NF)
如果一个关系满足第二范式,并且除了主键以外的其他列都不传递依赖于主键列,则满足第三范式.
第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关

规范化和性能的关系
阿里开发手册:关联查询不得超过三张表

  • ·考虑商业化的需求和目标,(成本,用户体验! )数据库的性能更加重要
  • 在规范性能的问题的时候,需要适当的考虑一下规范性!
  • 故意给某些表增加一些冗余的字段。(从多表查询中变为单表查询)
  • 故意增加一些计算列(从大数据量降低为小数据量的查询:索引)

10. JDBC(重点)

10.1 数据库驱动

驱动:声卡,显卡,数据库
imagen.png
我们的程序会通过数据库驱动,和数据库打交道!

10.2 JDBC

SUN 公司为了简化开发人员的(对数据库的统一)操作,提供了一个(Java操作数据库的)规范,JDBC
这些规范的实现由具体的厂商去做
对于开发人员来说,我们只需要掌握JDBC的接口操作即可
imagen.png
java.sql
javax.sql
除了这两个默认就有的,还需要导入数据库驱动包

10.3 第一个JDBC程序

创建测试数据库

CREATE DATABASE jdbcStudy CHARACTER SET utf8 COLLATE utf8_general_ci;

USE jdbcStudy;

CREATE TABLE `users`(
   id INT PRIMARY KEY,
   NAME VARCHAR(40),
   PASSWORD VARCHAR(40),
   email VARCHAR(60),
   birthday DATE
 );

INSERT INTO `users`(id,NAME,PASSWORD,email,birthday)
VALUES(1,'zhansan','123456','[email protected]','1980-12-04'),
(2,'lisi','123456','[email protected]','1981-12-04'),
(3,'wangwu','123456','[email protected]','1979-12-04')
  • 1.创建一个普通项目或maven项目
  • 2.导入数据库驱动
    • 普通项目
      file->Project Structure -> Libraries

imagen.png

imagen.png
pom.xml中配置

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
    </dependency>
  • 3 测试
package Deom01;

import java.sql.*;

public class MyFirstJdbc {
    
    
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
    
    
        // 1.加载驱动
        Class.forName("com.mysql.cj.jdbc.Driver"); //固定写法

        // 2.用户信息和URL
        // useUnicode=true&characterEncoding=utf8&useSSL=true"
        String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";
        String username = "root";
        String password = "root";

        // 3.连接成功,数据库对象   Connection代表数据库
        Connection connection = DriverManager.getConnection(url, username, password);

        // 4.执行SQL的对象 Statement执行sql的对象
        Statement statement = connection.createStatement();

        // 5.执行SQL的对象 --> 执行SQL语句,可能存在结果
        String sql = "SELECT * FROM `users`";
        ResultSet resultSet = statement.executeQuery(sql);

        while (resultSet.next()){
    
    
            System.out.println("id=" + resultSet.getObject("id"));
            System.out.println("id=" + resultSet.getObject("NAME"));
            System.out.println("id=" + resultSet.getObject("PASSWORD"));
            System.out.println("id=" + resultSet.getObject("email"));
            System.out.println("id=" + resultSet.getObject("birthday"));
        }

        // 6. 释放连接
        resultSet.close();;
        statement.close();
        connection.close();
    }
}

步骤总结:

  • 1.加载驱动
  • 2.连接数据库 DriverManager
  • 3.获取执行SQL的对象 Statement
  • 4.获得返回的结果集
  • 5.释放连接

DriverManager

//DriverManager.registerDriver(new com.mysql.jdbc.Driver()); //(推荐使用下面的方式)
Class.forName("com.mysql.jdbc.Driver");//固定写法,加载驱动
Connection connection= DriverManager.getConnection(url,name,password);

// connection代表数据库
connection.rollback();// 事务回滚
connection.commit();// 事务提交
connection.setAutoCommit();// 数据库设置自动提交

URL

String url ="jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&&useSSL=false";

// mysql 默认3306
// 协议://主机地址:端口号/数据库名?参数1&参数2&参数3

// Oracle   1521
// jdbc:oralce:thin:@localhost:1521:sid

Statement 执行SQL的对象 PrepareStatement 执行SQL的对象

Statement statement = connection.createStatement();
String sql="SELECT * FROM users";//编写Sql

statement.executeQuery(); //查询操作,返回ResultSet
statement.execute();      //执行任何sql,效率低
statement.executeUpdate();//更新,插入,删除,返回一个受影响的行数

ResultSet 查询的结果集,封装了所有的查询结果
获得指定的数据类型

ResultSet resultSet = statement.executeQuery(sql);//返回的结果集,结果集中封装了我们全部查询的结果
resultSet.getObject();//在不知道列类型下使用
resultSet.getString();//如果知道则指定使用
resultSet.getInt();  
...

遍历,指针

resultSet.next(); //移动到下一个
resultSet.afterLast();//移动到最后
resultSet.beforeFirst();//移动到最前面
resultSet.previous();//移动到前一行
resultSet.absolute(row);//移动到指定行

释放内存

//6. 释放连接  否则耗资源
resultSet.close();
statement.close();
connection.close();

10.4 statement对象

JDBC中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要
通过这个对象向数据库发送增删改查语句即可。
Statement对象的executeUpdate方法,用于向数据库发送增、删、改的sq|语句,
executeUpdate执行完后, 将会返回一个整数(即增删改语句导致了数据库几行数据发生了
变化)。
Statement.executeQuery方法用于向数据库发生查询语句,executeQuery方法返回代表查询
结果的ResultSet对象。
CRUD操作-create
使用executeUpdate(String sql)方法完成数据添加操作,示例操作:

Statement statement = connection.createStatement();
String sql = "insert into user(...) values(...)";
int num = statement.executeUpdate(sql);
if(num>0){
    
    
System.out.println("插入成功");

CRUD操作-delete
使用executeUpdate(String sql)方法完成数据删除操作,示例操作:

Statement statement = connection.createStatement();
String sql = "delete from user where id =1";
int num = statement.executeUpdate(sql);
if(num>0){
    
    
    System.out.println("删除成功");
}

CURD操作-update
使用executeUpdate(String sql)方法完成数据修改操作,示例操作:

Statement statement = connection.createStatement();
String sql = "update user set name ='' where name = ''";
int num = statement.executeUpdate(sql);
if(num>0){
    
    
    System.out.println("修改成功");
}

CURD操作-read
使用executeQuery(String sql)方法完成数据查询操作,示例操作:

Statement statement = connection.createStatement();
String sql = "select * from  user where id =1";
ResultSet rs= statement.executeQuery(sql);
if(rs.next()){
    
    
    System.out.println("");
}

代码实现
1.提取工具类

driver = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=TRUE
username = root
password = root

package Demo02.utils;

import java.io.IOException;
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 is = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
            Properties properties = new Properties();
            properties.load(is);
            driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");

            //1.驱动只需要加载一次
            Class.forName(driver);

        } catch (ClassNotFoundException ex) {
    
    
            throw new RuntimeException(ex);
        } catch (IOException e) {
    
    
            throw new RuntimeException(e);
        }
    }

    //获取连接
    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 e) {
    
    
                throw new RuntimeException(e);
            }
        }
        if (statement!=null){
    
    
            try {
    
    
                statement.close();
            } catch (SQLException e) {
    
    
                throw new RuntimeException(e);
            }
        }
        if (connection!=null){
    
    
            try {
    
    
                connection.close();
            } catch (SQLException e) {
    
    
                throw new RuntimeException(e);
            }
        }
    }
}

package Demo02.utils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestJdbcUtils {
    
    
    public static void main(String[] args) {
    
    
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;

        try {
    
    
            connection = JdbcUtils.getConnection();
            System.out.println(1);
            statement = connection.createStatement();

            // 插入
            String sql = "INSERT INTO users(`name`,`password`,`email`,`birthday`)"+
                    "VALUES('name','123456','email','2022-01-17')";
            if (statement.executeUpdate(sql)>0){
    
    
                System.out.println("插入成功");
            }

            // 查
            sql = "SELECT * FROM `users`";
            resultSet = statement.executeQuery(sql);
            while (resultSet.next()){
    
    
                System.out.println(resultSet.getInt("id"));
            }

        } catch (SQLException e) {
    
    
            throw new RuntimeException(e);
        }finally {
    
    
            JdbcUtils.release(connection,statement,resultSet);
        }
    }
}

SQL注入问题
SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针
对程序员编写时的疏忽,通过SQL语句,实现无账号登录,甚至篡改数据库。sql存在漏洞,
会被攻击导致数据泄露 .SQL会被拼接 or

package com.kuang.lesson02.utils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import static com.kuang.lesson02.utils.JdbcUtils.getConnection;

public class SQL注入 {
    
    
    public static void main(String[] args) {
    
    
        //SQL注入
        login("' or '1=1","123456");
    }
    public static void login(String name,String password){
    
    

        Connection conn =null;
        Statement st = null;
        ResultSet rs =null;

        try {
    
    
            conn = getConnection();//获取连接
            st = conn.createStatement();//获取SQL执行对象
            String sql = "select * from users where `NAME`='"+ name +"'  AND `PASSWORD`='"+ password +"'" ;
            rs=st.executeQuery(sql);//查询完毕返回结果集

            while (rs.next()){
    
    
                System.out.println(rs.getString("NAME"));
            }
            JdbcUtils.release(conn,st,rs);
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            try {
    
    
                JdbcUtils.release(conn,st,rs);
            } catch (SQLException throwables) {
    
    
                throwables.printStackTrace();
            }
        }
    }
}

10.5 PreparedStatement对象

PreparedStatement puede evitar la inyección de SQL y es más eficiente. (¿Escapar de caracteres especiales como comillas?)

  1. Nuevo
  2. borrar
  3. Preguntar
package lesson03;

import Demo02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class TestPrepareStatement {
    
    
    public static void main(String[] args) {
    
    
        Connection connection = null;
        PreparedStatement pstm = null;
        try {
    
    

            connection = JdbcUtils.getConnection();
            //区别
            //使用问号占位符代替参数
            String sql = "insert into users(id,`NAME`) values(?,?)";
            pstm = connection.prepareStatement(sql);//预编译sql,先写sql然后不执行
            //手动赋值
            pstm.setInt(1, 8);
            pstm.setString(2, "SANJIN");

            //执行
            int i = pstm.executeUpdate();
            if (i > 0) {
    
    
                System.out.println("插入成功");
            }
        } catch (SQLException e) {
    
    
            throw new RuntimeException(e);
        } finally {
    
    
            JdbcUtils.release(connection, pstm, null);
        }
    }
}

resumen:

  • declaración().executeQuery(sql) //Ejecución directa
  • prepareStatement(sql).executeQuert(sql) //Precompilar

10.6 IDEA se conecta a la base de datos

¿La premisa es que se importa el directorio lib?
imagen.png

10.7 Transacciones de operación JDBC

O todos tienen éxito o ambos fracasan
en el principio ACID

  • Atomicidad: o se completa todo o no se completa nada
  • Consistencia: el número total de resultados no cambia
  • Aislamiento: múltiples procesos no interfieren entre sí
  • Persistencia: una vez enviado, es irreversible y persiste en la base de datos.

Problemas de aislamiento:

  • Lectura sucia: una transacción lee otra transacción no confirmada
  • Lectura no repetible: dentro de la misma transacción, los datos de la tabla se leen repetidamente y la tabla cambia
  • Lectura virtual (lectura fantasma): en una transacción, los datos insertados por otros se leen, lo que da como resultado resultados de lectura inconsistentes.

Código

  1. Abrir transacción conn.setAutoCommit(false);
  2. Una vez completado un conjunto de ejecución comercial, se envía la transacción.
  3. La reversión se puede definir explícitamente en la declaración catch, pero se revertirá de forma predeterminada si falla.
package Demo04;

import Demo02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TestTransaction1 {
    
    
    public static void main(String[] args) {
    
    
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;

        try {
    
    
            conn = JdbcUtils.getConnection();
            //关闭数据库的自动提交,自动开启事务
            conn.setAutoCommit(false); //开启事务

            String sql1 = "update account set money = money-100 where name = 'A'";
            ps = conn.prepareStatement(sql1);
            ps.executeUpdate();

            int x = 1/0; //报错,回滚

            String sql2 = "update account set money = money+100 where name = 'B'";
            ps = conn.prepareStatement(sql2);
            ps.executeUpdate();

            // 业务完毕,开启事务
            conn.commit();

        } catch (SQLException e) {
    
    
            // 回滚语句,显示定义,不定义也行,系统默认调用
            try {
    
    
                conn.rollback();
            } catch (SQLException ex) {
    
    
                throw new RuntimeException(ex);
            }
            throw new RuntimeException(e);
        }finally {
    
    
            // 这里不能写开启自动提交,否则会提交报错之前的内容,导致回滚失败,
            // 回滚失败应该是 继续 从conn.setAutoCommit(false); 这个状态开始
            JdbcUtils.release(conn,ps,rs);
        }
    }
}

10.8 Grupo de conexiones de base de datos

Conexión de la base de datos: ejecución completa: liberación de conexión: la liberación es un desperdicio de
la tecnología de agrupación de recursos del sistema: prepare algunos recursos con anticipación y luego conéctese a los recursos preparados previamente.

Escriba un grupo de conexiones e implemente una interfaz, DataSource
no puedo entenderlo más tarde.

Supongo que te gusta

Origin blog.csdn.net/qq_53517370/article/details/128861112
Recomendado
Clasificación