数据库面试

发布时间:2016-10-21 11:12:15   来源:文档文库   
字号:

数据库面试

1、 SQL语言包括数据定义(DDL)、数据操纵(Data Manipulation),数据控制(Data Control)DQLDTL

数据定义:Create Table,Alter Table,Drop Table, Craete/Drop Index

数据操纵:Select ,insert,update,delete,

数据控制:grant,revoke

2、SQL常用命令:

CREATE TABLE Student(

ID NUMBER PRIMARY KEY,

NAME VARCHAR2(50) NOT NULL);//建表

CREATE VIEW view_name AS

Select * FROM Table_name;//建视图

Create UNIQUE INDEX index_name ON TableName(col_name);//建索引

INSERT INTO tablename {column1,column2,…} values(exp1,exp2,…);//插入

INSERT INTO Viewname {column1,column2,…} values(exp1,exp2,…);//插入视图实际影响表

UPDATE tablename SET name=’zang 3’ condition;//更新数据

DELETE FROM Tablename WHERE condition;//删除

GRANT (Select,delete,…) ON (对象) TO USER_NAME [WITH GRANT OPTION];//授权

REVOKE (权限表) ON(对象) FROM USER_NAME [WITH REVOKE OPTION] //撤权

列出工作人员及其领导的名字:

Select E.NAME, S.NAME FROM EMPLOYEE E S

WHERE E.SUPERName=S.Name

3、完整性约束:

实体完整性、参照完整性、用户定义完整性

4、 索引作用,优缺点(详情

第一,通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性 
第二,可以大大加快 数据的检索速度,这也是创建索引的最主要的原因。 
第三,可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。 
第四,在使用分组和排序 子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。 
第五,通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。

缺点

第一,创建索引和维护索引要耗费时间,这种时间随着数据 量的增加而增加。 
第二,索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。 
第三,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。

使用范围:

经常需要搜索的列上,可以加快搜索的速度; 
在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构; 
经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度; 
在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的 
在经常需要排序的列上创 建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间; 
经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。

不适用范围:

第一,对于那些在查询中很少使用或者参考的列不应该创建索引。这是因 为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。 
第二,对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比 例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。 
第三,对于那些定义为text, imagebit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。 
第四,当修改性能远远大于检索性能时,不应该创建索 引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因 此,当修改性能远远大于检索性能时,不应该创建索引。

5、事务

是一系列的数据库操作,是数据库应用的基本逻辑单位。事务性质:原子性、

原子性。即不可分割性,事务要么全部被执行,要么就全部不被执行。

一致性或可串性。事务的执行使得数据库从一种正确状态转换成另一种正确状态

隔离性。在事务正确提交之前,不允许把该事务对数据的任何改变提供给任何其他事务,

持久性。事务正确提交后,其结果将永久保存在数据库中,即使在事务提交后有了其他故障,事务的处理结果也会得到保存。

6、

共享锁、互斥锁

7、死锁及处理:

事务循环等待数据锁,则会死锁。

死锁处理:预防死锁协议,死锁恢复机制

8、存储过程:

存储过程就是编译好了的一些sql语句。

1.存储过程因为SQL语句已经预编绎过了,因此运行的速度比较快。

2. 可保证数据的安全性和完整性。通过存储过程可以使没有权限的用户在控制之下间接地存取数据库,从而保证数据的安全。通过存储过程可以使相关的动作在一起发生,从而可以维护数据库的完整性。

3.可以降低网络的通信量。存储过程主要是在服务器上运行,减少对客户机的压力。

4:存储过程可以接受参数、输出参数、返回单个或多个结果集以及返回值。可以向程序返回错误原因

5:存储过程可以包含程序流、逻辑以及对数据库的查询。同时可以实体封装和隐藏了数据逻辑。  

9、触发器

当满足触发器条件,则系统自动执行触发器的触发体。

触发时间:有before,after.触发事件:有insert,update,delete三种。触发类型:有行触发、语句触发

10、内联接,外联接区别?

内连接是保证两个表中所有的行都要满足连接条件,而外连接则不然。

在外连接中,某些不满条件的列也会显示出来,也就是说,只限制其中一个表的行,而不限制另一个表的行。分左连接、右连接、全连接三种

11、innodbmyisam

myisam索引文件和数据文件是分离的 ,myisam索引的存储方式是非聚合的,索引文件存储在MYI文件。

innodb 索引和数据文件是保存在一起的;数据共享的话会放在ibdata ,独享的话会放在ibd

innodb每个表只有一个聚集索引。如果木有主键,则会选择一个非空唯一索引来代替主键;如果再不存在则会定义一个隐藏的主键进行聚集。

innodb普通索引,这个跟myisam的差不多 但是与myisam索引的不同是叶子上存储是主键的值而不是记录的指针地址,而且用他检索的时候会检索两边索引 因为他需要先通过他查找主键(因为他叶子上面是的主键值) 然后通过主键到聚集索引中检索得到数据

MyISAM是非事务安全型的,而InnoDB是事务安全型的。

MyISAM锁的粒度是表级,而InnoDB支持行级锁定。

MyISAM支持全文类型索引,而InnoDB不支持全文索引。

MyISAM相对简单,所以在效率上要优于InnoDB,小型应用可以考虑使用MyISAM

MyISAM表是保存成文件的形式,在跨平台的数据转移中使用MyISAM存储会省去不少的麻烦。

InnoDB表比MyISAM表更安全,可以在保证数据不会丢失的情况下,切换非事务表到事务表(alter table tablename type=innodb

12、聚集和非聚集

非聚集索引叶子页包含一个指向表中的记录的指针地址,记录的物理顺序和索引的顺序不一致

聚集索引则数据行和键值一起保存在叶子页 而且记录的排列顺序与索引的排列顺序一致

13、数据库事务隔离级别

脏读,两个并发的事务,事务A:领导给singo发工资事务Bsingo查询工资账户事务B读取了事务A尚未提交的数据

不可重复读,两个并发的事务,事务Asingo消费事务Bsingo的老婆网上转账,事务A事先读取了数据,事务B紧接了更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。在一个事务内,多次读同一个数据。在这个事务还没有结束时,另一个事务也访问该同一数据。那么,在第一个事务的两次读数据之间。由于第二个事务的修改,那么第一个事务读到的数据可能不一样,这样就发生了在一个事务内两次读到的数据是不一样的,因此称为不可重复读,即原始读取不可重复)

幻读是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,比如这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样.一般解决幻读的方法是增加范围锁RangeS,锁定检锁范围为只读,这样就避免了幻读。

多数数据库的默认级别就是Read committed,比如Sql Server , Oracle

Mysql的默认隔离级别就是Repeatable read

分布式领域CAP理论,
Consistency(一致性), 数据一致更新,所有数据变动都是同步的
Availability(可用性), 好的响应性能
Partition tolerance(分区容错性) 可靠性
定理:任何分布式系统只可同时满足二点,没法三者兼顾。


关系数据库的ACID模型拥有 高一致性 + 可用性 很难进行分区
Atomicity原子性:一个事务中所有操作都必须全部完成,要么全部不完成。
Consistency一致性. 在事务开始或结束时,数据库应该在一致状态。
Isolation隔离层. 事务将假定只有它自己在操作数据库,彼此不知晓。
Durability. 一旦事务完成,就不能返回。

BASE模型反ACID模型,完全不同ACID模型,牺牲高一致性,获得可用性或可靠性
Basically Available基本可用。支持分区失败(e.g. sharding碎片划分数据库)
Soft state软状态 状态可以有一段时间不同步,异步
Eventually consistent最终一致,最终数据是一致的就可以了,而不是时时高一致。

实现一:(行转列,列转行

教师号  星期号 是否有课

 1    2   有

 1    3   有

 2    1   有

 3    2   有`

 1    2   有

写一条sql语句让你变为这样的表

教师号 星期一 星期二 星期三

 1       2   1 

 2   1   

 3       1

各星期下的数字表示:对应的教师在星期几已经排的课数

答:

create database study

go

use study

go

create table TeacherCourse

(

ID int not null,

TeacherID int,

WeekID int,

HasCourse bit,

)

insert into TeacherCourse (ID,TeacherID,WeekID ,HasCourse) values (1,1,2,1)

insert into TeacherCourse (ID,TeacherID,WeekID ,HasCourse) values (2,1,3,1)

insert into TeacherCourse (ID,TeacherID,WeekID ,HasCourse) values (3,2,1,1)

insert into TeacherCourse (ID,TeacherID,WeekID ,HasCourse) values (4,3,2,1)

insert into TeacherCourse (ID,TeacherID,WeekID ,HasCourse) values (5,1,2,1)

select TeacherID,WeekID,count(*) from TeacherCourse

where HasCourse=1

group by TeacherID,WeekID

order by TeacherID

select TeacherID,

count(case WeekID

when '1' then 1 else null

end) as '星期一',

count(case WeekID

when '2' then 1 else null

end) as '星期二',

count(case WeekID

when '3' then 1 else null

end) as '星期三',

count(case WeekID

when '4' then 1 else null

end) as '星期四' ,

count(case WeekID

when '5' then 1 else null

end) as '星期五',

count(case WeekID

when '6' then 1 else null

end) as '星期六',

count(case WeekID

when '7' then 1 else null

end) as '星期日'

from TeacherCourse

where HasCourse=1

group by TeacherID

order by TeacherID

实现二:(取第二大值)

select top 1 * from

(select top 2 * from tablename order by columnname) a

order by columnname desc

实现三:

查询A(ID,Name)表中第3140条记录,ID作为主键可能是不是连续增长的列,完整的查询语句如下:

select top 10 * from A where ID >(select max(ID) from (select top 30 ID from A order by A ) T) order by A

查询表A中存在ID重复三次以上的记录,完整的查询语句如下:

select * from(select count(ID) as count from table group by ID)T where T.count>3

1、
 MySQL 中的分页查询实现

import java.io.InputStream;

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.util.List;

import java.util.List;

import week07.domain.Flight;

import week07.domain.News;

import week07.util.ConnectionUtils;

public class FlightDaoImplForMySQL {

       /**

        * 分页查询flight表的所有列的数据

        *

        * @param page

        *            第几页

        * @param rowsPerPages

        *            每页显示行数

        * @param con

        *            数据库连接

        * @return 查询到的数据以News对象的形式存储到List中返回

        * @throws Exception

        */

       public List listPagesNewsDB(int page, int rowsPerPage,

                     Connection con) throws Exception {

              int from = (page - 1) * rowsPerPage;

              String sql = "select * from flight limit ?, ?;";

              Connection conn = null;

              PreparedStatement pStmt = null;

              ResultSet rs = null;

              Flight flight = null;

              List flights = new List();

              try {

                     conn = ConnectionUtils.openConnection();

                     pStmt = conn.prepareStatement(sql);

                     pStmt.setInt(1, from);

                     pStmt.setInt(2, rowsPerPage);

                     rs = pStmt.executeQuery();

                     while (rs.next()) {

                            String id = rs.getString(1);

                            String num = rs.getString(2);

                            flight = new Flight(id, num);

                            flights.add(flight);

                     }

              } catch (SQLException e) {

                     e.printStackTrace();

              } finally {

                     ConnectionUtils.closeResultSet(rs);

                     ConnectionUtils.closeStatement(pStmt);

                     ConnectionUtils.closeConnection(conn);

              }

              return flights;

       }

       public static void main(String[] args) throws Exception {

              List ff = new FlightDaoImplForMySQL().

              listPagesNewsDB(2, 3,

                            ConnectionUtils.openConnection());

              for(Flight f:ff){

                     System.out.println("=="+f.getId()+"="+f.getNum()+"==");

              }

       }

}

-------------------------------------------------------------------------------

//Oracle 中的分页查询实现

import java.io.FileInputStream;

import java.io.InputStream;

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.text.SimpleDateFormat;

import java.util.List;

import java.util.List;

import org.dom4j.Document;

import org.dom4j.Element;

import org.dom4j.io.SAXReader;

import week07.domain.News;

import week07.util.ConnectionUtils;

public class NewsDaoImpl implements INewsDao {

       /**

        * 分页查询news表的所有列的数据

        *

        * @param page

        *            第几页

        * @param rowsPerPages

        *            每页显示行数

        * @param con

        *            数据库连接

        * @return 查询到的数据以News对象的形式存储到List中返回

        * @throws Exception

        * select news_id, title, content, author, pubDate, rn from(

        *                       select news_id, title, content, author, pubDate, rownum rn

        *                       from news

        *                       where rownum < ? )

        * where rn >= ?;

        */

       public List listPagesNewsDB(int page, int rowsPerPage,

              Connection con) throws Exception {

              int from = (page - 1) * rowsPerPage + 1;

              int to = from + rowsPerPage;

              String sql = "select news_id, title, "

                            + "content, author, pubDate, rn " + "from "

                            + "(select news_id, title, content, "

                            + "author, pubDate, rownum rn "

                            + "from news where rownum < ? ) " + "where rn >= ?";

              Connection conn = null;

              PreparedStatement pStmt = null;

              ResultSet rs = null;

              News news = null;

              List newses = new List();

              try {

                     conn = ConnectionUtils.openConnection();

                     pStmt = conn.prepareStatement(sql);

                     pStmt.setInt(1, to);

                     pStmt.setInt(2, from);

                     rs = pStmt.executeQuery();

                     while (rs.next()) {

                            news = new News();

                            news.setNewsId(rs.getLong(1));

                            news.setTitle(rs.getString(2));

                            news.setContent(rs.getString(3));

                            news.setAuthor(rs.getString(4));

                            news.setPubdate(rs.getDate(5));

                            newses.add(news);

                     }

              } catch (SQLException e) {

                     e.printStackTrace();

              } finally {

                     ConnectionUtils.closeResultSet(rs);

                     ConnectionUtils.closeStatement(pStmt);

                     ConnectionUtils.closeConnection(conn);

              }

              return newses;

       }

}

2、分页,CTE实现

DECLARE @Start INT

DECLARE @End IN

SELECT @Start = 14000,@End = 14050;

WITH EmployeePage AS

(SELECT LastName, FirstName, EmailAddress,

ROW_NUMBER() OVER (ORDER BY LastName, FirstName, EmailAddress) AS RowNumber

FROM Employee

SELECT LastName, FirstName, EmailAddress

FROM EmployeePage

WHERE RowNumber > @Start AND RowNumber <= @End

ORDER BY LastName, FirstName, EmailAddress

GO

3、JDBCHibernate 分页怎样实现?

答:方法分别为:

1) Hibernate 的分页:

Query query = session.createQuery("from Student");

query.setFirstResult(firstResult);//设置每页开始的记录号

query.setMaxResults(resultNumber);//设置每页显示的记录数

Collection students = query.list();

2) JDBC 的分页:根据不同的数据库采用不同的sql 分页语句

例如: Oracle 中的sql 语句为: "SELECT * FROM (SELECT a.*, rownum r FROM

TB_STUDENT) WHERE r between 2 and 10" 查询从记录号2 到记录号10 之间的所有记

4、用你熟悉的语言写一个连接ORACLE数据库的程序,能够完成修改和查询工作。答:JDBC示例程序

如下:public void testJdbc(){

Connection con = null;

PreparedStatement ps = null;

ResultSet rs = null;

try{

//step1:注册驱动;

Class.forName("oracle.jdbc.driver.OracleDriver");

//step 2:获取数据库连接;

con=DriverManager.getConnection(

"jdbc:oracle:thin:@192.168.0.23:1521:tarena", "openlab","open123");

/************************查询************************/

//step 3:创建Statement

 String sql = "SELECT id, fname, lname, age, FROM Person_Tbl";

ps = con.prepareStatement(sql);

//step 4 :执行查询语句,获取结果集;

rs = ps.executeQuery();

//step 5:处理结果集输出结果集中保存的查询结果;

while (rs.next()){

System.out.print("id = " + rs.getLong("id"));

System.out.print(" , fname = " + rs.getString("fname"));

System.out.print(" , lname = " + rs.getString("lname"));

System.out.print(" , age = " + rs.getInt("age")); }

/************************JDBC 修改*********************/

sql = "UPDATE Person_Tbl SET age=23 WHERE id = ?"; ps = con.prepareStatement(sql);

ps.setLong(1, 88);

int rows = ps.executeUpdate();

System.out.println(rows + " rows affected.");

 } catch (Exception e){

e.printStackTrace();

 } finally{

try{

//关闭数据库连接,以释放资源。

con.close(); 

} catch (Exception e1) {

       E1.printStackTrace();

} } }

本文来源:https://www.2haoxitong.net/k/doc/425e24ebe109581b6bd97f19227916888486b94a.html

《数据库面试.doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档

文档为doc格式