关系型数据库是由多张能相互连接的二维表组成的数据库。
如果不由二维表组成,则称这个数据库为非关系型数据库。
SQL是一门结构化数据查询语言。具体的MySQL相当于“方言”。
SQL通用语法:
-- 这是注释
上边的注释一定要在–后面加上空格。这是语法规定,不然会报错。
/*这也是注释*/
此外,SQL语言要求一定要分号作为语句执行完毕的结尾。
SQL分类:
数值:
数据类型 | 含义 | 长度 |
---|---|---|
tinyint | 十分小的数据 | 1个字节 |
smallint | 小数据 | 2个字节 |
mediumint | 中等数据 | 3个字节 |
int | 标准数据 | 4个字节 |
bigint | 大数据 | 8个字节 |
float | 浮点数 | 4个字节 |
double | 浮点数 | 8个字节 |
decimal | 字符串形式的浮点数 | 金融计算的时候float和double无法满足精度要求,需要转化成字符串 |
字符串:
数据类型 | 含义 | 长度 |
---|---|---|
char | 固定大小的字符串 | 0-255 |
varchar | 可变大小的字符串 | 0-65535 常用来保存变量 |
tinytext | 微型文本串 | 2^8-1 |
text | 文本串 | 2^16-1 常用来保存大文本。写文章等等 |
时间日期:
Java有一个类java.utill.Date
数据类型 | 格式 | 含义 |
---|---|---|
year | YYYY | 年份格式 |
date | YYYY-MM-DD | 日期格式 |
time | HH:MM:SS | 时间格式 |
datetime | YYYY-MM-DD HH:MM:SS | 最常用的,把上边的日期和时间串起来了。 |
timestamp | 时间戳 | 1970.1.1到现在的毫秒数 非常重要 |
unsigned
zerofill
比如:设置字段的数据类型属性为int(3)或者在长度里填上3。那么:5->005
int
后面的括号表示一个宽度(上面例子是3
),使用了zerofill
后,当数据小于这个宽度时会自动填充0
。
auto_increment
自动在上一条记录的基础上+1
通常用来设计唯一的主键index
可以自己设计自增的起始值和步长
not null
如果设置字段属性为非空,那么记录里一定要填上一些数据,否则会报错。
default
字段设置默认值之后,如果不填入值,记录的值就会自动填入默认值。
SHOW DATABASES;
CREATE DATABASE 数据库名称;
-- 更好地创建数据库
CREATE DATABASE IF NOT EXISTS 数据库名称;
DROP DATABASE 数据库名称;
-- 更好地删除数据库
DROP DATABASE IF EXISTS 数据库名称;
-- 查看当前正在使用的数据库
SELECT DATABASE();
-- 使用数据库
USE 数据库名称;
上边是DDL定义数据库,接下来是DDL定义表
-- 查询当前数据库下所有表
SHOW TABLES;
-- 查询表的结构(注意只是查询表结构而已。不是表的数据)
DESC 表名称;
CREATE TABLE 表名(
字段名1 数据类型,
字段名2 数据类型,
字段名3 数据类型,
……
字段名n 数据类型
);
注意最后一行末尾不能加逗号。
添加字段
ALTER TABLE table_name ADD column_name data_type;
删除字段
ALTER TABLE table_name DROP COLUMN column_name;
修改字段名
ALTER TABLE table_name CHANGE old_column_name new_column_name data_type;
修改字段数据类型
ALTER TABLE table_name MODIFY COLUMN column_name new_data_type;
添加主键
ALTER TABLE table_name ADD PRIMARY KEY (column_name);
删除主键
ALTER TABLE table_name DROP PRIMARY KEY;
添加索引
ALTER TABLE table_name ADD INDEX index_name (column_name);
删除索引
ALTER TABLE table_name DROP INDEX index_name;
添加唯一约束
ALTER TABLE table_name ADD UNIQUE (column_name);
删除唯一约束
ALTER TABLE table_name DROP INDEX column_name;
DROP TABLE 表名;
-- 更好地删除表
DROP TABLE IF EXISTS 表名;
数据操作其实就是对表中的数据进行增删改。insert、update、delete。
-- 给指定的列添加数据(对应列就是对应的数据)
INSERT INTO 表名(字段1,字段2,……) VALUES(值1,值2,……);
-- 给所有的列添加数据
INSERT INTO 表名 VALUES(所有字段都必须要有对应的值!)
添加还是推荐使用第一种。因为可以直观看出哪个列对应哪个值。
update 表名 set 字段名 = 值 where 主键 = 什么
貌似无论是添加还是修改,都必须涉及到表名。
注意,如果update没有加where条件,那么会将一整列的数据全部修改。
DELETE FROM 表名 where 主键 = 什么
将一整条数据删除。如果不加where条件,会将表中所有数据删除。
-- 查询字段1和字段2
SELECT 字段1,字段2 FROM 表名;
-- 去重
SELECT DISTINCT 字段1,字段2 FROM 表名;
-- 别名
SELECT 字段1 AS 其他名字 FROM 表名;
可以用*来代替所有行,但是不推荐使用
就是where。然后加上大于小于等于等等条件。
比较特殊的:
between and 范围查询,不仅可以查询数值,也可以查询日期。
in() 就相当于括号里面的值两两之间都有一个or
is 查询null要用is
LIKE 模糊查询。通配符有两种:下划线_和百分号%。下划线单个任意字符,百分号多个任意字符
-- 查询名字字段第二个字是“化”的名字
SELECT name FROM stu where name LIKE "_化%";
-- 查询名字中包含“德”的名字
SELECT name FROM stu where name LIKE "%德%";
SELECT 字段 FROM 表名 ORDER BY 字段名 排序方式,字段名 排序方式,……
排序方式有两种,升序和降序。当有多个字段进行排序时,规则为:若第一个字段相等,则对相等的第一个字段所在的记录进行第二个字段的排序。排序方式中,升序使用ASC,降序使用DESC。
聚合函数:在select语句里前方使用,使用聚合函数对对应的列进行处理,之后再将列进行显示。主要函数有:count() sum() average() min() max()
所有的null都不参与聚合函数计算
SELECT 字段名 FROM 表名 GROUP BY 字段名 HAVING 条件(对分组之后的每一组执行此条件)
分组查询只能查两种字段:一种是进行分组的字段,另一种是其他字段但是必须经过聚合函数处理!!!
聚合函数紧跟着GROUP BY之后执行。注意是紧跟着。后面还有些优先级更低的比如having。
执行顺序:where>gruop by、聚合函数>having
所以where是在分组之前对数据进行过滤,having是在分组之后对分组结果进行过滤。
分页查询语法
select 字段列表 from 表名 limit 起始索引, 查询条数
起始索引从0开始。查询条数就是每一页显示多少条数据。但是“每一页”是需要在起始索引那里用数学表达式进行控制的。数学表达式为:起始索引=(第几页-1)*查询条数,“几”是从1开始的。
子句优先级顺序:where>分组(group by)聚合(count()、max()、min()等)过滤(having)>排序(order by)>分页(limit)
约束其实就是一些作用在列上的规则,用于限制加入表中的数据,约束的存在保证了数据的有效性,正确性和完整性。
约束写在创建表中的每一个字段的数据类型后面。
唯一约束和主键约束的区别就是主键约束要求非空。
当约束是唯一约束或者主键约束时,可以在这两个约束后面写上auto_increment,这个单词的意思是自动加1。
根据需求,可以给表中字段适当添加约束。
外键约束
两个表之间可能存在关系 比如一个学生表,一个年级表 每一个学生都有一个年级,故这两个表是可以连接起来的。
外键是关系型数据库中的一种特殊属性,它用于建立表与表之间的引用关系。在一个表中,外键是引用另一个表的主键的列。换句话说,外键是指向另一个表的主键的列,使得两个表之间建立关联关系。这种关联关系可以用于保持数据的一致性和完整性,避免数据冗余。外键的作用包括:
需要注意的是,外键的使用需要谨慎,不当的使用可能会对数据库性能产生负面影响。在设计和使用外键时,需要考虑数据库的表结构和查询需求,以及数据的一致性和完整性要求。
两个表有主从关系,创建外键需要在从表中创建。
语法:
在MySQL中创建外键通常涉及两个步骤:首先,创建主表和从表;然后,在从表中添加外键约束,该外键引用主表的主键。下面是一个简单的例子,
--- 创建主表
CREATE TABLE 主表 (
id INT PRIMARY KEY,
name VARCHAR(50)
);
--- 创建从表,并添加外键约束
CREATE TABLE 从表 (
id INT PRIMARY KEY,
主表_id INT,
description VARCHAR(100),
FOREIGN KEY (主表_id) REFERENCES 主表(id)
);
在这个例子中,主表 是主表,它有一个名为 id 的主键列。从表 是从表,它有一个名为 主表_id 的列,该列被定义为外键,并引用 主表 的 id 列。这样,在从表中插入或更新数据时,MySQL会检查 主表_id 列的值是否存在于 主表 的 id 列中,以确保数据的一致性和完整性。
创建外键时,需要确保以下几点:
1.主表和从表必须使用相同的存储引擎(例如InnoDB)。
2.主表的被引用列(在本例中为 主表.id)必须具有主键或唯一索引约束。
3.在创建外键约束之前,从表中的外键列(在本例中为 从表.主表_id)不能包含任何与主表中被引用列不匹配的值。
外键名字一般以fk(下划线)从表(下划线)主表来命名.
在创建主表和从表并在从表中指定外键时,必须先将主表先创建,之后才能创建从表, 必须先将主表的数据填入,之后才能填入从表的数据.
一旦外键约束建立,想要删除主表中外键指向的列中的数据, 就必须先将从表中的外键所在列的对应数据删干净才行.
多表查询分为连接查询和子查询。
连接查询分为内查询和外查询(左外查询和右外查询)。
select 表名.字段名,表名.字段名 from 表1 inner join 表2 on 条件
select 表名.字段名,表名.字段名 from 表1 left join 表2 on 条件
select 表名.字段名,表名.字段名 from 表1 right join 表2 on 条件
内查询和外查询的区别:
连接查询的条件用外键来进行连接是最方便的。
子查询其实就是嵌套查询。在where中再加一条查询,这条查询返回的结果经过判断继续给上一级的查询使用。
事务的主要作用是确保数据库的一致性和完整性。通过将一系列操作捆绑在一起,事务确保这些操作要么全部成功,要么全部失败。这样可以避免数据的不一致性,并保护数据库免受破坏。
举个例子来说明事务的作用:假设有一个银行ATM取钱的场景。当用户从其账户中取款时,涉及多个数据库操作,如扣款、更新账户余额等。如果这些操作不在一个事务中执行,可能会出现扣款成功但账户余额未更新的情况,导致数据不一致。
通过将取款操作放在一个事务中,可以确保这些操作要么全部成功,要么全部失败。如果其中一个操作失败,事务将回滚到之前的状态,即不会执行后续的操作。这样可以确保数据的完整性和一致性,避免出现数据不一致的情况。
因此,事务在数据库操作中起着重要的作用,它可以确保一系列操作要么全部成功,要么全部失败,从而保护数据库免受破坏并保持数据的一致性。
常见的面试题:事务的四大特征
ACID
- 原子性(Atomicity):事务是一个完整的操作。
- 一致性(Consistency):当事务完成时,数据必须处于一致状态。
- 隔离性(Isolation):对数据进行修改的所有并发事务是彼此隔离的。
- 持久性(Durability):事务完成后,它对于系统的影响是永久性的。
在MySQL中,事务是默认自动提交的。换而言之,会把每一句sql语句视为一个事务然后直接提交。
可以设置为手动提交(默认自动提交是1):
set @@aotocommit=0;
MySQL中如何进行事务回滚?
-- 开启一个事务
START TRANSACTION;
-- 执行一些SQL语句
INSERT INTO table_name (column1, column2) VALUES ('value1', 'value2');
UPDATE table_name SET column1 = 'new_value' WHERE condition;
-- 如果发生错误,回滚事务
BEGIN TRY
-- 执行一些SQL语句
INSERT INTO table_name (column1, column2) VALUES ('value3', 'value4');
UPDATE table_name SET column1 = 'new_value2' WHERE condition2;
COMMIT;
END TRY
BEGIN CATCH
ROLLBACK; -- 回滚事务
END CATCH;
在上述示例中,如果在执行BEGIN TRY
块中的SQL语句时发生错误,将进入BEGIN CATCH
块中执行回滚操作。这将撤销所有未提交的更改。
MySQL中的索引是一种特殊的数据结构,用于加速对数据库表中数据的检索操作。通过创建索引,MySQL可以在不需要扫描整个表的情况下快速找到与查询条件匹配的记录。
在MySQL中,主要有以下几种类型的索引:
此外,MySQL支持多种索引类型,如B-Tree索引、哈希索引、空间索引等。其中,B-Tree索引是MySQL中最常见的索引类型,适用于大部分场景。它支持全值匹配、范围查询和前缀匹配。哈希索引则是一种基于哈希表实现的索引,支持全值匹配,但不支持范围查询和前缀匹配。空间索引则是一种用于地理空间数据查询的特殊索引,基于R树实现。
总的来说,MySQL中的索引是提高查询效率的重要手段。正确地使用和创建索引可以显著提高数据库操作的性能。
但是,索引是需要消耗内存资源的。所以数据比较少的时候可以不使用索引,数据多的时候才使用。而且,数据量小的时候查询速度用索引和不用索引差不多
索引的使用
#显示所有的索引信息
show index from `student`
#给已经创建好的表添加一个索引
alter `student` add 索引类型 索引名 (要添加索引的字段名)
#为users表中username创建一个索引
CREATE INDEX idx_name ON users (username);
索引使用原则
索引的底层是b+树。这个是面试经常问到的内容,所以可以去深入了解一下。
虽然说是重点,但是写起来还是太麻烦了。后边有新的技术栈可以代替。mybatis
JDBC是指Java操作数据库的规范。这个规范由专业人员去设计。所以我只需要掌握JDBC接口的操作即可。
其实就是利用Java和数据库打交道。
首先,要想让程序和数据库之间产生联系,中间需要有一个数据库驱动来进行连接。所以去导一个包mysql-connector-java
就是在项目下边创建一个文件夹命名为lib。把包加进去,右键把lib添加到库里边就可以了。
JDBC程序:
package com.xu.jdbcdemo;
import java.sql.*;
public class JDBCDemo {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//加载驱动
Class.forName("com.mysql.jdbc.Driver");
//提供用户信息和主机地址,连接数据库。connection就是连接数据库的对象
String url="jdbc:mysql://localhost:3306/jdbcStudy?useUnicode=true&characterEncoding=utf8&useSSL=true";
String username="root";
String password="123456";
Connection connection=DriverManager.getConnection(url,username,password);
//执行数据库的对象
Statement statement=connection.createStatement();
//用执行数据库的对象来执行sql语句。打印一下
ResultSet resultSet=statement.executeQuery("SELECT * FROM users");
while(resultSet.next()){
System.out.println("id="+resultSet.getObject("id"));
System.out.println("name="+resultSet.getObject("name"));
System.out.println("password="+resultSet.getObject("password"));
System.out.println("email="+resultSet.getObject("email"));
System.out.println("birth="+resultSet.getObject("birthday"));
}
//关闭连接
resultSet.close();
statement.close();
connection.close();
}
}
步骤总结:
之后可以把这些步骤全部封装起来,传入sql语句就可以完成上边的全部步骤
connection对象中有一些方法是关于事务处理的。
statement中还有其他的方法,其中有一个是execute(),可以执行任何sql语句,不过效率会慢一些,因为要去判断属于哪一个语句。
resultSet是记录的结果集。这个对象中也有其他的方法。getObject()是在不知道字段类型的情况下使用的,如果知道了字段的类型,可以使用getInt,getDouble等等。然后next方法是移动到下一个记录。如果没有下一个记录就返回false