数据库的基本概念 | 英文:DataBase 简称 :DB 定义:用于存储和管理数据的仓库 特点: ·持久化存储数据(到硬盘中),速度快。其实数据库就是一个文件系统 ·方便存储和管理数据 ·使用了统一的方式操作数据库 -- SQL |
MySQL基本使用 | 【卸载】 ·控制面板 - 卸载 - 找到MySQL卸载 ·找到MySQL安装路径并删除剩余文件 ·找到MySQL数据路径C:\ProgramData\MySQL并删除剩余文件 ·删除注册表,[cmd] : regedit 打开注册表 MACHINE - SYSTEM - CONTROLSET001 - SERVICES - EVENLOG - APPLICATION - MYSQL 【(了解)启动、关闭服务】(cmd以管理员权限启动) ·[cmd] : services.msc 找到MySQL服务手动启动、关闭 ·[cmd] : net start mysql 启动服务 ·[cmd] : net stop mysql 关闭服务 【登录】 ·[cmd] : mysql -uroot -p密码 ·[cmd] : mysql -hip -uroot -p连接目标的密码 (h指host,ip是ip地址,本机ip为127.0.0.1) ·[cmd] : mysql --host=ip --user=root --password=连接目标的密码 【退出】 ·[cmd] : exit ·[cmd] : quit 【目录结构】 1. MySQL安装目录:basedir="E:/develop/MySQL/" * 在配置文件 my.ini 中可以查看到 2. MySQL数据目录:datadir="C:/ProgramData/MySQL/MySQL Server 5.5/Data/" * 数据库:文件夹 * 表:文件夹中的文件 * 数据:文件中的数据 |
SQL | SQL 全称:Structured Query Language:结构化查询语言 就是定义了操作所有[关系型]数据库的规则。每一种数据库操作的方式存在不一样的地方,称为“方言”。 【SQL 通用语法】 ·SQL 语句可以单行或多行书写,以分号 ; 结尾。 ·可使用空格和缩进来增强语句的可读性。 ·MySQL 数据库的 SQL 语句不区分大小写,关键字建议使用大写。 ·[3种注释方式] * 单行注释: -- 注释内容 (注意中间有空格,建议使用此方法) # 注释内容 (中间可以没有空壳,是mysql 特有) * 多行注释: /* 注释内容 */ 【SQL 四种分类】##【面试重点】 1) DDL (Data Definition Language) 数据定义语言 增删改查数据库,表,列(等数据库对象)。 关键字:create(增加), drop(删除),alter(修改),show(查询)等 2) DML (Data Manipulation Language) 数据操作语言 增删改数据库中的表的数据。 关键字:insert(增加), delete(删除), update(修改) 等 3) DQL (Data Query Language) 数据查询语言 查询数据库中的表的数据。 关键字:select(查询), where(条件查询) 等 4) DCL (Data Control Language) 数据控制语言(了解) 定义数据库的访问权限和安全级别,创建、删除用户。 关键字:GRANT(授权), REVOKE(撤销权限) 等 |
DDL操作数据库CRUD | 【C(Create):创建】 ·create database 数据库名称; -- 创建数据库 【重点掌握】 ·create database if not exists 数据库名称; -- 创建数据库,判断不存在,再创建(仅了解) ·create database 数据库名称 character set 字符集名; -- 创建数据库,并指定字符集(仅了解) ·[练习]:创建db4数据库,判断是否存在,并制定字符集为gbk。 create database if not exists db4 character set gbk; 【R(Retrieve):查询】 ·show databases; -- 查询所有数据库的名称: ·show create database 数据库名称; -- 查询某个数据库的字符集:查询某个数据库的创建语句 【U(Update):修改】 ·alter database 数据库名称 character set 字符集名称; -- 修改数据库的字符集 【D(Delete):删除】(危险,谨慎操作) ·drop database 数据库名称; -- 删除数据库 ·drop database if exists 数据库名称; -- 判断数据库存在,存在再删除 【使用数据库】 ·select database(); -- 查询当前正在使用的数据库名称 ·use 数据库名称; -- 使用数据库 |
数据库常用数据类型 | 数据类型: - int 整数类型 ·使用举例: age int, - double 小数类型 ·使用举例: score double(5,2) -- 总共有5位,其中小数占2位,整数占5-2=3位; ·注意:可以不指定()内的内容 - varchar:字符串类型 ·使用举例: name varchar(20) -- 姓名最大20个字符,如 zhangsan 是8个字符,张三 是2个字符 ·注意:必须指定()内的长度 ·与char的区别:varchar是可变字符串,更省空间,char是不可变字符串 - date:日期,只包含年月日 ·格式: yyyy-MM-dd - datetime:日期,包含年月日时分秒 ·格式: yyyy-MM-dd HH:mm:ss - timestamp:时间蹉类型 包含年月日时分秒 格式: yyyy-MM-dd HH:mm:ss ·与datetime的区别:如果将来不给这个字段赋值,或赋值为null,则默认使用当前的系统时间,来自动赋值 |
DDL操作表 | 【C(Create):创建】【重点】 ·[语法]: ·[使用举例 - 创建学生表] create table 表名( create table student( 字段名1 数据类型1 约束, id int, 字段名2 数据类型2 约束, name varchar(32) NOT NULL, ... ... age int , 字段名n 数据类型n 约束 score double(4,1), ); birthday date, - 注意:最后一列不需要加逗号 , insert_time timestamp ); ·[复制表]: create table 新建表名 like 被复制的表名; 【R(Retrieve):查询】 ·show tables; -- 查询某个数据库中所有的表名称 ·desc 表名; -- 查询表结构 【U(Update):修改】 ·alter table 表名 rename to 新的表名; -- 修改表名 ·alter table 表名 character set 字符集名称; -- 修改表的字符集 ·alter table 表名 add 列名 数据类型; -- 添加一列 ·alter table 表名 change 列名 新列名 新数据类型; -- 修改列名称、类型 ·alter table 表名 modify 列名 新数据类型; -- 修改列类型 ·alter table 表名 drop 列名; -- 删除列 【D(Delete):删除】 ·drop table 表名; -- 删除一个表 ·drop table if exists 表名 -- 判断一个表如果存在就删除 |
DML增删改表中数据 | 【添加数据】 ·[语法]: insert into 表名(列名1,列名2,...列名n) values(值1,值2,...值n); ·注意: - 列名和值的数量和类型必须一致,不赋值的字段给null值 - 如果表名后,不定义列名,则默认给所有列添加值 简化格式:insert into 表名 values(值1,值2,...值n); - 批量插入:insert into 表名 values(值1,值2,...值n),(值1,值2,...值n),(值1,值2,...值n)... - 除了数字类型,其他类型需要使用引号(单双都可以)引起来 【删除数据】 ·[语法]: delete from 表名 where 条件 ·注意: - 如果不加条件,则删除表中所有记录。 - 如果要删除所有记录 - delete from 表名; -- 不推荐使用。有多少条记录就会执行多少次删除操作 - TRUNCATE TABLE 表名; -- 推荐使用。先删除表,然后再创建一张一样的表。只执行删增两次操作,效率更高, 【修改数据】 ·[语法]: update 表名 set 列名1 = 值1, 列名2 = 值2,... where 条件; ·注意: - 如果不加任何条件,则会将表中所有记录全部修改。 |
DQL查询表中数据 | ·select * from 表名; -- 查询一张表所有的信息 ·[语法]: select 字段列表 from 表名列表 where 条件列表 group by 分组字段 having 分组之后的条件 order by 排序 limit 分页限定 |
DQL基础查询 | ·查询多字段 select 字段名1,字段名2... from 表名; 注意:如果查询所有字段,则可以使用*来替代字段列表。 字段名可以通过表名.出来 ·去除重复(一般只针对一个字段) select distinct 字段名 from 表名; ·计算列 一般针对数字列(int、double)使用四则运算计算值 ifnull(表达式1,表达式2):如果表达式1为null,就把表达式1替换为表达式2,。null参与的运算,计算结果都为null ·起别名: 字段名、表名 as 新名称 -- as可以省略,字段名+空格+新名称(新名称若为汉字,不需要用引号,直接使用) -- 同一张表在一个查询中可以起多个别名,用于自关联映射 |
DQL条件查询 | ·[语法]: where 条件 - 运算符 · > < <= >= = != <> · BETWEEN...AND -- 例: BETWEEN 20 AND 30 -- [20,30] 左右都包括,小的数必须放在前面 · IN(集合) -- 例: IN(18,20,22) -- 18 or 20 or 22,即存在宇这个集合中,可以简化多个or语句 · IS NULL / IS NOT NULL -- 判断是否为null,null值不能使用 = 和 != 来判断 · and / && [与] or / || [或] not / ! [非] · LIKE:模糊查询 -- 配合占位符使用,如查询所有带某个字的姓名 两种占位符: · 下划线 _ -- 表示单个任意字符 · 百分号 % -- 表示多个任意字符 |
——DQL条件查询练习 | · 查询年龄大于20岁 SELECT * FROM student WHERE age > 20; -- 查询年龄大于等于20岁 SELECT * FROM student WHERE age >= 20; -- 查询年龄等于20岁 SELECT * FROM student WHERE age = 20; -- 查询年龄不等于20岁 SELECT * FROM student WHERE age != 20; SELECT * FROM student WHERE age <> 20; -- 查询年龄大于等于20并且小于等于30 SELECT * FROM student WHERE age >= 20 && age <=30; SELECT * FROM student WHERE age >= 20 AND age <=30; SELECT * FROM student WHERE age BETWEEN 20 AND 30; -- 查询年龄22岁,18岁,25岁的信息 SELECT * FROM student WHERE age = 22 OR age = 18 OR age = 25 SELECT * FROM student WHERE age IN (22,18,25); -- 查询英语成绩为null SELECT * FROM student WHERE english = NULL; -- 这种写法错误!null值不能使用 = 和 != 来判断 SELECT * FROM student WHERE english IS NULL; -- 查询英语成绩不为null SELECT * FROM student WHERE english IS NOT NULL; -- 查询姓马的有哪些? like SELECT * FROM student WHERE NAME LIKE '马%'; -- 查询姓名第二个字是化的人 SELECT * FROM student WHERE NAME LIKE "_化%"; -- 查询姓名是3个字的人 SELECT * FROM student WHERE NAME LIKE '___'; -- 查询姓名中包含德的人 SELECT * FROM student WHERE NAME LIKE '%德%'; |
DQL排序查询 | ·[语法]: order by 排序字段1 排序方式1,排序字段2 排序方式2... ·排序方式: - ASC:升序,默认的。 - DESC:降序。 ·注意: 如果有多个排序条件,则当前边的条件值一样时,才会判断第二条件 |
DQL聚合函数 | ·[语法]: SELECT 函数名(字段名) FROM 表名; 聚合函数:将一列数据作为一个整体,进行纵向的计算 ·count:计算个数 一般选择非空的列:主键(如学号,编号等) count(*) *表示,一行数据中只要有一个不为null,那么这行就算一条数据,一般不使用此方法 ·max:计算最大值 ·min:计算最小值 ·sum:计算和 ·avg:计算平均值 ·注意:聚合函数的计算,要排除null值。 解决方案: - 选择不包含空的列进行计算 - 使用IFNULL函数 |
DQL分组查询 | ·[语法]: SELECT 分组字段,聚合函数1,聚合函数2... FROM 表名 WHERE 分组前的条件 GROUP BY 分组字段 HAVING 分组后的条件; ·注意: - 分组之后查询的字段:分组字段、聚合函数,聚合函数可以起别名使用 - where 和 having 的区别? 【面试重点】 - where 在分组之前进行限定,如果不满足条件,则不参与分组。having在分组之后进行限定,如果不满足结果,则不会被查询出来 - where 后不可以跟聚合函数,having可以进行聚合函数的判断。 ·练习: -- 按照性别分组。分别查询男、女同学的平均分 SELECT sex , AVG(math) FROM student GROUP BY sex; -- 按照性别分组。分别查询男、女同学的平均分,人数 SELECT sex , AVG(math),COUNT(id) FROM student GROUP BY sex; -- 按照性别分组。分别查询男、女同学的平均分,人数 要求:分数低于70分的人,不参与分组 SELECT sex , AVG(math),COUNT(id) FROM student WHERE math > 70 GROUP BY sex; -- 按照性别分组。分别查询男、女同学的平均分,人数 要求:分数低于70分的人,不参与分组,分组之后。人数要大于2个人 SELECT sex , AVG(math),COUNT(id) FROM student WHERE math > 70 GROUP BY sex HAVING COUNT(id) > 2; SELECT sex , AVG(math),COUNT(id) 人数 FROM student WHERE math > 70 GROUP BY sex HAVING 人数 > 2; |
DQL分页查询 | ·[语法]: limit 开始的索引,每页查询的条数; 注意:开始的索引可以省略,省略不写则默认为0 ·公式:开始的索引 = (当前的页码 - 1) * 每页显示的条数 举例:每页显示3条记录 SELECT * FROM student LIMIT 0,3; -- 第1页 SELECT * FROM student LIMIT 3,3; -- 第2页 SELECT * FROM student LIMIT 6,3; -- 第3页 ·limit 是一个MySQL"方言" |
DCL—管理用户(了解) | DCL:管理用户,授权,在公司中由DBA(数据库管理员)来管理; 本机主机名:localhost; ·添加用户: - 语法:CREATE USER '用户名账号'@'主机名/电脑IP地址' IDENTIFIED BY '密码'; ·删除用户: - 语法:DROP USER '用户名'@'主机名'; ·修改用户密码: - UPDATE USER SET PASSWORD = PASSWORD('新密码') WHERE USER = '用户名'; - 例: UPDATE USER SET PASSWORD = PASSWORD('abc') WHERE USER = 'lisi'; - SET PASSWORD FOR '用户名'@'主机名' = PASSWORD('新密码'); - 例: SET PASSWORD FOR 'root'@'localhost' = PASSWORD('123'); - mysql中忘记了root用户的密码? 1. cmd -- > net stop mysql 停止mysql服务 (* 需要管理员运行该cmd) 2. 使用无验证方式启动mysql服务: mysqld --skip-grant-tables 3. 打开新的cmd窗口,直接输入mysql命令,敲回车。就可以登录成功 4. use mysql; 5. update user set password = password('你的新密码') where user = 'root'; 6. 关闭两个窗口 7. 打开任务管理器,手动结束mysqld.exe 的进程 8. 启动mysql服务 9. 使用新密码登录。 ·查询用户: - 1. 切换到mysql数据库 USE myql; - 2. 查询user表 SELECT * FROM USER; |
DCL—权限管理(了解) | 通配符: % 表示可以在任意主机使用用户登录数据库 1. 查询权限: -- 查询权限 SHOW GRANTS FOR '用户名'@'主机名/IP地址'; SHOW GRANTS FOR 'lisi'@'%'; 2. 授予权限: -- 授予权限 grant 权限列表 on 数据库名.表名 to '用户名'@'主机名/IP地址'; -- 给张三用户授予所有权限,在任意数据库任意表上 GRANT ALL ON *.* TO 'zhangsan'@'localhost'; 3. 撤销权限: -- 撤销权限: revoke 权限列表 on 数据库名.表名 from '用户名'@'主机名/IP地址'; REVOKE UPDATE ON db3.`account` FROM 'lisi'@'%'; |
约束 | ·概念: 对表中的数据进行限定,保证数据的正确性、有效性和完整性。 ·分类: ·主键约束:primary key ·非空约束:not null ·唯一约束:unique ·外键约束:foreign key |
约束——非空约束 | ·非空约束:not null,某一列的值不能为null ·创建表时添加约束 CREATE TABLE stu( id INT, NAME VARCHAR(20) NOT NULL -- name为非空 ); ·创建表完后,添加非空约束 ALTER TABLE stu MODIFY NAME VARCHAR(20) NOT NULL; ·删除name的非空约束 ALTER TABLE stu MODIFY NAME VARCHAR(20); |
约束——唯一约束 | ·唯一约束:unique,某一列的值不能重复,对null值不会唯一约束,即可以有多个null值,又叫索引唯一约束 ·注意: 唯一约束可以有NULL值,但是只能有一条记录为null ·在创建表时,添加唯一约束 CREATE TABLE stu( id INT, phone_number VARCHAR(20) UNIQUE -- 手机号唯一 ); ·在表创建完后,添加唯一约束 ALTER TABLE stu MODIFY phone_number VARCHAR(20) UNIQUE; ·删除唯一约束 ALTER TABLE stu DROP INDEX phone_number; |
约束——主键约束 | ·主键约束:primary key。 ·注意: - 含义:非空且唯一 - 一张表只能有一个主键 - 主键可以一个或多个字段(联合主键) - 主键可以用整数类型:一般和auto_increment结合,缺点:有可能超过整数范围(21亿+) - 主键可以用字符串类型:随机生成一个永远不会重复的字符串 ·在创建表时,添加主键约束 create table stu( id int primary key, -- 给id添加主键约束 name varchar(20) ); ·创建完表后,添加主键 ALTER TABLE stu MODIFY id INT PRIMARY KEY; ·删除主键 ALTER TABLE stu DROP PRIMARY KEY; ·自动增长: - 概念:如果某一列是数值类型的,使用 auto_increment 可以来完成值得自动增长 - 在创建表时,添加主键约束,并且完成主键自增长 create table stu( id int primary key auto_increment,-- 给id添加主键约束 name varchar(20) ); - 添加自动增长 ALTER TABLE stu MODIFY id INT AUTO_INCREMENT; - 删除自动增长 ALTER TABLE stu MODIFY id INT; |
约束——外键约束 | ·外键约束:foreign key,让表于表产生关系,从而保证数据的正确性。 ·在创建表时,可以添加外键 语法: create table 表名( .... 外键列 constraint 外键名称 foreign key (外键列名称) references 主表名称(主表列名称) ); ·创建表之后,添加外键 ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键列名称) REFERENCES 主表名称(主表列名称); ·删除外键 ALTER TABLE 表名 DROP FOREIGN KEY 外键名称; ·constraint 外键名称 这个添加外键名称的操作可以省略,此时系统会自动生成一个随机的名字,如果需要做删除等操作使用到名字 可以查看:show ·级联操作(了解即可) - 添加/删除级联操作 - 语法:ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称) ON UPDATE CASCADE / ON DELETE CASCADE; - 分类: - 级联更新:ON UPDATE CASCADE - 级联删除:ON DELETE CASCADE |
数据库设计 | |
多表之间的关系 | ·分类: · 一对一(了解即可,开发中很少遇到,万一有需求,一般就合成一张表): 如:人和身份证 分析:一个人只有一个身份证,一个身份证只能对应一个人 实现方式:一对一关系实现,可以在任意一方添加唯一外键指向另一方的主键。 · 一对多(多对一): 如:部门和员工 分析:一个部门有多个员工,一个员工只能对应一个部门 实现方式:在“多”的一方建立外键,指向“一”的一方的主键。 · 多对多: 如:学生和课程 分析:一个学生可以选择很多门课程,一个课程也可以被很多学生选择 实现方式:多对多关系实现需要借助第三张中间表。中间表至少包含两个字段,这两个字段作为第三张表的外键,分别指向两张表的主键,这两个主键组合起来作为中间表的联合主键 |
范式(重复内容拆分) | ·概念:设计数据库时,需要遵循的一些规范。要遵循后边的范式要求,必须先遵循前边的所有范式要求 设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。 目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。 ·分类: 1. 第一范式(1NF):每一列都是不可分割的原子数据项(列表头不能合并拆分,一列数据只有一个表头) 第一范式存在的问题: 1.存在非常严重的数据冗余(重复):如姓名、系名、系主任 2.数据添加存在问题:如添加新开设的系和系主任时,没有学生学号等信息,数据不合法 3.数据删除存在问题:如张无忌同学毕业了,删除数据,会将系的数据一起删除。 2. 第二范式(2NF):在1NF的基础上,非码属性必须完全依赖于码(在1NF基础上消除非主属性对主码的部分函数依赖) ·相关概念: 1. 函数依赖:A-->B,如果通过A属性(属性组)的值,可以确定唯一B属性的值。则称B依赖于A 例如: 学号 --> 姓名。 2. 完全函数依赖:A-->B, 如果A是一个属性组,则B属性值得确定需要依赖于A属性组中所有的属性值。 例如:(学号,课程名称) --> 分数 3. 部分函数依赖:A-->B, 如果A是一个属性组,则B属性值得确定只需要依赖于A属性组中某一些值即可。 例如:(学号,课程名称) --> 姓名 4. 传递函数依赖:A-->B, B -- >C . 如果通过A属性(属性组)的值,可以确定唯一B属性的值,在通过B属性(属性组)的值可以确定唯一C属性的值,则称 C 传递函数依赖于A 例如: 学号-->系名,系名-->系主任 5. 码:如果在一张表中,一个属性或属性组,被其他所有属性所完全依赖,则称这个属性(属性组)为该表的码 例如:该表中码为:(学号,课程名称) - 主属性:码属性组中的所有属性 - 非主属性:码属性组之外的属性 第二范式存在的问题: 2.数据添加存在问题:如添加新开设的系和系主任时,没有学生学号等信息,数据不合法 3.数据删除存在问题:如张无忌同学毕业了,删除数据,会将系的数据一起删除。 3. 第三范式(3NF):在2NF基础上,任何非主属性不依赖于其它非主属性(在2NF基础上消除传递依赖) |
数据库的备份和还原 | ·cmd命令行: ·[语法]: - 备份: mysqldump -u用户名 -p密码 数据库名称 > 保存的路径 - 还原: 1. 登录数据库 mysqldump -u用户名 -p密码 2. 创建数据库 3. 使用数据库 4. 执行文件。source 文件路径 ·图形化工具: 右键 - 备份/导出 - 备份数据库 - 选择路径并导出 右键 - 执行SQL脚本 - 选择备份文件导入 |
多表查询 | 概述: select * from 表1,表2; 会出现表1、2组合的所有结果(笛卡尔积) 多表查询需要消除其中的无用数据 |
多表查询—内连接查询 | ·内连接查询: ·隐式内连接:配合where(将来用这个) - 使用举例:select * from 表A,表B where 表A.主键名 = 表B.主键名 ·显式内连接:(了解,将来不用这个) - 语法: select 字段列表 from 表名1 [inner] join 表名2 on 条件 -- inner []表示可省略 ·内连接查询的思路: - 从哪些表中查询数据 - 条件是什么 - 查询哪些字段 |
多表查询—外连接查询 | ·外链接查询: ·左外连接:(将来用这个) - 语法:select 字段列表 from 表1 left [outer] join 表2 on 条件; - 查询的是左表所有数据以及其交集部分。 - 注意:left join 左右两侧各只能有一张表 - 例子: - 查询所有员工信息,如果员工有部门,则查询部门名称,没有部门,则不显示部门名称 SELECT t1.*,t2.`name` FROM emp t1 LEFT JOIN dept t2 ON t1.`dept_id` = t2.`id`; ·右外连接:(了解,将来不用这个) - 语法:select 字段列表 from 表1 right [outer] join 表2 on 条件; - 查询的是右表所有数据以及其交集部分。 - 例子: SELECT * FROM dept t2 RIGHT JOIN emp t1 ON t1.`dept_id` = t2.`id`; |
多表查询—子查询 | ·子查询的结果是单行单列的: - 子查询可以作为条件,使用运算符去判断。 运算符: > >= < <= = != <> - 例子: 查询员工工资小于平均工资的人 SELECT * FROM emp WHERE emp.salary < (SELECT AVG(salary) FROM emp); ·子查询的结果是多行单列的: - 查询可以作为条件,使用运算符in来判断 - 例子: 查询'财务部'和'市场部'所有的员工信息 SELECT * FROM emp WHERE dept_id IN (SELECT id FROM dept WHERE NAME = '财务部' OR NAME = '市场部'); -- 建议使用普通内连接 SELECT * FROM emp,dept WHERE emp.`dept_id` = dept.`id` and dept.`name` = '财务部' OR NAME = '市场部'; ·子查询的结果是多行多列的: * 子查询可以作为一张虚拟表参与查询 -例子: 查询员工入职日期是2011-11-11日之后的员工信息和部门信息 -- 子查询 SELECT * FROM dept t1 ,(SELECT * FROM emp WHERE emp.`join_date` > '2011-11-11') t2 WHERE t1.id = t2.dept_id; -- 建议使用普通内连接 SELECT * FROM emp t1,dept t2 WHERE t1.`dept_id` = t2.`id` AND t1.`join_date` > '2011-11-11' |
事务 | 基本介绍: ·概念: 如果一个包含多个步骤的业务操作,被事务管理,那么这些操作要么同时成功,要么同时失败。 ·操作(手动提交): - 开启事务: start transaction; -- 保证一些操作成功 - 回滚: rollback; -- 在java中,如果发生异常,在catch语句中来回滚 - 提交: commit; -- 没有发生问题时,再提交 ·MySQL默认自动提交: 一条DML(数据增删改)语句会自动提交一次事务 (Oracle 数据库默认是手动提交事务) ·查看事务的默认提交方式:SELECT @@autocommit; -- 结果为 1 代表自动提交 0 代表手动提交 ·(了解)修改默认提交方式: set @@autocommit = 0; -- 把默认自动提交修改为默认手动提交 |
事务的四大特征(面试) | 1. 原子性:是不可分割的最小操作单位,要么同时成功,要么同时失败。 2. 持久性:当事务提交或回滚后,数据库会持久化的保存数据。 3. 隔离性:多个事务之间。相互独立。 4. 一致性:事务操作前后,数据总量不变 |
事务的隔离级别(了解) | ·概念:多个事务之间隔离的,相互独立的。但是如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别就可以解决这些问题。 ·存在问题: - 脏读:一个事务,读取到另一个事务中没有提交的数据 - 不可重复读(虚读):在同一个事务中,两次读取到的数据不一样。 - 幻读:一个事务操作(DML)数据表中所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改。 ·隔离级别: - read uncommitted:读未提交 - 产生的问题:脏读、不可重复读、幻读,脏读问题很大不建议使用 - read committed:读已提交 (Oracle默认) - 产生的问题:不可重复读、幻读,可以使用此方法 - repeatable read:可重复读 (MySQL默认) - 产生的问题:幻读,可以使用此方法 - serializable:串行化 - 可以解决所有的问题,但是效率低下,不建议使用 - 注意:隔离级别从小到大安全性越来越高,但是效率越来越低 - 数据库查询隔离级别: select @@tx_isolation; - 数据库设置隔离级别: set global transaction isolation level 级别字符串; * 演示: set global transaction isolation level read uncommitted; start transaction; -- 转账操作 update account set balance = balance - 500 where id = 1; update account set balance = balance + 500 where id = 2; |
JDBC概念 | Java DataBase Connectivity Java数据库连接 / Java语言操作数据库 JDBC本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。 JDBC作用:平复数据库数据的差异 |
快速入门 | //1.导入驱动jar包 复制mysql-connector-java-5.1.37-bin.jar到项目的libs目录下 libs右键-->Add As Library //2.注册驱动 //告诉程序该使用哪一个数据库驱动jar Class.forName("com.mysql.jdbc.Driver"); //3.通过 【 DriverManager 驱动管理对象 】 获取 【 Connection 数据库连接对象 】 //搭桥,获取数据库连接 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3", "root", "root"); //4.获取 【 Statement 执行sql的对象 】 Statement stmt = conn.createStatement(); //5.执行sql int count = stmt.executeUpdate(sql语句); //6.处理结果 System.out.println(count); //7.释放资源 stmt.close(); conn.close(); |
DriverManager | 驱动管理对象 【功能】 1. 注册驱动 2. 获取数据库连接 1. 注册驱动:告诉程序该使用哪一个数据库驱动jar 方法:static void registerDriver(Driver driver) :注册与给定的驱动程序 DriverManager 。 【掌握】代码实现: Class.forName("com.mysql.jdbc.Driver"); 通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块 static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } } 注意:mysql5之后的驱动jar包可以省略注册驱动的步骤,但是依然建议手写注册,方便兼容低版本的MySQL。 2. 获取数据库连接: 【掌握】方法:static Connection getConnection(String url, String user, String password) 参数:url:指定连接的路径 user:用户名 password:密码 url语法: jdbc:mysql://ip地址(域名):端口号/数据库名称 url例子: jdbc:mysql://localhost:3306/db3 url细节: 如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称 |
Connection | 数据库连接对象 【功能】 1. 获取执行 sql 的对象 2. 管理事务 1. 获取执行 sql 的对象 方法: - Statement createStatement() 【掌握】 - PreparedStatement prepareStatement(String sql) 2. 管理事务 方法: - 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,把自动提交关闭(只针对这一次),即开启事务 - 回滚事务:rollback() - 提交事务:commit() |
Statement(了解) | 执行sql的对象 【功能】:执行sql ·SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题,所以以后不使用这个,而使用PreparedStatement - 输入用户随便,输入密码:a' or 'a' = 'a - sql:select * from user where username = 'fhdsjkf' and password = 'a' or 'a' = 'a' 方法: · 【掌握】 int executeUpdate(String sql) :执行DML(insert、update、delete)语句、DDL(create,alter、drop)语句(DDL不常用,了解) - 返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功 返回值>0的则执行成功,反之,则失败。 · 【掌握】 ResultSet executeQuery(String sql) :执行DQL(select)语句 - 返回值:ResultSet 这个对象封装了所有结果 (详情见表格下一行) · boolean execute(String sql) :可以执行任意的sql,返回true表示执行的是DQL查询,返回false表示执行的是DML增删改 (了解) 由于返回的是布尔值,对于我们查询需要得到的结果没有意义,所以不使用 |
ResultSet | 结果集对象 【功能】:封装查询结果 ·【掌握】方法: ·boolean next(): 游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回false,如果不是则返回true ·getXxx(参数):获取数据 - Xxx:代表数据类型 如: int getInt() , String getString() - 参数: 1. int:代表列的编号,从1开始 如: getString(1),获取第1列 id列的值 (建议)2. String:代表列名称。 如: getDouble("balance") 获取列名是balance的列的值 ·使用步骤: 1. 游标向下移动一行 2. 判断是否有数据 3. 获取数据 //循环判断游标是否是最后一行末尾,若不是,获取并打印所有信息。 【掌握】 while(rs.next()){ int id = rs.getInt("id"); String name = rs.getString("name"); double balance = rs.getDouble("balance"); System.out.println(id + "," + name + "," + balance); } |
PreparedStatement | 执行sql的对象 【功能】:执行sql 【方法】 ·执行DML int excuteUpdate();//这里不能传入sql语句了 ·执行DQL ResultSet excuteQuery();//这里不能传入sql语句了 ·SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题 - 输入用户随便,输入密码:a' or 'a' = 'a - sql:select * from user where username = 'fhdsjkf' and password = 'a' or 'a' = 'a' ·解决sql注入问题:使用PreparedStatement对象来解决 ·预编译的SQL:参数使用?作为占位符 ·步骤: 1. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar 2. 注册驱动 3. 获取数据库连接对象 Connection 4. 定义sql 注意:sql的参数使用?作为占位符。 如:select * from user where username = ? and password = ?; 5. 获取执行sql语句的对象 PreparedStatement 通过方法:connection.prepareStatement(String sql) 6. 给?赋值: 方法: setXxx(参数1,参数2) 如:preparedStatement.setString(1,username); 参数1:?的位置编号 从1 开始 preparedStatement.setString(2,password); 参数2:?的值 7. 执行sql,接受返回结果,无参数不能传递sql语句 如:rs = preparedStatement.executeQuery(); 8. 处理结果,如:return rs.next(); 9. 释放资源 ·注意:后期都会使用PreparedStatement来完成增删改查的所有操作 - 可以防止SQL注入 - 效率更高 |
JDBCUtils | 抽取JDBC工具类 目的:简化书写 --注册驱动,获取连接 --释放资源 import java.io.FileReader; import java.io.IOException; import java.sql.*; import java.util.Properties; public class JDBCUtils { private static String url; private static String user; private static String password; private static String driverClass; static{ try { ClassLoader classLoader = JDBCUtils.class.getClassLoader(); String path = classLoader.getResource("mysql.properties").getPath(); Properties prop = new Properties(); prop.load(new FileReader(path)); url = prop.getProperty("url"); user = prop.getProperty("user"); password = prop.getProperty("password"); driverClass = prop.getProperty("driverClass"); Class.forName(driverClass); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } //获取连接 public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url,user,password); } //释放资源 public static void close(){} public static void close(Statement stmt, Connection conn){ close(null,stmt,conn); } public static void close(ResultSet rs, Statement stmt, Connection conn){ if (rs!=null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stmt!=null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } |
JDBC控制事务 | ·事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。 ·使用Connection对象来管理事务 - 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务 * 在执行sql之前开启事务 conn.setAutoCommit(false); - 提交事务:commit() * 当所有sql都执行完提交事务 conn.commit(); - 回滚事务:rollback() * 在catch中回滚事务 try { if(conn != null) { conn.rollback(); } } catch (SQLException e1) { e1.printStackTrace(); } |
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) | 黑马程序员IT技术论坛 X3.2 |