定义:如果关系模式R的每个关系r的属性都是不可分割的数据项,那么就称R是第一范式的模式。 简单的说,每一个属性都是原子项,不可分割。 1NF是关系模式应具备的最起码的条件,如果数据库设计不能满足第一范式,就不称为关系型数据库。关系数据库设计研究的关系规范化是在1NF之上进行的。
例如(学生信息表):
学生编号 姓名 性别 联系方式 20080901 张三 男 email:zs@126.com,phone:88886666 20080902 李四 女 email:ls@126.com,phone:66668888
以上的表就不符合,第一范式:联系方式字段可以再分,所以变更为正确的是:
学生编号 姓名 性别 电子邮件 电话 20080901 张三 男 zs@126.com 88886666 20080902 李四 女 ls@126.com 66668888
定义:如果关系模式R是1NF,且每个非主属性完全依赖主键,那么就称R是第二范式。 简单的说,第二范式要满足以下的条件:首先要满足第一范式,其次每个非主属性要完全函数依赖与候选键,或者是主键。也就是说,每个非主属性是由整个主键函数决定的,而不能由主键的一部分来决定。
例如(学生选课表):
学生 课程 教师 教师职称 教材 教室 上课时间 李四 Spring 张老师 java讲师 《Spring深入浅出》 301 08:00 张三 Struts 杨老师 java讲师 《Struts in Action》 302 13:30
这里通过(学生,课程)可以确定教师、教师职称,教材,教室和上课时间,所以可以把(学生,课程)作为主键。但是,教材并不完全依赖于(学生,课程),只拿出课程就可以确定教材,因为一个课程,一定指定了某个教材。这就叫不完全依赖,或者部分依赖。出现这种情况,就不满足第二范式。
修改后,选课表:
学生 课程 教师 教师职称 教室 上课时间 李四 Spring 张老师 java讲师 301 08:00 张三 Struts 杨老师 java讲师 302 13:30
课程表:
课程 教材 Spring 《Spring深入浅出》 Struts 《Struts in Action》
所以,第二范式可以说是消除部分依赖。第二范式可以减少插入异常,删除异常和修改异常。
第三范式:每一列数据都直接依赖主键,而不传递依赖 。 例如: 在某企业中,有关系 W(工号,姓名,工种,工资),其中工资由工种唯一决定。将其规范化到第三范式:
W1(工号,姓名) W2(工种,工资)
错误,因为表W1和W2没有建立联系,不知道某个人的是什么工种的。
W1(工号,工种,工资) W2(工号,姓名)
错误,因为工号->工种,工种->工资(题目强调工资由工种唯一决定)。存在传递依赖 。
W1(工号,姓名,工种) W2(工种,工资)
正确,工号->姓名,工号—>工种 是可以确定的,但是 姓名->工种?不一定,因为可能存在同名的情况下,所以选项C是消除了传递依赖。
索引是对数据库表中一列或多列的值进行排序的一种单独的、物理的数据库结构。 优点: 1) 大大加快数据的检索速度;
2) 创建唯一性索引,保证数据库表中每一行数据的唯一性;
3) 加速表和表之间的连接;
4) 在使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间。
缺点: 1) 索引需要占物理空间;
2) 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,降低了数据的维护速度。
–创建索引,在列上点击右键,写一个名称,选定列即可。
主索引:主索引是一种只能在数据库表中建立不能在自由表中建立的索引。在指定的字段或表达式中,主索引的关键字绝对不允许有重复值。
候选索引:和主索引类似,它的值也不允许在指定的字段或表达式中重复。一个表中可以有多个候选索引。
普通索引允许关键字段有相同值,不能唯一标识一条记录,可以任意建立,数量不限。建立普通索引的主要目的是为了加快查询速度和建立表之间的联系。
唯一索引已经淘汰不用了,唯一索引允许关键字取重复的值。当有重复值 出现时,索引文件只保存重复值的第1次出现。提供唯一索引主要是为了兼容早期的版本。
复合索引可以只使用复合索引中的一部分,但必须是由最左部分开始,且可以存在常量。 例如索引是key index (a,b,c). 所以查询条件只能是在a,ab,abc,ac才算使用到索引。
建立索引为的是让检索查询的过程更快捷方便;相应的建立索引所付出的代价的是创建数据时额外的建立索引所产生的相关代价。
主键,外键,建立索引其实也是为了更好的查询,归根结底还是为了在查询和排序,分组时去使用,也就是where,order by ,group by三个地方。 主键和外键建立索引是因为相对的这两个值比较能确定一些数据,所以比较适合建立索引; where条件中的字段适合建立索引是因为要在查询过程中减少数据检索,需要使用索引。
modify:修改字段类型和长度的(即修改字段的属性)。 alter:修改表的数据结构(modify是alter的一种用法)。 update:修改数据内容。 例如,在数据库中增加一列:
alter table tableName add columnName varchar (30)删除一列:
alter table tableName drop column columnName% 表示任意0个或多个字符。如下语句:Select * FROM user Where name LIKE ‘%三%’; 将会把name为“张三”,“三脚猫”,“唐三藏”等等有“三”的全找出来。%三:表示左匹配。三%:表示右匹配。
_ 表示任意单个字符。语句: Select * FROM user Where name LIKE ‘三‘;只找出“唐三藏”。这样name为三个字且中间一个字是“三”的; Select * FROM user Where name LIKE ‘三__’; 只找出“三脚猫”这样name为三个字且第一个字是“三”的。
[ ] 表示括号内所列字符中的一个(类似与正则表达式)。语句:Select * FROM user Where name LIKE ‘[张李王]三’; 将找出“张三”、“李三”、“王三”(而不是“张李王三”); 如 [ ] 内有一系列字符(01234、abcde之类的)则可略写为“0-4”、“a-e“。Select * FROM user Where name LIKE ‘老[1-9]’;将找出“老1”、“老2”、……、“老9”;如要找“-”字符请将其放在首位:’张三[-1-9]’。
[^ ] 表示不在括号所列之内的单个字符。语句:Select * FROM user Where name LIKE ‘[^张李王]三’;将找出不姓“张”、“李”、“王”的“赵三”、“孙三”等;Select * FROM user Where name LIKE ‘老[^1-4]’; 将排除“老1”到“老4”寻找“老5”、“老6”、……、“老9”。
给列取别名.As关键字
SELECT FNumber AS 编号, FName AS 姓名 FROM T_Employee;对查询结果进行排序,ORDER BY 子句要放在 WHERE 子句之后.
SELECT * FROM T_Employee WHERE FAge>23 ORDER BY FAge DESC,FSalary DESC;模糊匹配,首字母未知.
SELECT * FROM T_Employee WHERE FName LIKE '_arry';模糊匹配,前后多个字符未知.
SELECT * FROM T_Employee WHERE FName LIKE '%n%';查询数据是否为 NULL,不能用 = 、!= 或 <>,要用IS关键字
SELECT * FROM T_Employee WHERE FName IS NULL; SELECT * FROM T_Employee WHERE FName IS NOT NULL;查询在某个范围内的数据,IN 表示包含于,IN后面是一个集合
SELECT * FROM T_Employee WHERE FAge IN (23, 25, 28);下面两条查询语句等价。
SELECT * FROM T_Employee WHERE FAge>=23 AND FAge<=30; SELECT * FROM T_Employee WHERE FAge BETWEEN 23 AND 30;–查询T_Employee表中数据条数
select COUNT(*) from T_Employee–查询工资最高的人
select MAX(FSalary) as Top1 from T_Employee–查询工资最低的人
select Min(FSalary) as Bottom1 from T_Employee–查询工资的平均水平
select Avg(FSalary) as 平均水平 from T_Employee–所有工资的和
select SUM(FSalary) as 总工资 from T_Employee–查询工资大于5K的员工总数
select COUNT(*) as total from T_Employee where FSalary>5000–按年龄排序升序,默认是升序
select * from T_Employee order by FAge ASC–多个条件排序,先什么,后什么,在前一个条件相同的情况下,根据后一个条件进行排列
–where在order by之前
select * from T_Employee order by FAge ASC, FSalary DESC–通配符查询
–1.单字符通配符_
–2.多字符通配符%
–以DEV开头的任意个字符串
select * from T_Employee where FNumber like 'DEV%'–以一个字符开头,om结尾的字符串
select * from T_Employee where FName like '_om'–检索姓名中包含m的字符
select * from T_Employee where FName like '%m%'注意:没有出现在group by 子句中的字段,不能出现在select语句后的列名列表中(聚合函数除外),例如:
Select FAge,AVG(FSalary),COUNT(*) from T_Employee group by FAge–加上where的group by 子句
–group by 必须出现在where后面
Select FAge,AVG(FSalary),COUNT(*) from T_Employee where FAge>=25 group by FAge–Having不能包含查不到的字段,只能包含聚合函数和本次查询有关的字段,例如:
select FAge,COUNT(*) from T_Employee group by FAge Having COUNT(*)>1而
select FAge,COUNT(*) from T_Employee group by FAge Having FSalary>2500是错误的,以为HAVING 子句中的列 ‘FSalary’ 无效,因为该列没有包含在聚合函数或 GROUP BY 子句中。换句话说,Having是对分组后信息的过滤,能用的列和select中能有的列是一样的,它不能代替where。 而这么写则是可以的:
select FAge,COUNT(*) from T_Employee group by FAge Having min(FSalary)>2500因为min(FSalary)是聚合函数。
–取出前三名员工的信息,根据工资降序排列。
MySQL中不支持TOP语句,SQL Server 和 sybase中才有效,否则可以写作:
select top 3 * from T_Employee order by FSalary DESC在MySQL中,使用
select * from tablename order by orderfield desc/asc limit position,counter;其中,position 指示从哪里开始查询,0表示从头开始,counter 表示查询的个数,于是可以写作:
select * from T_Employee order by FSalary ASC limit 0,3–根据工资取出排名在6-8的员工信息,按工资降排列
select * from T_Employee order by FSalary ASC limit 5,3Union关键字,联合2个结果,把2个查询结果结合为1个查询结果,要求:两次查询的列数必须一致。 —Union All:不合并重复数据 –Union:合并重复数据
select FName,Fage from T_TempEmployee union select FName,Fage from T_Employeedatediff(date1,date2):两个日期相减 date1 - date2,返回天数。
select datediff('2008-08-08', '2008-08-01'); # 7 select datediff('2008-08-01', '2008-08-08'); # -7timediff(time1,time2):两个日期相减 time1 - time2,返回 time 差值。
select timediff('2008-08-08 08:08:08', '2008-08-08 00:00:00'); # 08:08:08 select timediff('08:08:08', '00:00:00'); # 08:08:08注意:timediff(time1,time2) 函数的两个参数类型必须相同。
输出所有数据中通话时间最长的5条记录。
–@计算通话时间;
–@按通话时间降序排列;
–@取前5条记录。
select CallerNumber,timediff(StartDateTime,EndDateTime) as 总时长 from T_CallRecords order by timediff(StartDateTime,EndDateTime) DESC limit 0,5随机选择3行数据
select * from T_TempEmployee order by rand() limit 3是可以的,但是速度太慢,应该采用下面的方式: 选出某列最大的数,将它乘以rand(),然后四舍五入,得到一个更合适的随机数:
select * from T_TempEmployee where FAge >= (select round(rand() * (select max(FAge) from T_TempEmployee))) order by FAge limit 3求同一部门里薪水最高的那些员工: 思路是当某行的薪水等于他所在部门的最大值时,就说明他就是薪水最高的那个了。
select * from T_Employee t1 where FSalary = (select max(FSalary) from T_Employee t2 where t1.FDepartment = t2.FDepartment)或者先按部门分组,并求出每个部门的薪水最大值,然后逐行比较。这种写法比上面的稍微复杂一点。
select t1.* from T_Employee t1 ,(select FDepartment,max(FSalary) as ttm from T_Employee group by FDepartment) as tt where t1.FDepartment=tt.FDepartment and t1.FSalary=tt.ttmSQL语句需要先编译然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给定参数(如果该存储过程带有参数)来调用执行它。
存储过程是可编程的函数,在数据库中创建并保存,可以由SQL语句和控制结构组成。当想要在不同的应用程序或平台上执行相同的函数,或者封装特定功能时,存储过程是非常有用的。数据库中的存储过程可以看做是对编程中面向对象方法的模拟,它允许控制数据的访问方式。
1.基本语法:call sp_name() MySQL的存储过程参数没有默认值,所以在调用MySQL存储过程时,不能省略参数,但是可以用null来代替。
集中式体系结构:数据库和应用程序均储存在一台计算机上; 主从式(客户机/服务器式)体系结构:数据库存放在服务器上,应用程序存放在客户机上; 分布式体系结构: 数据库物理上存放在不同的场地。
事务是由一组SQL语句组成的逻辑处理单元。 数据库事务必须具备ACID特性,ACID是Atomic(原子性)、Consistency(一致性)、Isolation(隔离性或独立性)和Durability(持久性)的英文缩写。
指整个数据库事务是不可分割的工作单位。只有使据库中所有的操作执行成功,才算整个事务成功;事务中任何一个SQL语句执行失败,那么已经执行成功的SQL语句也必须撤销,数据库状态应该退回到执行事务前的状态。2、一致性: 指数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。
是指事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。保证数据库一致性是指当事务完成时,必须使所有数据都具有一致的状态。在关系型数据库中,所有的规则必须应用到事务的修改上,以便维护所有数据的完整性。
指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。
指的是只要事务成功结束,它对数据库所做的更新就必须永久保存下来。即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。
事务的(ACID)特性是由关系数据库管理系统(RDBMS,数据库系统)来实现的。 数据库管理系统采用日志来保证事务的原子性、一致性和持久性。日志记录了事务对数据库所做的更新,如果某个事务在执行过程中发生错误,就可以根据日志,撤销事务对数据库已做的更新,使数据库退回到执行事务前的初始状态。
数据库管理系统采用锁机制来实现事务的隔离性。当多个事务同时更新数据库中相同的数据时,只允许持有锁的事务能更新该数据,其他事务必须等待,直到前一个事务释放了锁,其他事务才有机会更新该数据。
一个事务的更新覆盖了其它事务的更新结果,就是所谓的更新丢失。例如:用户A把值从6改为2,用户B把值从2改为6,则用户A丢失了他的更新。
脏读:一个事务正在对一条记录做修改,在修改完成前,另一个事务也来读取同一条记录,这时它就读到了“脏”数据。
是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。
不可重复读的重点在于update和delete,而幻读的重点在于insert。
如果使用锁机制来实现这两种隔离级别,在可重复读中,该sql第一次读取到数据后,就将这些数据加锁,其它事务无法修改这些数据,就可以实现可重复 读了。但这种方法却无法锁住insert的数据,所以当事务A先前读取了数据,或者修改了全部数据,事务B还是可以insert数据提交,这时事务A就会 发现莫名其妙多了一条之前没有的数据,这就是幻读,不能通过行锁来避免。需要Serializable隔离级别 ,读用读锁,写用写锁,读锁和写锁互斥,这么做可以有效的避免幻读、不可重复读、脏读等问题,但会极大的降低数据库的并发能力。
悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。 乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。 乐观锁不能解决脏读的问题。
数据库的事务隔离越严格,并发副作用越小,但付出的代价也就越大。因为事务隔离本质上就是使事务在一定程度上“串行化”进行,这与“并发”是矛盾的。 4种隔离级别:
未提交读,最低级,还是可能出现脏读、不可重复读、幻读已提交读,语句级,可防止出现脏读可重复读,事务级,可防止出现脏读、不可重复读可序列化,事务级,无副作用只需要数据库后备副本和日志文件即可。
数据库存储引擎是数据库底层软件组织,数据库管理系统(DBMS)使用数据引擎进行创建、查询、更新和删除数据。不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能,使用不同的存储引擎,还可以 获得特定的功能。现在许多不同的数据库管理系统都支持多种不同的数据引擎。MySQL的核心就是存储引擎。
InnoDB是事务型数据库的首选引擎,支持事务安全表(ACID),支持行锁定和外键,InnoDB是默认的MySQL引擎。InnoDB主要特性有:
1、InnoDB给MySQL提供了具有提交、回滚和崩溃恢复能力的事物安全(ACID兼容)存储引擎。InnoDB锁定在行级并且也在SELECT语句中提供一个类似Oracle的非锁定读。这些功能增加了多用户部署和性能。在SQL查询中,可以自由地将InnoDB类型的表和其他MySQL的表类型混合起来,甚至在同一个查询中也可以混合
2、InnoDB是为处理巨大数据量的最大性能设计。它的CPU效率可能是任何其他基于磁盘的关系型数据库引擎锁不能匹敌的
3、InnoDB存储引擎完全与MySQL服务器整合,InnoDB存储引擎为在主内存中缓存数据和索引而维持它自己的缓冲池。InnoDB将它的表和索引在一个逻辑表空间中,表空间可以包含数个文件(或原始磁盘文件)。这与MyISAM表不同,比如在MyISAM表中每个表被存放在分离的文件中。InnoDB表可以是任何尺寸,即使在文件尺寸被限制为2GB的操作系统上
4、InnoDB支持外键完整性约束,存储表中的数据时,每张表的存储都按主键顺序存放,如果没有显示在表定义时指定主键,InnoDB会为每一行生成一个6字节的ROWID,并以此作为主键
5、InnoDB被用在众多需要高性能的大型数据库站点上
InnoDB不创建目录,使用InnoDB时,MySQL将在MySQL数据目录下创建一个名为ibdata1的10MB大小的自动扩展数据文件,以及两个名为ib_logfile0和ib_logfile1的5MB大小的日志文件
MyISAM基于ISAM存储引擎,并对其进行扩展。它是在Web、数据仓储和其他应用环境下最常使用的存储引擎之一。MyISAM拥有较高的插入、查询速度,但不支持事物。MyISAM主要特性有:
1、大文件(达到63位文件长度)在支持大文件的文件系统和操作系统上被支持
2、当把删除和更新及插入操作混合使用的时候,动态尺寸的行产生更少碎片。这要通过合并相邻被删除的块,以及若下一个块被删除,就扩展到下一块自动完成
3、每个MyISAM表最大索引数是64,这可以通过重新编译来改变。每个索引最大的列数是16
4、最大的键长度是1000字节,这也可以通过编译来改变,对于键长度超过250字节的情况,一个超过1024字节的键将被用上
5、BLOB和TEXT列可以被索引
6、NULL被允许在索引的列中,这个值占每个键的0~1个字节
7、所有数字键值以高字节优先被存储以允许一个更高的索引压缩
8、每个MyISAM类型的表都有一个AUTO_INCREMENT的内部列,当INSERT和UPDATE操作的时候该列被更新,同时AUTO_INCREMENT列将被刷新。所以说,MyISAM类型表的AUTO_INCREMENT列更新比InnoDB类型的AUTO_INCREMENT更快
9、可以把数据文件和索引文件放在不同目录
10、每个字符列可以有不同的字符集
11、有VARCHAR的表可以固定或动态记录长度
12、VARCHAR和CHAR列可以多达64KB
使用MyISAM引擎创建数据库,将产生3个文件。文件的名字以表名字开始,扩展名之处文件类型:frm文件存储表定义、数据文件的扩展名为.MYD(MYData)、索引文件的扩展名时.MYI(MYIndex)
MEMORY存储引擎将表中的数据存储到内存中,未查询和引用其他表数据提供快速访问。MEMORY主要特性有:
1、MEMORY表的每个表可以有多达32个索引,每个索引16列,以及500字节的最大键长度
2、MEMORY存储引擎执行HASH和BTREE缩影
3、可以在一个MEMORY表中有非唯一键值
4、MEMORY表使用一个固定的记录长度格式
5、MEMORY不支持BLOB或TEXT列
6、MEMORY支持AUTO_INCREMENT列和对可包含NULL值的列的索引
7、MEMORY表在所由客户端之间共享(就像其他任何非TEMPORARY表)
8、MEMORY表内存被存储在内存中,内存是MEMORY表和服务器在查询处理时的空闲中,创建的内部表共享
9、当不再需要MEMORY表的内容时,要释放被MEMORY表使用的内存,应该执行DELETE FROM或TRUNCATE TABLE,或者删除整个表(使用DROP TABLE)
除了关系型数据库的行式存储,NoSQL(非关系型数据库)可以分为4类: 键值模型,列式模型,文档模型和图形模型。 具体见详细
inner join(相等联接或内联接) :主表和从表都存在的记录才会查出来 left outer join:是以A表的记录为基础的,A可以看成左表,B可以看成右表,左表(A)的记录将会全部表示出来,而右表(B)只会显示符合搜索条件的记录(例子中为: A.aID = B.bID)。B表记录不足的地方均为NULL。 right outer join:和left outer join正相反。