3.1.1、数据库的分类及常用的数据库
数据库分为:关系型数据库和非关系型数据库
关系型:mysql oracle sqlserver等
非关系型:redis,memcache,mogodb,hadoop等
3.1.2简单介绍一下关系数据库三范式?
范式就是规范,就是关系型数据库在设计表时,要遵循的三个规范。
要想满足第二范式必须先满足第一范式,要满足第三范式必须先满足第二范式。
第一范式(1NF)是指数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。列数据的不可分割
二范式(2NF)要求数据库表中的每个行必须可以被唯一地区分。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。(主键)
满足第三范式(3NF)必须先满足第二范式(2NF)。简而言之,第三范式(3NF)要求一个数据库表中不包含已在其它表中已包含的非主关键字信息。(外键)
反三范式,有的时候为了效率,可以设置重复或者可以推导出的字段.
订单(总价)和订单项(单价)
3.1.3事务四个基本特征或 ACID 特性。
事务是并发控制的单位,是用户定义的一个操作序列。这些操作要么都做,要么都不做,是一个不可分割的工作单位。
一个转账必须 A账号扣钱成功,B账号加钱成功,才算正真的转账成功。
事务必须满足四大特征:原子性,一致性,隔离性,持久性/持续性
原子性:表示事务内操作不可分割。要么都成功、要么都是失败.
一致性:要么都成功、要么都是失败.后面的失败了要对前面的操作进行回滚。
隔离性:一个事务开始后,不能后受其他事务干扰。
持久性/持续性:表示事务开始了,就不能终止。
3.1.4 mysql数据库的默认的最大连接数?
100
为什么需要最大连接数?特定服务器上面的数据库只能支持一定数目同时连接,这时候我们一般都会设置最大连接数(最多同时服务多少连接)。
在数据库安装时都会有一个默认的最大连接数为100
3.1.5说一下msyql的分页?Oracle的分页?
为什么需要分页?在很多数据是,不可能完全显示数据。进行分段显示.
Mysql是使用关键字limit来进行分页的 limit offset,size 表示从多少索引去多少位.
Oracle的分页,大部分情况下,我们是记不住了。说思路,要使用三层嵌套查询。
Oracle的分页有点儿记不住了,只记得一些大概。是使用了三层嵌套查询。如果在工作中使用了,可以到原来的项目中拷贝或上网查询。
mysql:
String sql ="select * from students order by id limit " + pageSize*(pageNumber-1) + "," + pageSize;
oracle:
String sql =
"select * from " +
(select *,rownum rid from (select * from students order by postime desc) where rid<=" + pagesize*pagenumber + ") as t" +
"where t>" + pageSize*(pageNumber-1);
3.1.6简单讲一下数据库的触发器的使用场景?
触发器,需要有触发条件,当条件满足以后做什么操作。
触发器用处还是很多的,比如校内网、开心网、Facebook,你发一个日志,自动通知好友,其实就是在增加日志时做一个后触发,再向通知表中写入条目。因为触发器效率高。而UCH没有用触发器,效率和数据处理能力都很低。
每插入一个帖子,都希望将版面表中的最后发帖时间,帖子总数字段进行同步更新,用触发器做效率就很高。
create table board1(id int primary key auto_increment,name varchar(50),ar ticleCount int);
create table article1(id int primary key auto_increment,title varchar(50) ,bid int references board1(id));
delimiter |#把分割符;改成|
create trigger insertArticle_Trigger after insert on article1 for each ro w begin -> update board1 set articleCount=articleCount+1 where id= NEW.bid; -> end; -> |
delimiter ;
insert into board1 value (null,'test',0);
insert into article1 value(null,'test',1);
|
3.1.7、简单讲一下数据库的存储过程的使用场景?
数据库存储过程具有如下优点:
1、存储过程只在创建时进行编译,以后每次执行存储过程都不需再重新编译,而一般 SQL 语句每执行一次就编译一次,因此使用存储过程可以大大提高数据库执行速度。
2、通常,复杂的业务逻辑需要多条 SQL 语句。这些语句要分别地从客户机发送到服务器,当客户机和服务器之间的操作很多时,将产生大量的网络传输。如果将这些操作放在一个存储过程中,那么客户机和服务器之间的网络传输就会大大减少,降低了网络负载。
3、存储过程创建一次便可以重复使用,从而可以减少数据库开发人员的工作量。
4、安全性高,存储过程可以屏蔽对底层数据库对象的直接访问,使用 EXECUTE 权限调用存储过程,无需拥有访问底层数据库对象的显式权限。
正是由于存储过程的上述优点,目前常用的数据库都支持存储过程,例如 IBM DB2,Microsoft SQL Server,Oracle,Access 等,开源数据库系统 MySQL 也在 5.0 的时候实现了对存储过程的支持。
定义存储过程:
create procedure insert_Student (_name varchar(50),_age int ,out _id int) begin insert into student value(null,_name,_age); select max(stuId) into _id from student; end;
call insert_Student('wfz',23,@id); select @id;
|
3.1.8 用jdbc怎么调用存储过程?
加载驱动
获取连接
设置参数
执行
释放连接
package com.huawei.interview.lym;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Types;
public class JdbcTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Connection cn = null;
CallableStatement cstmt = null;
try {
//这里最好不要这么干,因为驱动名写死在程序中了
Class.forName("com.mysql.jdbc.Driver");
//实际项目中,这里应用DataSource数据,如果用框架,
//这个数据源不需要我们编码创建,我们只需Datasource ds = context.lookup()
//cn = ds.getConnection();
cn = DriverManager.getConnection("jdbc:mysql:///test","root","root");
cstmt = cn.prepareCall("{call insert_Student(?,?,?)}");
cstmt.registerOutParameter(3,Types.INTEGER);
cstmt.setString(1, "wangwu");
cstmt.setInt(2, 25);
cstmt.execute();
//get第几个,不同的数据库不一样,建议不写
System.out.println(cstmt.getString(3));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
/*try{cstmt.close();}catch(Exception e){}
try{cn.close();}catch(Exception e){}*/
try {
if(cstmt != null)
cstmt.close();
if(cn != null)
cn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
3.1.9、简单说一下你对jdbc的理解?
Java database connection java数据库连接.数据库管理系统(mysql oracle等)是很多,每个数据库管理系统支持的命令是不一样的。
Java只定义接口,让数据库厂商自己实现接口,对于我们者而言。只需要导入对应厂商开发的实现即可。
然后以接口方式进行调用.(mysql + mysql驱动(实现)+jdbc)
3.1.10、写一个简单的jdbc的程序。写一个访问oracle数据的jdbc程序?
加载驱动(com.mysql.jdbc.Driver,oracle.jdbc.driver.OracleDriver)
获取连接(DriverManager.getConnection(url,usernam,passord))
设置参数 Statement PreparedStatement
cstmt.setXXX(index, value);
执行 executeQuery executeUpdate
释放连接 (是否连接要从小到大,必须放到finnaly)
3.1.11 JDBC中的PreparedStatement相比Statement的好处
大多数我们都使用PreparedStatement代替Statement
1:PreparedStatement是预编译的,比Statement速度快
2:代码的可读性和可维护性
虽然用PreparedStatement来代替Statement会使代码多出几行,但这样的代码无论从可读性还是可维护性上来说.都比直接用Statement的代码高很多档次:
stmt.executeUpdate("insert into tb_name (col1,col2,col2,col4) values ('"+var1+"','"+var2+"',"+var3+",'"+var4+"')");
perstmt = con.prepareStatement("insert into tb_name (col1,col2,col2,col4) values (?,?,?,?)");
perstmt.setString(1,var1);
perstmt.setString(2,var2);
perstmt.setString(3,var3);
perstmt.setString(4,var4);
perstmt.executeUpdate();
不用我多说,对于第一种方法,别说其他人去读你的代码,就是你自己过一段时间再去读,都会觉得伤心。
3:安全性
PreparedStatement可以防止SQL注入攻击,而Statement却不能。比如说:
String sql = "select * from tb_name where name= '"+varname+"' and passwd='"+varpasswd+"'";
如果我们把[' or '1' = '1]作为varpasswd传入进来.用户名随意,看看会成为什么?
select * from tb_name = '随意' and passwd = '' or '1' = '1';
因为'1'='1'肯定成立,所以可以任何通过验证,更有甚者:
把[';drop table tb_name;]作为varpasswd传入进来,则:
select * from tb_name = '随意' and passwd = '';drop table tb_name;有些数据库是不会让你成功的,但也有很多数据库就可以使这些语句得到执行。
而如果你使用预编译语句你传入的任何内容就不会和原来的语句发生任何匹配的关系,只要全使用预编译语句你就用不着对传入的数据做任何过虑。而如果使用普通的statement,有可能要对drop等做费尽心机的判断和过虑。
3.1.12 数据库连接池作用
1、限定数据库的个数,不会导致由于数据库连接过多导致系统运行缓慢或崩溃
2、数据库连接不需要每次都去创建或销毁,节约了资源
3、数据库连接不需要每次都去创建,响应时间更快。