什么是存储过程?有哪些优缺点?html
存储过程就像咱们编程语言中的函数同样,封装了咱们的代码(PLSQL、T-SQL)。java
存储过程的优势:mysql
存储过程的缺点:程序员
三个范式是什么面试
第一范式(1NF): 数据库表中的字段都是单一属性的,不可再分。这个单一属性由基本类型构成,包括整型、实数、字符型、逻辑型、日期型等。 第二范式(2NF):数据库表中不存在非关键字段对任一候选关键字段的部分函数依赖(部分函数依赖指的是存在组合关键字中的某些字段决定非关键字段的状况),也即全部非关键字段都彻底依赖于任意一组候选关键字。 第三范式(3NF):在第二范式的基础上,数据表中若是不存在非关键字段对任一候选关键字段的传递函数依赖则符合第三范式。所谓传递函数依赖,指的是若是存在"A → B → C"的决定关系,则C传递函数依赖于A。所以,知足第三范式的数据库表应该不存在以下依赖关系: 关键字段 → 非关键字段x → 非关键字段y
上面的文字咱们确定是看不懂的,也不肯意看下去的。接下来我就总结一下:sql
参考连接:数据库
什么是视图?以及视图的使用场景有哪些?编程
视图是一种基于数据表的一种虚表安全
有的时候,咱们可能只关系一张数据表中的某些字段,而另外的一些人只关系同一张数据表的某些字段...服务器
那么把所有的字段都都显示给他们看,这是不合理的。
咱们应该作到:他们想看到什么样的数据,咱们就给他们什么样的数据...一方面就可以让他们只关注本身的数据,另外一方面,咱们也保证数据表一些保密的数据不会泄露出来...
咱们在查询数据的时候,经常须要编写很是长的SQL语句,几乎每次都要写很长很长....上面已经说了,视图就是基于查询的一种虚表,也就是说,视图能够将查询出来的数据进行封装。。。那么咱们在使用的时候就会变得很是方便...
值得注意的是:使用视图可让咱们专一与逻辑,但不提升查询效率
drop、delete与truncate分别在什么场景之下使用?
咱们来对比一下他们的区别:
drop table
truncate table
delete from
5)删除速度慢,须要逐行删除
保留表而删除全部数据的时候用truncate
索引是什么?有什么做用以及优缺点?
什么是索引【Index】
索引表把数据变成是有序的....
快速定位到硬盘中的数据文件...
rowid的特色
索引的特色
须要注意的是:Oracle是自动帮咱们管理索引的,而且若是咱们指定了primary key或者unique约束,系统会自动在对应的列上建立索引..
何时【要】建立索引
何时【不要】建立索引
索引优缺点:
索引分类:
深刻理解索引可参考:
什么是事务?
事务简单来讲:一个Session中所进行全部的操做,要么同时成功,要么同时失败
ACID — 数据库事务正确执行的四个基本要素
一个支持事务(Transaction)中的数据库系统,必须要具备这四种特性,不然在事务过程(Transaction processing)当中没法保证数据的正确性,交易过程很可能达不到交易。
举个例子:A向B转帐,转帐这个流程中若是出现问题,事务可让数据恢复成原来同样【A帐户的钱没变,B帐户的钱也没变】。
事例说明:
/* * 咱们来模拟A向B帐号转帐的场景 * A和B帐户都有1000块,如今我让A帐户向B帐号转500块钱 * * */ //JDBC默认的状况下是关闭事务的,下面咱们看看关闭事务去操做转帐操做有什么问题 //A帐户减去500块 String sql = "UPDATE a SET money=money-500 "; preparedStatement = connection.prepareStatement(sql); preparedStatement.executeUpdate(); //B帐户多了500块 String sql2 = "UPDATE b SET money=money+500"; preparedStatement = connection.prepareStatement(sql2); preparedStatement.executeUpdate();
从上面看,咱们的确能够发现A向B转帐,成功了。但是若是A向B转帐的过程当中出现了问题呢?下面模拟一下
//A帐户减去500块 String sql = "UPDATE a SET money=money-500 "; preparedStatement = connection.prepareStatement(sql); preparedStatement.executeUpdate(); //这里模拟出现问题 int a = 3 / 0; String sql2 = "UPDATE b SET money=money+500"; preparedStatement = connection.prepareStatement(sql2); preparedStatement.executeUpdate();
显然,上面代码是会抛出异常的,咱们再来查询一下数据。A帐户少了500块钱,B帐户的钱没有增长。这明显是不合理的。
咱们能够经过事务来解决上面出现的问题
//开启事务,对数据的操做就不会当即生效。 connection.setAutoCommit(false); //A帐户减去500块 String sql = "UPDATE a SET money=money-500 "; preparedStatement = connection.prepareStatement(sql); preparedStatement.executeUpdate(); //在转帐过程当中出现问题 int a = 3 / 0; //B帐户多500块 String sql2 = "UPDATE b SET money=money+500"; preparedStatement = connection.prepareStatement(sql2); preparedStatement.executeUpdate(); //若是程序能执行到这里,没有抛出异常,咱们就提交数据 connection.commit(); //关闭事务【自动提交】 connection.setAutoCommit(true); } catch (SQLException e) { try { //若是出现了异常,就会进到这里来,咱们就把事务回滚【将数据变成原来那样】 connection.rollback(); //关闭事务【自动提交】 connection.setAutoCommit(true); } catch (SQLException e1) { e1.printStackTrace(); }
上面的程序也同样抛出了异常,A帐户钱没有减小,B帐户的钱也没有增长。
注意:当Connection遇到一个未处理的SQLException时,系统会非正常退出,事务也会自动回滚,但若是程序捕获到了异常,是须要在catch中显式回滚事务的。
数据库定义了4个隔离级别:
分别对应Connection类中的4个常量
脏读:一个事务读取到另一个事务未提交的数据
例子:A向B转帐,A执行了转帐语句,但A尚未提交事务,B读取数据,发现本身帐户钱变多了!B跟A说,我已经收到钱了。A回滚事务【rollback】,等B再查看帐户的钱时,发现钱并无多。
不可重复读:一个事务读取到另一个事务已经提交的数据,也就是说一个事务能够看到其余事务所作的修改
注:A查询数据库获得数据,B去修改数据库的数据,致使A屡次查询数据库的结果都不同【危害:A每次查询的结果都是受B的影响的,那么A查询出来的信息就没有意思了】
虚读(幻读):是指在一个事务内读取到了别的事务插入的数据,致使先后读取不一致。
注:和不可重复读相似,但虚读(幻读)会读到其余事务的插入的数据,致使先后读取不一致
简单总结:脏读是不可容忍的,不可重复读和虚读在必定的状况下是能够的【作统计的确定就不行】。
数据库的乐观锁和悲观锁是什么?
确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性,乐观锁和悲观锁是并发控制主要采用的技术手段。
悲观锁:
乐观锁:
参考资料:
超键、候选键、主键、外键分别是什么?
候选码和主码:
例子:邮寄地址(城市名,街道名,邮政编码,单位名,收件人)
SQL 约束有哪几种?
数据库运行于哪一种状态下能够防止数据的丢失?
在archivelog mode(归档模式)只要其归档日志文件不丢失,就能够有效地防止数据丢失。
Mysql的存储引擎有如下几种:
个人是5.7.15版本,默认使用的是Innodb版本!
经常使用的存储引擎有如下:
同一个数据库也可使用多种存储引擎的表。若是一个表修改要求比较高的事务处理,能够选择InnoDB。这个数据库中能够将查询要求比较高的表选择MyISAM存储。若是该数据库须要一个用于查询的临时表,能够选择MEMORY存储引擎。
参考资料:
MyIASM和Innodb两种引擎所使用的索引的数据结构是什么?
答案:都是B+树!
MyIASM引擎,B+树的数据结构中存储的内容其实是实际数据的地址值。也就是说它的索引和实际数据是分开的,只不过使用索引指向了实际数据。这种索引的模式被称为非汇集索引。
Innodb引擎的索引的数据结构也是B+树,只不过数据结构中存储的都是实际的数据,这种索引有被称为汇集索引。
varchar和char的区别
Char是一种固定长度的类型,varchar是一种可变长度的类型
mysql有关权限的表都有哪几个
MySQL服务器经过权限表来控制用户对数据库的访问,权限表存放在mysql数据库里,由mysql_install_db脚本初始化。这些权限表分别user,db,table_priv,columns_priv和host。下面分别介绍一下这些表的结构和内容:
数据表损坏的修复方式有哪些?
使用 myisamchk 来修复,具体步骤:
使用repair table 或者 OPTIMIZE table命令来修复,REPAIR TABLE table_name 修复表 OPTIMIZE TABLE table_name 优化表 REPAIR TABLE 用于修复被破坏的表。
OPTIMIZE TABLE 用于回收闲置的数据库空间,当表上的数据行被删除时,所占据的磁盘空间并无当即被回收,使用了OPTIMIZE TABLE命令后这些空间将被回收,而且对磁盘上的数据行进行重排(注意:是磁盘上,而非数据库)
MySQL中InnoDB引擎的行锁是经过加在什么上完成
InnoDB是基于索引来完成行锁
例: select * from tab_with_index where id = 1 for update
;
for update
能够根据条件来完成行锁锁定,而且 id 是有索引键的列,
若是 id 不是索引键那么InnoDB将完成表锁,,并发将无从谈起
在咱们书写SQL语句的时候,其实书写的顺序、策略会影响到SQL的性能,虽然实现的功能是同样的,可是它们的性能会有些许差异。
所以,下面就讲解在书写SQL的时候,怎么写比较好。
数据库的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表将被最早处理
在FROM子句中包含多个表的状况下:
若是有3个以上的表链接查询:
例如:查询员工的编号,姓名,工资,工资等级,部门名
emp表被引用得最多,记录数也是最多,所以放在form字句的最后面
select emp.empno,emp.ename,emp.sal,salgrade.grade,dept.dname from salgrade,dept,emp where (emp.deptno = dept.deptno) and (emp.sal between salgrade.losal and salgrade.hisal)
数据库采用自右而左的顺序解析WHERE子句,根据这个原理,表之间的链接必须写在其余WHERE条件之左,那些能够过滤掉最大数量记录的条件必须写在WHERE子句的之右。
emp.sal能够过滤多条记录,写在WHERE字句的最右边
select emp.empno,emp.ename,emp.sal,dept.dname from dept,emp where (emp.deptno = dept.deptno) and (emp.sal > 1500)
咱们当时学习的时候,“*”号是能够获取表中所有的字段数据的。
这里仅仅是:删除表的所有记录,除了表结构才这样作。
DELETE是一条一条记录的删除,而Truncate是将整个表删除,保留表结构,这样比DELETE快
例如使用mysql的concat()函数会比使用||来进行拼接快,由于concat()函数已经被mysql优化过了。
若是表或列的名称太长了,使用一些简短的别名也能稍微提升一些SQL的性能。毕竟要扫描的字符长度就变少了。。。
comiit会释放回滚点...
索引就是为了提升咱们的查询数据的,当表的记录量很是大的时候,咱们就可使用索引了。
咱们在编写SQL 的时候,官方推荐的是使用大写来写关键字,由于Oracle服务器老是先将小写字母转成大写后,才执行
由于Oracle服务器遇到NOT后,他就会中止目前的工做,转而执行全表扫描
WHERE子句中,若是索引列是函数的一部分,优化器将不使用索引而使用全表扫描,这样会变得变慢
>=
替代 >
低效: SELECT * FROM EMP WHERE DEPTNO > 3 首先定位到DEPTNO=3的记录而且扫描到第一个DEPT大于3的记录 高效: SELECT * FROM EMP WHERE DEPTNO >= 4 直接跳到第一个DEPT等于4的记录
select * from emp where sal = 1500 or sal = 3000 or sal = 800; select * from emp where sal in (1500,3000,800);
若是索引是创建在多个列上,只有在它的第一个列被WHERE子句引用时,优化器才会选择使用该索引。 当只引用索引的第二个列时,不引用索引的第一个列时,优化器使用了全表扫描而忽略了索引
create index emp_sal_job_idex on emp(sal,job); ---------------------------------- select * from emp where job != 'SALES'; 上边就不使用索引了。
这个么多花钱咯!
下列练习题参考自公众号Java知音:
基本表结构:
student(sno,sname,sage,ssex)学生表 course(cno,cname,tno) 课程表 sc(sno,cno,score) 成绩表 teacher(tno,tname) 教师表
题目:
101,查询课程1的成绩比课程2的成绩高的全部学生的学号 select a.sno from (select sno,score from sc where cno=1) a, (select sno,score from sc where cno=2) b where a.score>b.score and a.sno=b.sno 102,查询平均成绩大于60分的同窗的学号和平均成绩 select a.sno as "学号", avg(a.score) as "平均成绩" from (select sno,score from sc) a group by sno having avg(a.score)>60 103,查询全部同窗的学号、姓名、选课数、总成绩 select a.sno as 学号, b.sname as 姓名, count(a.cno) as 选课数, sum(a.score) as 总成绩 from sc a, student b where a.sno = b.sno group by a.sno, b.sname 或者: selectstudent.sno as 学号, student.sname as 姓名, count(sc.cno) as 选课数, sum(score) as 总成绩 from student left Outer join sc on student.sno = sc.sno group by student.sno, sname 104,查询姓“张”的老师的个数 selectcount(distinct(tname)) from teacher where tname like '张%‘ 或者: select tname as "姓名", count(distinct(tname)) as "人数" from teacher where tname like'张%' group by tname 105,查询没学过“张三”老师课的同窗的学号、姓名 select student.sno,student.sname from student where sno not in (select distinct(sc.sno) from sc,course,teacher where sc.cno=course.cno and teacher.tno=course.tno and teacher.tname='张三') 106,查询同时学过课程1和课程2的同窗的学号、姓名 select sno, sname from student where sno in (select sno from sc where sc.cno = 1) and sno in (select sno from sc where sc.cno = 2) 或者: selectc.sno, c.sname from (select sno from sc where sc.cno = 1) a, (select sno from sc where sc.cno = 2) b, student c where a.sno = b.sno and a.sno = c.sno 或者: select student.sno,student.sname from student,sc where student.sno=sc.sno and sc.cno=1 and exists( select * from sc as sc_2 where sc_2.sno=sc.sno and sc_2.cno=2) 107,查询学过“李四”老师所教全部课程的全部同窗的学号、姓名 select a.sno, a.sname from student a, sc b where a.sno = b.sno and b.cno in (select c.cno from course c, teacher d where c.tno = d.tno and d.tname = '李四') 或者: select a.sno, a.sname from student a, sc b, (select c.cno from course c, teacher d where c.tno = d.tno and d.tname = '李四') e where a.sno = b.sno and b.cno = e.cno 108,查询课程编号1的成绩比课程编号2的成绩高的全部同窗的学号、姓名 select a.sno, a.sname from student a, (select sno, score from sc where cno = 1) b, (select sno, score from sc where cno = 2) c where b.score > c.score and b.sno = c.sno and a.sno = b.sno 109,查询全部课程成绩小于60分的同窗的学号、姓名 select sno,sname from student where sno not in (select distinct sno from sc where score > 60) 110,查询至少有一门课程与学号为1的同窗所学课程相同的同窗的学号和姓名 select distinct a.sno, a.sname from student a, sc b where a.sno <> 1 and a.sno=b.sno and b.cno in (select cno from sc where sno = 1) 或者: select s.sno,s.sname from student s, (select sc.sno from sc where sc.cno in (select sc1.cno from sc sc1 where sc1.sno=1)and sc.sno<>1 group by sc.sno)r1 where r1.sno=s.sno 1十一、把“sc”表中“王五”所教课的成绩都更改成此课程的平均成绩 update sc set score = (select avg(sc_2.score) from sc sc_2 wheresc_2.cno=sc.cno) from course,teacher where course.cno=sc.cno and course.tno=teacher.tno andteacher.tname='王五' 1十二、查询和编号为2的同窗学习的课程彻底相同的其余同窗学号和姓名 这一题分两步查: 1, select sno from sc where sno <> 2 group by sno having sum(cno) = (select sum(cno) from sc where sno = 2) 2, select b.sno, b.sname from sc a, student b where b.sno <> 2 and a.sno = b.sno group by b.sno, b.sname having sum(cno) = (select sum(cno) from sc where sno = 2) 11三、删除学习“王五”老师课的sc表记录 delete sc from course, teacher where course.cno = sc.cno and course.tno = teacher.tno and tname = '王五' 11四、向sc表中插入一些记录,这些记录要求符合如下条件: 将没有课程3成绩同窗的该成绩补齐, 其成绩取全部学生的课程2的平均成绩 insert sc select sno, 3, (select avg(score) from sc where cno = 2) from student where sno not in (select sno from sc where cno = 3) 11五、按平平均分从高到低显示全部学生的以下统计报表: -- 学号,企业管理,马克思,UML,数据库,物理,课程数,平均分 select sno as 学号 ,max(case when cno = 1 then score end) AS 企业管理 ,max(case when cno = 2 then score end) AS 马克思 ,max(case when cno = 3 then score end) AS UML ,max(case when cno = 4 then score end) AS 数据库 ,max(case when cno = 5 then score end) AS 物理 ,count(cno) AS 课程数 ,avg(score) AS 平均分 FROM sc GROUP by sno ORDER by avg(score) DESC 11六、查询各科成绩最高分和最低分: 以以下形式显示:课程号,最高分,最低分 select cno as 课程号, max(score) as 最高分, min(score) 最低分 from sc group by cno select course.cno as '课程号' ,MAX(score) as '最高分' ,MIN(score) as '最低分' from sc,course where sc.cno=course.cno group by course.cno 11七、按各科平均成绩从低到高和及格率的百分数从高到低顺序 SELECT t.cno AS 课程号, max(course.cname)AS 课程名, isnull(AVG(score),0) AS 平均成绩, 100 * SUM(CASE WHEN isnull(score,0)>=60 THEN 1 ELSE 0 END)/count(1) AS 及格率 FROM sc t, course where t.cno = course.cno GROUP BY t.cno ORDER BY 及格率 desc 11八、查询以下课程平均成绩和及格率的百分数(用"1行"显示): 企业管理(001),马克思(002),UML (003),数据库(004) select avg(case when cno = 1 then score end) as 平均分1, avg(case when cno = 2 then score end) as 平均分2, avg(case when cno = 3 then score end) as 平均分3, avg(case when cno = 4 then score end) as 平均分4, 100 * sum(case when cno = 1 and score > 60 then 1 else 0 end) / sum(casewhen cno = 1 then 1 else 0 end) as 及格率1, 100 * sum(case when cno = 2 and score > 60 then 1 else 0 end) / sum(casewhen cno = 2 then 1 else 0 end) as 及格率2, 100 * sum(case when cno = 3 and score > 60 then 1 else 0 end) / sum(casewhen cno = 3 then 1 else 0 end) as 及格率3, 100 * sum(case when cno = 4 and score > 60 then 1 else 0 end) / sum(casewhen cno = 4 then 1 else 0 end) as 及格率4 from sc 11九、查询不一样老师所教不一样课程平均分, 从高到低显示 select max(c.tname) as 教师, max(b.cname) 课程, avg(a.score) 平均分 from sc a, course b, teacher c where a.cno = b.cno and b.tno = c.tno group by a.cno order by 平均分 desc 或者: select r.tname as '教师',r.rname as '课程' , AVG(score) as '平均分' from sc, (select t.tname,c.cno as rcso,c.cname as rname from teacher t ,course c where t.tno=c.tno)r where sc.cno=r.rcso group by sc.cno,r.tname,r.rname order by AVG(score) desc 120、查询以下课程成绩均在第3名到第6名之间的学生的成绩: -- [学生ID],[学生姓名],企业管理,马克思,UML,数据库,平均成绩 select top 6 max(a.sno) 学号, max(b.sname) 姓名, max(case when cno = 1 then score end) as 企业管理, max(case when cno = 2 then score end) as 马克思, max(case when cno = 3 then score end) as UML, max(case when cno = 4 then score end) as 数据库, avg(score) as 平均分 from sc a, student b where a.sno not in (select top 2 sno from sc where cno = 1 order by score desc) and a.sno not in (select top 2 sno from sc where cno = 2 order by scoredesc) and a.sno not in (select top 2 sno from sc where cno = 3 order by scoredesc) and a.sno not in (select top 2 sno from sc where cno = 4 order by scoredesc) and a.sno = b.sno group by a.sno
在Mysql中,一个用户下能够建立多个库:
而在Oracle中,Oracle服务器是由两部分组成
一个数据库实例可拥有多个用户,一个用户默认拥有一个表空间。
表空间是存储咱们数据库表的地方,表空间内能够有多个文件。
当咱们使用Oracle做为咱们数据库时,咱们须要指定用户、表空间来存储咱们所须要的数据!
参考资料: