·数据库的概念
DB:数据库
DBMS:数据库管理系统MYSQL,Oracle,DB2,sqlserver
SQL:结构化语句查询
1.SQL语句的分类:
数据查询语句(DQL)—slect
数据操纵(DML)—insert,truncate(delete),update
数据定义语言(DDL)–create,drop,alter
事务语句(DCL)–grant,revoke
·MYSQL安装5.7.26-----结合PDF—文章末尾
1.入门指令:
2.常见函数
a.字符函数:--------大小写控制函数
LOWER('SQL HAha')====>(sql haha)
UPPER('sql HHHH')=====>(SQL HHHH)
--------字符控制函数
CONCAT('hello','world')===>helloworld
SUBSTR('HelloWorld',1,5)>Hello
LENGTH('HelloWorld')====>10
INSTR('HelloWorld','W')===>6
LPAD(salary,10,'*')=======>****salary
RPAD(salary,10,'*')=======>salary****
TRIM('H' from 'HelloWorld')=>elloWorld
REPLACE('abcd','b','m')====>amcd
b.数字函数
- ROUND:四舍五入
ROUND(45.926,2)------>45.93
- TRUNCATE:截断
TRUNC(45.926,2)------->45.92
- MOD:求余
MOD(1600,300)---------->300
- now():获取当前日期
c.条件表达式
IF-THEN-ELSE
case:查询部门号为10,20,30的员工信息,若部门号为10,则打印工资为其1.1倍数,20号部门,则打印工资为1.2倍,30号部门则打印工资为1.3倍
select last_name,job_id,salary,
CASE job_id WHEN 10 THEN 1.10*salary
WHEN 20 THEN 1.20*salary
WHEN 30 THEN 1.30*salary
ELSE salary END "REVISED_SALARY"
3.子查询
概念:出现在其他语句内部的select语句,称为子查询,或者是内部查询
单行子查询
- 1. 谁的工资比Abel高?
【SELECT last_name FROM employees WHERE salary > all(SELECT salary FROM employee WHERE last_name = 'Abel'】
- 2. 返回job_id与141员工号相同,salary比143号员工多的员工姓名,job_id 和 工资
【SELECT name,job_id,salary FROM employee WHERE job_id =141 AND salary >(select salary FROM employee WHERE department_id = 143) 】
- 3. 返回工资最少员工的last_name,job_id和salary
【SELECT last_name,job_id,salary FROM employee WHERE salary = (SELECT MIN(salary) FROM employee
- 4. 查询最低工资大于40号部门最低工资的部门id和他的最低工资】
【SELECT department_id,MIN(salary) FROM employee GROUP BY department_id HAVING MIN(salary) > (SELECT MIN(salary) FROM employee WHERE department_id = 40】 AND department_id <> 40
多行子查询
IN/NOT IN------------------------------>列表中的任意一个
ANY | SOME--------------------------->和子查询返回的某一个值比较
ALL--------------------------------------->和子查询返回的所有数值比较
4.创建和管理表
CREATE TABLE dept(
#表示自增
deptno INT(2) AUTO_INCREMENT,
dname VARCHAR(14),
loc CARCHAR(13),
#主键
PRIMARY KEY(deptno);
)
数据类型:
INT:使用四个字节保存整数数据
CHAR:定长字符数据,若未指定,默认一个字符,最大长度255
VARCHAR:可变字符数据,根据字符串实际长度保存
FLOAT(M,D):M+D<6
DOUBLE(M,D):M+D<15
DATE:日期数据格式
BLOB:二进制的长文本数据
TEXT:长文本数据
复制现有的表:
#复制数据
CREATE TABLE emp1 AS SELECT *FROM employee
#复制表的结构
CREATE TABLE emp1 AS SELECT *FROM employee WHERE 1=2;
#多表联查
SELECT * FORM A,B,C,D where
追加一个新的列
ALTER TABLE dept80
ADD job_id VARCHAR(15);
可以修改列的数据类型,尺寸和默认值
ALTER TABLE dept80
MODIFY last_name VARCHAR(30);
MODIFY (salary double(9,2) default 1000);
ALTER TABLE dept80
DROP COLUMN job_id;
ALTER TABLE dept80
CHANGE department_name dept_name VARCHAR(15);
DROP TABLE dept80;
truncate table dept;
delete from emp2;
select * from emp2;
rollback ;
select * from emp2;
ALTER table dept
RENAME TO detail_dept;
5.约束和分页
概念:
- 为了保证数据的一致性和完整性,SQL规范以约束的方式对表数据进行额外 条件限制
- 约束是表级的强制规定
- 可以在创建表时规定约束,也可以在创建表以后进行约束,通过ALTER TABLE 语句
约束的种类:
- NOT NULL非空约束
- UNIQUE 唯一约束,规定某个字段在整个表中唯一
- PRIMARY KEY 非空而且唯一
- FOREIGN KEY 外键
- CHECK 检查约束----(MYSQL不支持)
- DEFAULT 默认值
NULL:(ALTER TABLE MODIFY )
1.非空约束用于确保当前列的值不为空,非空约束只能够出现在表对象的列上
2.NULL类型特征值:
>所有的类型值都可以是null,包括int,float
>空字符串“ ”不等于NULL,0也不等于NULL;
UNIQUE:唯一约束允许出现多个空值:NULL
CREATE TABLE user (
id INT NOT NULL,
name VARCHAR(25),
password VARCHAR(25),
#使用表级约束语句法
#表示name和password组合不能够重复
CONSTRAINT uk_name_ped UNIQUE(name,password)
);
-添加唯一的约束
ALTER TABLE USER
ADD UNIQUE(name,password);
ALTER TABLE USER
ADD CONSTRAINT uk_name_ped UNIQUE(name,password);
-删除约束
ALTER TABLE user
DROP INDEX uk_name_pwd
PRIMARY KEY ==唯一约束+非空约束
#列级模式
CREATE TABLE emp4(
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(20)
);
#表级模式
CREATE TABLE emp5(
id INT AUTO_INCREMENT ,
name VARCHAR(20),
pwd VARCHAR(15),
CONSTRAINT emp5_id_pk PRIMARY KEY(id)
);
#组合模式
CREATE TABLE emp5(
id INT AUTO_INCREMENT ,
name VARCHAR(20),
pwd VARCHAR(15),
CONSTRAINT emp7_pk PRIMARY KEY(name,pwd)
);
-增,删,改
ALTER TABLE sth
ADD/DROP /MODIFY
FOREIGN KEY(创建外键约束能够联表查询)
========================================
CREATE TABLE emp4(
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(20)
);
=======================================
CREATE TABLE dept(
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(20)
);
CONSTRAINT dept_emp5_id_fk FOREIGN KEY(id)
REFERENCE emp4(id)
======================================
-增,删除
> ALTER TABLE emp
DROP FOREIGN KEY emp_dept_id_fk
>ALTER TABLE emp
ADD [CONSTRAINT emp_dept_id_fk] FOREIGN KEY(dept_id) REFERENCE dept (dept_id);
======================================
-FOREIGN :指定子表中的列
-REFERENCE:标识父表中的列
-ON DELETE CASCADE(联级删除)当父亲删除时,子也应该删除
-ON DELETE SET NULL:子表中相应的列置空
FORENIGN KEY (class_name,classes_number)
REFERENCE class(name,number) ON DELETE CASCADE
分页查询-limit:必须放在整个查询的最后面
前10条记录:select * from table limit 0,10
前11条至20条记录:select * from table limit 10,10
前21条至30条记录:select *from table limit 20,10;
6.事务
>1. 事务的概念和特性
事务:事务由单独的单元的一个或者是多个SQL语句组成,在这个单元中,每个MYSQL语句是相互依赖的
而整个单独单元作为一个不可分隔的整体,如果单元中某条SQL语句一旦执行失败或者产生错误,真个单元将会回滚。所有受到影响的数据将返回事物开始以前的状态,如果单元中的所有SQL语句执行成功,则事务被顺利进行
MySQL中存储引擎 [ 了解 ]
概念:在mysql中的数据用各种不同的技术存储在文件(或内存)中
通过show engines 查看
MySQL中常用的引擎有:innodb,myisam,memory等。其中innodb支持事务,mysiam和memory不支持
2.事务的ACID属性
数据库提供四种事务的隔离级别:
-READ UNCOMMITTED:允许事务读取未被其他事务提交的变更和脏读,不可重复读和幻读都会出现
-READ COMMITED :只允许事务读取已经被其他事务提交的变更,可以避免脏读,但不可重复读和幻读问题仍然存
REPEATABLE READ:确保事务可以多次从一个字段中读取相同的值,在这个事务持续期间,禁止其他事务对这个字段进行更改,避免了脏读和不可重复度读取,但是幻读仍然存
SERIALIZABLE(串行化):确保事务可以从一个表中读取相同的行,在这个事务持续期间,禁止其他事务对该表执行插入,更新和删除,所有并发问题都解决,但是性能低下
Oracle支持两种:READ COMMITED(读取已经提交),SERIALIZABLE,默认事务隔离级别:READ COMMITED
Mysql支持4种,默认级别为:REPEATABL EREAD
查看当前隔离级别:SELECT @@tx_isolation
设置当前连接的隔离级别:set transation isolation level read committed
7.数据库范式
第一范式(1NF):列不可分,eg:【联系人】(姓名,性别,电话),一个联系人有家庭电话和公司电话,那么这种表结构设计就没有达到 1NF
第二范式(2NF):有主键,保证完全依赖。eg:订单明细表【OrderDetail】(OrderID,ProductID,UnitPrice,Discount,Quantity,ProductName),Discount(折扣),Quantity(数量)完全依赖(取决)于主键(OderID,ProductID),而 UnitPrice,ProductName 只依赖于 ProductID,不符合2NF;
第三范式 (3NF):无传递依赖(非主键列 A 依赖于非主键列 B,非主键列 B 依赖于主键的情况),eg:订单表【Order】(OrderID,OrderDate,CustomerID,CustomerName,CustomerAddr,CustomerCity)主键是(OrderID),CustomerName,CustomerAddr,CustomerCity 直接依赖的是 CustomerID(非主键列),而不是直接依赖于主键,它是通过传递才依赖于主键,所以不符合 3NF。
9.存储过程和函数的区别是什么
存储过程是用户定义的一系列SQL语句的集合,涉及特定的表或者其他对象的任务,用户可以调用存储过程。而函数通常是数据库已经定义的方法,它接收
参数,并且返回某种类型的值,并不涉及特定用户表
10.游标的作用,如何知道游标已经到达最后了呢??
游标用于定位结果集的行,通常判断全局变量@@FETCH_STATUS可以判断其是否到了最后,通常此变量不等于0表示出错或者到了最后
11.触发器分为事前触发和事后触发,这两种触发有何区别?语句级触发和行级触发有何区别?
触发器是与表相关的数据库对象,在满足定义条件时触发,并执行触发器中定义的语句集合。触发器的这种特性可以协助应用在数据库端确保数据库的完整性。
事前触发运行于事前触发之前,事后触发运行于触发之后,语句级触发,可以运行在语句执行前或者执行之后,行级触发在触发器所影响的每一行触发一次
12.什么叫做SQL注入式攻击,如何防范?
所谓注入式攻击指的是,攻击者把SQL命令插入到Web表单的输入域或者页面请求的查询字符串中,欺骗服务器执行恶意的SQL命令,在某些表单中用户输入内容直接用来构造(或者影响)动态SQL命令,或者作为存储过程的输入参数,这类表单特别容易受到注入式攻击
防范SQL注入式攻击并不是一件特别困难的事情,只要在表单输入的内容构造SQL命令之前,把所有输入内容过滤一遍就够了,过滤输入内容可以按照多种方法进行。
-用来执行查询的数据库账号限制其权限 -将用户登陆的名字,密码等数据进行加密
-检查输入用户的合法性,确定输入内容只包含合法的数据
13.数据库索引
索引是对数据库表中一个或多个列的值进行排序的数据结构,以协助快速查询、更新数据库表中数据。
索引的实现通常使用B_TREE及其变种。索引加速了数据访问,因为存储引擎不会再去扫描整张表得到需要的数据;相反,它从根节点开始,根节点保存了子节点的指针,存储引擎会根据指针快速寻找数据。
14.索引有哪些结构
Hash索引和B+ Tree索引(5.7版本后InnoDB默认)
问:为什么采用B+ 树吗?这和Hash索引比较起来有什么优缺点吗?
答:因为Hash索引底层是哈希表,哈希表是一种以key-value存储数据的结构,所以多个数据在存储关系上是完全没有任何顺序关系的,所以,对于区间查询是无法直接通过索引查询的,就需要全表扫描。所以,哈希索引只适用于等值查询的场景。而B+ 树是一种多路平衡查询树,所以他的节点是天然有序的(左子节点小于父节点、父节点小于右子节点),所以对于范围查询的时候不需要做全表扫描
1、哈希索引适合等值查询,但是无法进行范围查询
2、哈希索引没办法利用索引完成排序
3、哈希索引不支持多列联合索引的最左匹配规则
4、如果有大量重复键值的情况下,哈希索引的效率会很低,因为存在哈希碰撞问题
15.问:文件和数据库为什么采用B+ 树,不采用红黑树?
文件与数据库都是需要较大的存储,也就是说,它们都不可能全部存储在内存中,故需要存储到磁盘上。而所谓索引,则为了数据的快速定位与查找,那么索引的结构组织要尽量减少查找过程中磁盘I/O的存取次数,因此B+树相比B树更为合适。数据库系统巧妙利用了局部性原理与磁盘预读原理,将一个节点的大小设为等于一个页,这样每个节点只需要一次I/O就可以完全载入,而红黑树这种结构,高度明显要深的多,并且由于逻辑上很近的节点(父子)物理上可能很远,无法利用局部性。最重要的是,B+树还有一个最大的好处:方便扫库。B树必须用中序遍历的方法按序扫库,而B+树直接从叶子结点挨个扫一遍就完了,B+树支持range-query非常方便,而B树不支持,这是数据库选用B+树的最主要原因。
16.B树,B+树,红黑树,AVL树,的特点以及区别
(1). B-Tree(平衡多路查找树)
B_TREE是一种平衡多路查找树,是一种动态查找效率很高的树形结构。B_TREE中所有结点的孩子结点的最大值称为B_TREE的阶,B_TREE的阶通常用m表示,简称为m叉树。一般来说,应该是m>=3。一颗m阶的B_TREE或是一颗空树,或者是满足下列条件的m叉树:
2)B+Tree : InnoDB存储引擎的索引实现
B+Tree是应文件系统所需而产生的一种B_TREE树的变形树。一棵m阶的B+树和m阶的B_TREE的差异在于以下三点:
(3). 为什么说B±tree比B 树更适合实际应用中操作系统的文件索引和数据库索引?
18.索引的优点
19.什么情况下设置了索但是无法使用
20.什么样的字段适合创建索引?
21.索引有哪些索引
聚集索引的顺序就是数据的物理存储顺序,而非聚集索引的解释是索引顺序与物理存储数据无关,正因为如此一个表中最多一个聚集索引
SQLserver中索引是用二叉树的数据结构描述的,我们可以这样理解聚集索引,索引的叶节点就是数据节点,而非聚集索引的叶节点仍然是索引节点,只不过有一个指针指向对应的数据
22. 索引的缺点
23.主键、自增主键、主键索引与唯一索引概念区别
主键:指字段 唯一、不为空值 的列;
主键索引:指的就是主键,主键是索引的一种,是唯一索引的特殊类型。创建主键的时候,数据库默认会为主键创建一个唯一索引;
自增主键:字段类型为数字、自增、并且是主键;
唯一索引:索引列的值必须唯一,但允许有空值。主键是唯一索引,这样说没错;但反过来说,唯一索引也是主键就错误了,因为唯一索引允许空值,主键不允许有空值,所以不能说唯一索引也是主键。
24.主键就是聚集索引吗?主键和索引有什么区别?
主键是一种特殊的唯一性索引,其可以是聚集索引,也可以是非聚集索引。在SQLServer中,主键的创建必须依赖于索引,默认创建的是聚集索引,但也可以显式指定为非聚集索引。InnoDB作为MySQL存储引擎时,默认按照主键进行聚集,如果没有定义主键,InnoDB会试着使用唯一的非空索引来代替。如果没有这种索引,InnoDB就会定义隐藏的主键然后在上面进行聚集。所以,对于聚集索引来说,你创建主键的时候,自动就创建了主键的聚集索引
25.实践中如何优化数据库
实践中,MySQL的优化主要涉及SQL语句及索引的优化、数据表结构的优化、系统配置的优化和硬件的优化四个方面,如下图所示:
26.简单说一说drop、delete与truncate的区别
SQL中的drop、delete、truncate都表示删除,但是三者有一些差别:
因此,在不再需要一张表的时候,用drop;在想删除部分数据行时候,用delete;在保留表而删除所有数据的时候用truncate。
27、MySQL中的悲观锁与乐观锁的实现
悲观锁与乐观锁是两种常见的资源并发锁设计思路,也是并发编程中一个非常基础的概念。
(1). 悲观锁
悲观锁的特点是先获取锁,再进行业务操作,即“悲观”的认为所有的操作均会导致并发安全问题,因此要先确保获取锁成功再进行业务操作。通常来讲,在数据库上的悲观锁需要数据库本身提供支持,即通过常用的select … for update操作来实现悲观锁。当数据库执行select … for update时会获取被select中的数据行的行锁,因此其他并发执行的select … for update如果试图选中同一行则会发生排斥(需要等待行锁被释放),因此达到锁的效果。select for update获取的行锁会在当前事务结束时自动释放,因此必须在事务中使用。
这里需要特别注意的是,不同的数据库对select… for update的实现和支持都是有所区别的,例如oracle支持select for update no wait,表示如果拿不到锁立刻报错,而不是等待,mysql就没有no wait这个选项。另外,mysql还有个问题是: select… for update语句执行中所有扫描过的行都会被锁上,这一点很容易造成问题。因此,如果在mysql中用悲观锁务必要确定使用了索引,而不是全表扫描。
(2). 乐观锁
乐观锁的特点先进行业务操作,只在最后实际更新数据时进行检查数据是否被更新过,若未被更新过,则更新成功;否则,失败重试。乐观锁在数据库上的实现完全是逻辑的,不需要数据库提供特殊的支持。一般的做法是在需要锁的数据上增加一个版本号或者时间戳,然后按照如下方式实现:
1. SELECT data AS old_data, version AS old_version FROM …;
2. 根据获取的数据进行业务操作,得到new_data和new_version
3. UPDATE SET data = new_data, version = new_version WHERE version = old_version
if (updated row > 0) {
// 乐观锁获取成功,操作完成
} else {
// 乐观锁获取失败,回滚并重试
}
乐观锁是否在事务中其实都是无所谓的,其底层机制是这样:在数据库内部update同一行的时候是不允许并发的,即数据库每次执行一条update语句时会获取被update行的写锁,直到这一行被成功更新后才释放。因此在业务操作进行前获取需要锁的数据的当前版本号,然后实际更新数据时再次对比版本号确认与之前获取的相同,并更新版本号,即可确认这其间没有发生并发的修改。如果更新失败,即可认为老版本的数据已经被并发修改掉而不存在了,此时认为获取锁失败,需要回滚整个业务操作并可根据需要重试整个过程。