第一章:J2EE高级软件工程师面试题集

面试宝典 专栏收录该内容
50 篇文章 1 订阅

 

--JAVA基础部分

 

1、面向对象的特征有哪些方面  

1.抽象:

抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。抽象包括两个方面,一是过程抽象,二是数据抽象。

2.继承:

继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。

3.封装:

封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。

4. 多态性:

多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。

2、String是最基本的数据类型吗?

基本数据类型包括byte、int、char、long、float、double、boolean和short。

java.lang.String类是final类型的,因此不可以继承这个类、不能修改这个类。为了提高效率节省空间,我们应该用StringBuffer类

3、int 和 Integer 有什么区别

Java 提供两种不同的类型:引用类型和原始类型(或内置类型)。Int是java的原始数据类型,Integer是java为int提供的封装类。Java为每个原始类型提供了封装类。

原始类型封装类

boolean     Boolean

char        Character

byte        Byte

short       Short

int         Integer

long        Long

float       Float

double      Double

引用类型和原始类型的行为完全不同,并且它们具有不同的语义。引用类型和原始类型具有不同的特征和用法,它们包括:大小和速度问题,这种类型以哪种类型的数据结构存储,当引用类型和原始类型用作某个类的实例数据时所指定的缺省值。对象引用实例变量的缺省值为 null,而原始类型实例变量的缺省值与它们的类型有关。

4、String 和StringBuffer的区别

JAVA平台提供了两个类:String和StringBuffer,它们可以储存和操作字符串,即包含多个字符的字符数据。这个String类提供了数值不可改变的字符串。而这个StringBuffer类提供的字符串进行修改。当你知道字符数据要改变的时候你就可以使用StringBuffer。典型地,你可以使用StringBuffers来动态构造字符数据。String str1 = “java”;str1.replace(‘j’,’2’);//此后str1还是java,只是replace可以重新返回一个2ava!

5、运行时异常与一般异常有何异同?

异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。级别不一样...      

  一般异常都是Exception的子类,  运行期异常与System.err平级的

  一般异常值得捕获,运行期异常就管部了,无能为力地.

 

运行时异常与运行时环境有关,一般异常与原代码有关!

6、说出Servlet的生命周期,并说出Servlet和CGI的区别。

Servlet被服务器实例化后,容器运行其init方法,请求到达时运行其service方法,service方法自动派遣运行与请求对应的doXXX方法(doGet,doPost)等,当服务器决定将实例销毁的时候调用其destroy方法。

与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。

7、说出ArrayList,Vector, LinkedList的存储性能和特性

ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。

8、EJB是基于哪些技术实现的?并说出SessionBean和EntityBean的区别,StatefulBean和StatelessBean的区别。

    EJB包括Session Bean、Entity Bean、Message Driven Bean,基于JNDI、RMI、JAT等技术实现。

SessionBean在J2EE应用程序中被用来完成一些服务器端的业务操作,例如访问数据库、调用其他EJB组件。EntityBean被用来代表应用系统中用到的数据。

对于客户机,SessionBean是一种非持久性对象,它实现某些在服务器上运行的业务逻辑。

对于客户机,EntityBean是一种持久性对象,它代表一个存储在持久性存储器中的实体的对象视图,或是一个由现有企业应用程序实现的实体。

Session Bean 还可以再细分为 Stateful Session Bean 与 Stateless Session Bean ,这两种的 Session Bean都可以将系统逻辑放在 method之中执行,不同的是 Stateful Session Bean 可以记录呼叫者的状态,因此通常来说,一个使用者会有一个相对应的 Stateful Session Bean 的实体。Stateless Session Bean 虽然也是逻辑组件,但是他却不负责记录使用者状态,也就是说当使用者呼叫 Stateless Session Bean 的时候,EJB Container 并不会找寻特定的 Stateless Session Bean 的实体来执行这个 method。换言之,很可能数个使用者在执行某个 Stateless Session Bean 的 methods 时,会是同一个 Bean 的 Instance 在执行。从内存方面来看, Stateful Session Bean 与 Stateless Session Bean 比较, Stateful Session Bean 会消耗 J2EE Server 较多的内存,然而 Stateful Session Bean 的优势却在于他可以维持使用者的状态。

9、Collection 和 Collections的区别。

  Collection是集合类的上级接口,继承与他的接口主要有Set 和List.

Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。

10、&和&&的区别。

    &是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and)。

11、HashMap和Hashtable的区别。

    HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),由于非线程安全,效率上可能高于Hashtable。

HashMap允许将null作为一个entry的key或者value,而Hashtable不允许。

HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。

Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现。

最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。

Hashtable和HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差异。

12、final, finally, finalize的区别。

  final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。

finally是异常处理语句结构的一部分,表示总是执行。

finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。

13、sleep() 和 wait() 有什么区别?

    sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。

wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。

14、Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?

方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被"屏蔽"了。如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。Overloaded的方法是可以改变返回值的类型。

15、error和exception有什么区别?

error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。

    exception 表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况。

16、同步和异步有何异同,在什么情况下分别使用他们?举例说明。

如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。

当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。

17、abstract class和interface有什么区别?

声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,其类型是一个抽象类,并让它指向具体子类的一个实例。不能有抽象构造函数或抽象静态方法。Abstract 类的子类为它们父类中的所有抽象方法提供实现,否则它们也是抽象类为。取而代之,在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法。

接口(interface)是抽象类的变体。在接口中,所有方法都是抽象的。多继承性可通过实现这样的接口而获得。接口中的所有方法都是抽象的,没有一个有程序体。接口只可以定义static final成员变量。接口的实现与子类相似,除了该实现类不能从接口定义中继承行为。当类实现特殊接口时,它定义(即将程序体给予)所有这种接口的方法。然后,它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类,它允许使用接口名作为引用变量的类型。通常的动态联编将生效。引用可以转换到接口类型或从接口类型转换,instanceof 运算符可以用来决定某对象的类是否实现了接口。

18、heap和stack有什么区别。

栈是一种线形集合,其添加和删除元素的操作应在同一段完成。栈按照后进先出的方式进行处理。

堆是栈的一个组成元素

 

1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。

 

2. 栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外,栈数据可以共享,详见第3点。堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。

 

 

19、forward 和redirect的区别

forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容是从哪儿来的,所以它的地址栏中还是原来的地址。

    redirect就是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,一般来说浏览器会用刚才请求的所有参数重新请求,所以session,request参数都可以获取。

20、EJB与JAVA BEAN的区别?

Java Bean 是可复用的组件,对Java Bean并没有严格的规范,理论上讲,任何一个Java类都可以是一个Bean。但通常情况下,由于Java Bean是被容器所创建(如Tomcat)的,所以Java Bean应具有一个无参的构造器,另外,通常Java Bean还要实现Serializable接口用于实现Bean的持久性。Java Bean实际上相当于微软COM模型中的本地进程内COM组件,它是不能被跨进程访问的。EnterpriseJava Bean 相当于DCOM,即分布式组件。它是基于Java的远程方法调用(RMI)技术的,所以EJB可以被远程访问(跨进程、跨计算机)。但EJB必须被布署在诸如Webspere、WebLogic这样的容器中,EJB客户从不直接访问真正的EJB组件,而是通过其容器访问。EJB容器是EJB组件的代理,EJB组件由容器所创建和管理。客户通过容器来访问真正的EJB组件。

21、Static Nested Class 和 Inner Class的不同。

    Static Nested Class是被声明为静态(static)的内部类,它可以不依赖于外部类实例被实例化。而通常的内部类需要在外部类实例化后才能实例化。

22、JSP中动态INCLUDE与静态INCLUDE的区别?

动态INCLUDE用jsp:include动作实现 <jsp:include page="included.jsp"flush="true" />它总是会检查所含文件中的变化,适合用于包含动态页面,并且可以带参数。

静态INCLUDE用include伪码实现,定不会检查所含文件的变化,适用于包含静态页面<%@ include file="included.htm" %>

23、什么时候用assert。

    assertion(断言)在软件开发中是一种常用的调试方式,很多开发语言中都支持这种机制。在实现中,assertion就是在程序中的一条语句,它对一个boolean表达式进行检查,一个正确程序必须保证这个boolean表达式的值为true;如果该值为false,说明程序已经处于不正确的状态下,系统将给出警告或退出。一般来说,assertion用于保证程序最基本、关键的正确性。assertion检查通常在开发和测试时开启。为了提高性能,在软件发布后,assertion检查通常是关闭的。

24、GC是什么? 为什么要有GC?

  GC是垃圾收集的意思(GabageCollection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。

25、short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?

    short s1 = 1; s1 = s1 + 1; (s1+1运算结果是int型,需要强制转换类型)

short s1 = 1; s1+= 1;(可以正确编译)

26、Math.round(11.5)等於多少? Math.round(-11.5)等於多少?

    Math.round(11.5)==12

Math.round(-11.5)==-11

round方法返回与参数最接近的长整数,参数加1/2后求其floor.

27、String s = new String("xyz");创建了几个String Object?

    两个

28、设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1。写出程序。

以下程序使用内部类实现线程,对j增减的时候没有考虑顺序问题。

public classThreadTest1{

  private int j;

  public static void main(String args[]){

ThreadTest1tt=new ThreadTest1();

Inc inc=tt.newInc();

Dec dec=tt.newDec();

for(inti=0;i<2;i++){

Thread t=newThread(inc);

t.start();

t=newThread(dec);

t.start();

}

}

  private synchronized void inc(){

j++;

System.out.println(Thread.currentThread().getName()+"-inc:"+j);

  }

  private synchronized void dec(){

j--;

System.out.println(Thread.currentThread().getName()+"-dec:"+j);

  }

  class Inc implements Runnable{

public voidrun(){

for(inti=0;i<100;i++){

inc();

}

}

  }

  class Dec implements Runnable{

public voidrun(){

for(inti=0;i<100;i++){

dec();

}

 }

  }

}

29、Java有没有goto?

java中的保留字,现在没有在java中使用。

30、启动一个线程是用run()还是start()?

启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。run()方法可以产生必须退出的标志来停止一个线程。

 

31、EJB包括(SessionBean,EntityBean)说出他们的生命周期,及如何管理事务的?

SessionBean:Stateless Session Bean 的生命周期是由容器决定的,当客户机发出请求要建立一个Bean的实例时,EJB容器不一定要创建一个新的Bean的实例供客户机调用,而是随便找一个现有的实例提供给客户机。当客户机第一次调用一个Stateful Session Bean 时,容器必须立即在服务器中创建一个新的Bean实例,并关联到客户机上,以后此客户机调用Stateful Session Bean 的方法时容器会把调用分派到与此客户机相关联的Bean实例。

EntityBean:Entity Beans能存活相对较长的时间,并且状态是持续的。只要数据库中的数据存在,Entity beans就一直存活。而不是按照应用程序或者服务进程来说的。即使EJB容器崩溃了,Entity beans也是存活的。Entity Beans生命周期能够被容器或者 Beans自己管理。

EJB通过以下技术管理实务:对象管理组织(OMG)的OTS),Sun Microsystems的Transaction Service(JTS)、Java TransactionAPI(JTA),开发组(X/Open)的XA接口。

32、应用服务器有那些?

BEA WebLogicServer,IBM WebSphereApplication Server,Oracle9i Application Server,jBoss,Tomcat

33、给我一个你最常见到的runtime exception。

ArithmeticException,ArrayStoreException, BufferOverflowException,

 

 BufferUnderflowException, CannotRedoException,CannotUndoException,

 

ClassCastException,CMMException, ConcurrentModificationException, DOMException,

 

EmptyStackException,IllegalArgumentException, IllegalMonitorStateException,

 

IllegalPathStateException,IllegalStateException, ImagingOpException,

 

IndexOutOfBoundsException,MissingResourceException, NegativeArraySizeException,

 

NoSuchElementException,NullPointerException, ProfileDataException,

 

ProviderException,RasterFormatException, SecurityException, SystemException,

 

UndeclaredThrowableException,UnmodifiableSetException, UnsupportedOperationException

34、接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concreteclass)?

接口可以继承接口。抽象类可以实现(implements)接口,抽象类是否可继承实体类,但前提是实体类必须有明确的构造函数。

35、List, Set, Map是否继承自Collection接口?

    List,Set是,Map不是

36、说出数据连接池的工作机制是什么?

J2EE服务器启动时会建立一定数量的池连接,并一直维持不少于此数目的池连接。客户端程序需要连接时,池驱动程序会返回一个未使用的池连接并将其表记为忙。如果当前没有空闲连接,池驱动程序就新建一定数量的连接,新建连接的数量有配置参数决定。当使用的池连接调用完成后,池驱动程序将此连接表记为空闲,其他调用就可以使用这个连接。

37、abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized?

    都不能

38、数组有没有length()这个方法? String有没有length()这个方法?

数组没有length()这个方法,有length的属性。String有有length()这个方法。

39、Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?

Set里的元素是不能重复的,那么用iterator()方法来区分重复与否。equals()是判读两个Set是否相等。

    equals()和==方法决定引用值是否指向同一对象equals()在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值。

40、构造器Constructor是否可被override?

构造器Constructor不能被继承,因此不能重写Overriding,但可以被重载Overloading。

41、是否可以继承String类?

String类是final类故不可以继承。

42、swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上?

switch(expr1)中,expr1是一个整数表达式。因此传递给switch 和 case 语句的参数应该是 int、 short、 char 或者 byte。long,string 都不能作用于swtich。

43、try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行,在return前还是后?

会执行,在return前执行。

44、编程题: 用最有效率的方法算出2乘以8等於几?

2 << 3

45、两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?

不对,有相同的hash code。

46、当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?

是值传递。Java 编程语言只有值传递参数。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的内容可以在被调用的方法中改变,但对象的引用是永远不会改变的。

47、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?

不能,一个对象的一个synchronized方法只能由一个线程访问。

48、编程题: 写一个Singleton出来。

Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。

一般Singleton模式通常有几种种形式:

第一种形式: 定义一个类,它的构造函数为private的,它有一个static的private的该类变量,在类初始化时实例话,通过一个public的getInstance方法获取对它的引用,继而调用其中的方法。

public classSingleton {

privateSingleton(){}

      //在自己内部定义自己一个实例,是不是很奇怪?

      //注意这是private 只供内部调用

      private static Singletoninstance = new Singleton();

      //这里提供了一个供外部访问本class的静态方法,可以直接访问  

      public static SingletongetInstance() {

        return instance;   

      }

    }

    第二种形式:

public classSingleton {

  private static Singleton instance = null;

  public static synchronized Singleton getInstance() {

  //这个方法比上面有所改进,不用每次都进行生成对象,只是第一次     

  //使用时生成实例,提高了效率!

  if (instance==null)

    instance=new Singleton();

return instance;  }

}

其他形式:

定义一个类,它的构造函数为private的,所有方法为static的。

一般认为第一种形式要更加安全些

49、Java的接口和C++的虚类的相同和不同处。

由于Java不支持多继承,而有可能某个类或对象要使用分别在几个类或对象里面的方法或属性,现有的单继承机制就不能满足要求。与继承相比,接口有更高的灵活性,因为接口中没有任何实现代码。当一个类实现了接口以后,该类要实现接口里面所有的方法和属性,并且接口里面的属性在默认状态下面都是public static,所有方法默认情况下是public.一个类可以实现多个接口。

50、Java中的异常处理机制的简单原理和应用。

当JAVA程序违反了JAVA的语义规则时,JAVA虚拟机就会将发生的错误表示为一个异常。违反语义规则包括2种情况。一种是JAVA类库内置的语义检查。例如数组下标越界,会引发IndexOutOfBoundsException;访问null的对象时会引发NullPointerException。另一种情况就是JAVA允许程序员扩展这种语义检查,程序员可以创建自己的异常,并自由选择在何时用throw关键字引发异常。所有的异常都是java.lang.Thowable的子类。

51、垃圾回收的优点和原理。并考虑2种回收机制。

Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制,Java中的对象不再有"作用域"的概念,只有对象的引用才有"作用域"。垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收。

52、请说出你所知道的线程同步的方法。

wait():使一个线程处于等待状态,并且释放所持有的对象的lock。

sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException异常。

notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。

Allnotity():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。

53、你所知道的集合类都有哪些?主要方法?

最常用的集合类是 List 和 Map。 List 的具体实现包括 ArrayList 和 Vector,它们是可变大小的列表,比较适合构建、存储和操作任何类型对象的元素列表。 List 适用于按数值索引访问元素的情形。

Map 提供了一个更通用的元素存储方法。 Map 集合类用于存储元素对(称作"键"和"值"),其中每个键映射到一个值。

54、描述一下JVM加载class文件的原理机制?

JVM中类的装载是由ClassLoader和它的子类来实现的,Java ClassLoader 是一个重要的Java运行时系统组件。它负责在运行时查找和装入类文件的类。

55、char型变量中能不能存贮一个中文汉字?为什么?

能够定义成为一个中文的,因为java中以unicode编码,一个char占16个字节,所以放一个中文是没问题的

56、多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么?

多线程有两种实现方法,分别是继承Thread类与实现Runnable接口

同步的实现方面有两种,分别是synchronized,wait与notify

57、JSP的内置对象及方法。

request表示HttpServletRequest对象。它包含了有关浏览器请求的信息,并且提供了几个用于获取cookie, header, 和session数据的有用的方法。

    response表示HttpServletResponse对象,并提供了几个用于设置送回浏览器的响应的方法(如cookies,头信息等)

    out对象是javax.jsp.JspWriter的一个实例,并提供了几个方法使你能用于向浏览器回送输出结果。

    pageContext表示一个javax.servlet.jsp.PageContext对象。它是用于方便存取各种范围的名字空间、servlet相关的对象的API,并且包装了通用的servlet相关功能的方法。

    session表示一个请求的javax.servlet.http.HttpSession对象。Session可以存贮用户的状态信息

    applicaton 表示一个javax.servle.ServletContext对象。这有助于查找有关servlet引擎和servlet环境的信息

    config表示一个javax.servlet.ServletConfig对象。该对象用于存取servlet实例的初始化参数。

    page表示从该页面产生的一个servlet实例

58、线程的基本概念、线程的基本状态以及状态之间的关系

线程指在程序执行过程中,能够执行程序代码的一个执行单位,每个程序至少都有一个线程,也就是程序本身。

Java中的线程有四种状态分别是:运行、就绪、挂起、结束。

59、JSP的常用指令

 

isErrorPage(是否能使用Exception对象),isELIgnored(是否忽略表达式)

 

/"target="_blank">http://......"%>

60、什么情况下调用doGet()和doPost()?

Jsp页面中的form标签里的method属性为get时调用doGet(),为post时调用doPost()。

 

61、servlet的生命周期

web容器加载servlet,生命周期开始。通过调用servlet的init()方法进行servlet的初始化。通过调用service()方法实现,根据请求的不同调用不同的do***()方法。结束服务,web容器调用servlet的destroy()方法。

62、如何现实servlet的单线程模式

<%@ pageisThreadSafe="false"%>

63、页面间对象传递的方法

request,session,application,cookie等

64、JSP和Servlet有哪些相同点和不同点,他们之间的联系是什么?

JSP是Servlet技术的扩展,本质上是Servlet的简易方式,更强调应用的外表表达。JSP编译后是"类servlet"。Servlet和JSP最主要的不同点在于,Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来。而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp的文件。JSP侧重于视图,Servlet主要用于控制逻辑。

65、四种会话跟踪技术

会话作用域ServletsJSP 页面描述

page否是代表与一个页面相关的对象和属性。一个页面由一个编译好的 Java servlet 类(可以带有任何的 include 指令,但是没有 include 动作)表示。

request是是代表与 Web 客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个 Web 组件(由于 forward 指令和 include 动作的关系)

session是是代表与用于某个 Web 客户机的一个用户体验相关的对象和属性。一个 Web 会话可以也经常会跨越多个客户机请求

application是是代表与整个 Web 应用程序相关的对象和属性。这实质上是跨越整个 Web 应用程序,包括多个页面、请求和会话的一个全局作用域

66、Request对象的主要方法:

setAttribute(Stringname,Object):设置名字为name的request的参数值

getAttribute(Stringname):返回由name指定的属性值

getAttributeNames():返回request对象所有属性的名字集合,结果是一个枚举的实例

getCookies():返回客户端的所有Cookie对象,结果是一个Cookie数组

getCharacterEncoding():返回请求中的字符编码方式

getContentLength():返回请求的Body的长度

getHeader(Stringname):获得HTTP协议定义的文件头信息

getHeaders(Stringname):返回指定名字的requestHeader的所有值,结果是一个枚举的实例

getHeaderNames():返回所以request Header的名字,结果是一个枚举的实例

getInputStream():返回请求的输入流,用于获得请求中的数据

getMethod():获得客户端向服务器端传送数据的方法

getParameter(Stringname):获得客户端传送给服务器端的有name指定的参数值

getParameterNames():获得客户端传送给服务器端的所有参数的名字,结果是一个枚举的实例

getParameterValues(Stringname):获得有name指定的参数的所有值

getProtocol():获取客户端向服务器端传送数据所依据的协议名称

getQueryString():获得查询字符串

getRequestURI():获取发出请求字符串的客户端地址

getRemoteAddr():获取客户端的IP地址

getRemoteHost():获取客户端的名字

getSession([Booleancreate]):返回和请求相关Session

getServerName():获取服务器的名字

getServletPath():获取客户端所请求的脚本文件的路径

getServerPort():获取服务器的端口号

removeAttribute(Stringname):删除请求中的一个属性

67、J2EE是技术还是平台还是框架?

    J2EE本身是一个标准,一个为企业分布式应用的开发提供的标准平台。

    J2EE也是一个框架,包括JDBC、JNDI、RMI、JMS、EJB、JTA等技术。

68、我们在web应用开发过程中经常遇到输出某种编码的字符,如iso8859-1等,如何输出一个某种编码的字符串?

  Public String translate (String str) {

    String tempStr = "";

    try {

      tempStr = newString(str.getBytes("ISO-8859-1"), "GBK");

      tempStr = tempStr.trim();

    }

    catch (Exception e) {

      System.err.println(e.getMessage());

    }

    return tempStr;

  }

69、简述逻辑操作(&,|,^)与条件操作(&&,||)的区别。

区别主要答两点:a.条件操作只能操作布尔型的,而逻辑操作不仅可以操作布尔型,而且可以操作数值型

b.逻辑操作不会产生短路

70、XML文档定义有几种形式?它们之间有何本质区别?解析XML文档有哪几种方式?

a: 两种形式 dtd schema,b: 本质区别:schema本身是xml的,可以被XML解析器解析(这也是从DTD上发展schema的根本目的),c:有DOM,SAX,STAX等

    DOM:处理大型文件时其性能下降的非常厉害。这个问题是由DOM的树结构所造成的,这种结构占用的内存较多,而且DOM必须在解析文件之前把整个文档装入内存,适合对XML的随机访问

SAX:不现于DOM,SAX是事件驱动型的XML解析方式。它顺序读取XML文件,不需要一次全部装载整个文件。当遇到像文件开头,文档结束,或者标签开头与标签结束时,它会触发一个事件,用户通过在其回调事件中写入处理代码来处理XML文件,适合对XML的顺序访问

    STAX:Streaming API for XML (StAX)

71、简述synchronized和java.util.concurrent.locks.Lock的异同 ?

主要相同点:Lock能完成synchronized所实现的所有功能

主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放。

72、EJB的角色和三个对象

一个完整的基于EJB的分布式计算结构由六个角色组成,这六个角色可以由不同的开发商提供,每个角色所作的工作必须遵循Sun公司提供的EJB规范,以保证彼此之间的兼容性。这六个角色分别是EJB组件开发者(Enterprise Bean Provider) 、应用组合者(ApplicationAssembler)、部署者(Deployer)、EJB 服务器提供者(EJB Server Provider)、EJB 容器提供者(EJBContainer Provider)、系统管理员(System Administrator)

三个对象是Remote(Local)接口、Home(LocalHome)接口,Bean类

73、EJB容器提供的服务

主要提供声明周期管理、代码产生、持续性管理、安全、事务管理、锁和并发行管理等服务。

74、EJB规范规定EJB中禁止的操作有哪些?

    1.不能操作线程和线程API(线程API指非线程对象的方法如notify,wait等),2.不能操作awt,3.不能实现服务器功能,4.不能对静态属生存取,5.不能使用IO操作直接存取文件系统,6.不能加载本地库.,7.不能将this作为变量和返回,8.不能循环调用。

75、remote接口和home接口主要作用

remote接口定义了业务方法,用于EJB客户端调用业务方法。

home接口是EJB工厂用于创建和移除查找EJB实例

76、bean 实例的生命周期

对于Stateless Session Bean、Entity Bean、Message Driven Bean一般存在缓冲池管理,而对于Entity Bean和Statefull Session Bean存在Cache管理,通常包含创建实例,设置上下文、创建EJB Object(create)、业务方法调用、remove等过程,对于存在缓冲池管理的Bean,在create之后实例并不从内存清除,而是采用缓冲池调度机制不断重用实例,而对于存在Cache管理的Bean则通过激活和去激活机制保持Bean的状态并限制内存中实例数量。

77、EJB的激活机制

以Stateful Session Bean 为例:其Cache大小决定了内存中可以同时存在的Bean实例的数量,根据MRU或NRU算法,实例在激活和去激活状态之间迁移,激活机制是当客户端调用某个EJB实例业务方法时,如果对应EJBObject发现自己没有绑定对应的Bean实例则从其去激活Bean存储中(通过序列化机制存储实例)回复(激活)此实例。状态变迁前会调用对应的ejbActive和ejbPassivate方法。

78、EJB的几种类型

会话(Session)Bean ,实体(Entity)Bean 消息驱动的(Message Driven)Bean

会话Bean又可分为有状态(Stateful)和无状态(Stateless)两种

实体Bean可分为Bean管理的持续性(BMP)和容器管理的持续性(CMP)两种

79、客服端调用EJB对象的几个基本步骤

设置JNDI服务工厂以及JNDI服务地址系统属性,查找Home接口,从Home接口调用Create方法创建Remote接口,通过Remote接口调用其业务方法。

80、如何给weblogic指定大小的内存?

在启动Weblogic的脚本中(位于所在Domian对应服务器目录下的startServerName),增加set MEM_ARGS=-Xms32m -Xmx200m,可以调整最小内存为32M,最大200M

81、如何设定的weblogic的热启动模式(开发模式)与产品发布模式?

可以在管理控制台中修改对应服务器的启动模式为开发或产品模式之一。或者修改服务的启动文件或者commenv文件,增加set PRODUCTION_MODE=true。

82、如何启动时不需输入用户名与密码?

修改服务启动文件,增加 WLS_USER和WLS_PW项。也可以在boot.properties文件中增加加密过的用户名和密码.

83、在weblogic管理制台中对一个应用域(或者说是一个网站,Domain)进行jms及ejb或连接池等相关信息进行配置后,实际保存在什么文件中?

保存在此Domain的config.xml文件中,它是服务器的核心配置文件。

84、说说weblogic中一个Domain的缺省目录结构?比如要将一个简单的helloWorld.jsp放入何目录下,然的在浏览器上就可打入http://主机:端口号//helloword.jsp就可以看到运行结果了? 又比如这其中用到了一个自己写的javaBean该如何办?

Domain目录服务器目录applications,将应用目录放在此目录下将可以作为应用访问,如果是Web应用,应用目录需要满足Web应用目录要求,jsp文件可以直接放在应用目录中,Javabean需要放在应用目录的WEB-INF目录的classes目录中,设置服务器的缺省应用将可以实现在浏览器上无需输入应用名。

85、在weblogic中发布ejb需涉及到哪些配置文件

不同类型的EJB涉及的配置文件不同,都涉及到的配置文件包括ejb-jar.xml,weblogic-ejb-jar.xmlCMP实体Bean一般还需要weblogic-cmp-rdbms-jar.xml

86、如何在weblogic中进行ssl配置与客户端的认证配置或说说j2ee(标准)进行ssl的配置

缺省安装中使用DemoIdentity.jks和DemoTrust.jks  KeyStore实现SSL,需要配置服务器使用Enable SSL,配置其端口,在产品模式下需要从CA获取私有密钥和数字证书,创建identity和trust keystore,装载获得的密钥和数字证书。可以配置此SSL连接是单向还是双向的。

87、如何查看在weblogic中已经发布的EJB?

可以使用管理控制台,在它的Deployment中可以查看所有已发布的EJB

88、CORBA是什么?用途是什么?

CORBA 标准是公共对象请求代理结构(Common Object Request BrokerArchitecture),由对象管理组织 (ObjectManagement Group,缩写为 OMG)标准化。它的组成是接口定义语言(IDL), 语言绑定(binding:也译为联编)和允许应用程序间互操作的协议。 其目的为:用不同的程序设计语言书写在不同的进程中运行,为不同的操作系统开发。

89、说说你所熟悉或听说过的j2ee中的几种常用模式?及对设计模式的一些看法

  Session Facade Pattern:使用SessionBean访问EntityBean

Message FacadePattern:实现异步调用

EJB CommandPattern:使用CommandJavaBeans取代SessionBean,实现轻量级访问

Data TransferObject Factory:通过DTO Factory简化EntityBean数据提供特性

GenericAttribute Access:通过AttibuteAccess接口简化EntityBean数据提供特性

BusinessInterface:通过远程(本地)接口和Bean类实现相同接口规范业务逻辑一致性

EJB架构的设计好坏将直接影响系统的性能、可扩展性、可维护性、组件可重用性及开发效率。项目越复杂,项目队伍越庞大则越能体现良好设计的重要性。

90、说说在weblogic中开发消息Bean时的persistent与non-persisten的差别

persistent方式的MDB可以保证消息传递的可靠性,也就是如果EJB容器出现问题而JMS服务器依然会将消息在此MDB可用的时候发送过来,而non-persistent方式的消息将被丢弃。

 

 

 

java面试笔试题大汇总(4) [转]  

 

91、Servlet执行时一般实现哪几个方法?

public voidinit(ServletConfig config)

publicServletConfig getServletConfig()

public StringgetServletInfo()

public voidservice(ServletRequest request,ServletResponse response)

public voiddestroy()

92、j2ee常用的设计模式?说明工厂模式。

    Java中的23种设计模式:

Factory(工厂模式),     Builder(建造模式),       Factory Method(工厂方法模式),

Prototype(原始模型模式),Singleton(单例模式),   Facade(门面模式),

Adapter(适配器模式),   Bridge(桥梁模式),        Composite(合成模式),

Decorator(装饰模式),   Flyweight(享元模式),     Proxy(代理模式),

Command(命令模式),     Interpreter(解释器模式), Visitor(访问者模式),

Iterator(迭代子模式),  Mediator(调停者模式),    Memento(备忘录模式),

Observer(观察者模式),  State(状态模式),         Strategy(策略模式),

Template Method(模板方法模式), Chain Of Responsibleity(责任链模式)

工厂模式:工厂模式是一种经常被使用到的模式,根据工厂模式实现的类可以根据提供的数据生成一组类中某一个类的实例,通常这一组类有一个公共的抽象父类并且实现了相同的方法,但是这些方法针对不同的数据进行了不同的操作。首先需要定义一个基类,该类的子类通过不同的方法实现了基类中的方法。然后需要定义一个工厂类,工厂类可以根据条件生成不同的子类实例。当得到子类的实例后,开发人员可以调用基类中的方法而不必考虑到底返回的是哪一个子类的实例。

93、EJB需直接实现它的业务接口或Home接口吗,请简述理由。

远程接口和Home接口不需要直接实现,他们的实现代码是由服务器产生的,程序运行中对应实现类会作为对应接口类型的实例被使用。

94、排序都有哪几种方法?请列举。用JAVA实现一个快速排序。

    排序的方法有:插入排序(直接插入排序、希尔排序),交换排序(冒泡排序、快速排序),选择排序(直接选择排序、堆排序),归并排序,分配排序(箱排序、基数排序)

快速排序的伪代码。

/ /使用快速排序方法对a[ 0 :n- 1 ]排序

从a[ 0 :n- 1 ]中选择一个元素作为m i d d l e,该元素为支点

把余下的元素分割为两段left 和r i g h t,使得l e f t中的元素都小于等于支点,而right 中的元素都大于等于支点

递归地使用快速排序方法对left 进行排序

递归地使用快速排序方法对right 进行排序

所得结果为l e f t + m i d d l e + r i g h t

95、请对以下在J2EE中常用的名词进行解释(或简单描述)

web容器:给处于其中的应用程序组件(JSP,SERVLET)提供一个环境,使JSP,SERVLET直接更容器中的环境变量接**互,不必关注其它系统问题。主要有WEB服务器来实现。例如:TOMCAT,WEBLOGIC,WEBSPHERE等。该容器提供的接口严格遵守J2EE规范中的WEB APPLICATION 标准。我们把遵守以上标准的WEB服务器就叫做J2EE中的WEB容器。

EJB容器:Enterprise java bean 容器。更具有行业领域特色。他提供给运行在其中的组件EJB各种管理功能。只要满足J2EE规范的EJB放入该容器,马上就会被容器进行高效率的管理。并且可以通过现成的接口来获得系统级别的服务。例如邮件服务、事务管理。

JNDI:(Java Naming & Directory Interface)JAVA命名目录服务。主要提供的功能是:提供一个目录系统,让其它各地的应用程序在其上面留下自己的索引,从而满足快速查找和定位分布式应用程序的功能。

JMS:(Java Message Service)JAVA消息服务。主要实现各个应用程序之间的通讯。包括点对点和广播。

JTA:(Java Transaction API)JAVA事务服务。提供各种分布式事务服务。应用程序只需调用其提供的接口即可。

JAF:(Java Action FrameWork)JAVA安全认证框架。提供一些安全控制方面的框架。让开发者通过各种部署和自定义实现自己的个性安全控制策略。

RMI/IIOP:(Remote Method Invocation /internet对象请求中介协议)他们主要用于通过远程调用服务。例如,远程有一台计算机上运行一个程序,它提供股票分析服务,我们可以在本地计算机上实现对其直接调用。当然这是要通过一定的规范才能在异构的系统之间进行通信。RMI是JAVA特有的。

96、JAVA语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try块中可以抛出异常吗?

Java通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了良好的接口。在Java中,每个异常都是一个对象,它是Throwable类或其它子类的实例。当一个方法出现异常后便抛出一个异常对象,该对象中包含有异常信息,调用这个对象的方法可以捕获到这个异常并进行处理。Java的异常处理是通过5个关键词来实现的:try、catch、throw、throws和finally。一般情况下是用try来执行一段程序,如果出现异常,系统会抛出(throws)一个异常,这时候你可以通过它的类型来捕捉(catch)它,或最后(finally)由缺省处理器来处理。

用try来指定一块预防所有"异常"的程序。紧跟在try程序后面,应包含一个catch子句来指定你想要捕捉的"异常"的类型。

throw语句用来明确地抛出一个"异常"。

throws用来标明一个成员函数可能抛出的各种"异常"。

Finally为确保一段代码不管发生什么"异常"都被执行一段代码。

可以在一个成员函数调用的外面写一个try语句,在这个成员函数内部写另一个try语句保护其他代码。每当遇到一个try语句,"异常"的框架就放到堆栈上面,直到所有的try语句都完成。如果下一级的try语句没有对某种"异常"进行处理,堆栈就会展开,直到遇到有处理这种"异常"的try语句。

 

97、一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制?

可以。必须只有一个类名与文件名相同。

98、MVC的各个部分都有那些技术来实现?如何实现?

MVC是Model-View-Controller的简写。"Model" 代表的是应用的业务逻辑(通过JavaBean,EJB组件实现), "View" 是应用的表示面(由JSP页面产生),"Controller"是提供应用的处理过程控制(一般是一个Servlet),通过这种设计模型把应用逻辑,处理过程和显示逻辑分成不同的组件实现。这些组件可以进行交互和重用。

99、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用?

有两种实现方法,分别是继承Thread类与实现Runnable接口

用synchronized关键字修饰同步方法

反对使用stop(),是因为它不安全。它会解除由线程获取的所有锁定,而且如果对象处于一种不连贯状态,那么其他线程能在那种状态下检查和修改它们。结果很难检查出真正的问题所在。suspend()方法容易发生死锁。调用suspend()的时候,目标线程会停下来,但却仍然持有在这之前获得的锁定。此时,其他任何线程都不能访问锁定的资源,除非被"挂起"的线程恢复运行。对任何线程来说,如果它们想恢复目标线程,同时又试图使用任何一个锁定的资源,就会造成死锁。所以不应该使用suspend(),而应在自己的Thread类中置入一个标志,指出线程应该活动还是挂起。若标志指出线程应该挂起,便用wait()命其进入等待状态。若标志指出线程应当恢复,则用一个notify()重新启动线程。

100、java中有几种类型的流?JDK为每种类型的流提供了一些抽象类以供继承,请说出他们分别是哪些类?

字节流,字符流。字节流继承于InputStream OutputStream,字符流继承于InputStreamReader OutputStreamWriter。在java.io包中还有许多其他的流,主要是为了提高性能和使用方便。

101、java中会存在内存泄漏吗,请简单描述。

会。如:int i,i2;  return (i-i2);   //when i为足够大的正数,i2为足够大的负数。结果会造成溢位,导致错误。

102、java中实现多态的机制是什么?

方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。

103、垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?

对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是"可达的",哪些对象是"不可达的"。当GC确定一些对象为"不可达"时,GC就有责任回收这些内存空间。可以。程序员可以手动执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。

104、静态变量和实例变量的区别?

static i = 10;//常量

   class A a; a.i =10;//可变

105、什么是java序列化,如何实现java序列化?

序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。

序列化的实现:将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。

106、是否可以从一个static方法内部发出对非static方法的调用?

不可以,如果其中包含对象的method();不能保证对象初始化.

107、写clone()方法时,通常都有一行代码,是什么?

Clone 有缺省行为,super.clone();他负责产生正确大小的空间,并逐位复制。

108、在JAVA中,如何跳出当前的多重嵌套循环?

用break; return 方法。

109、List、Map、Set三个接口,存取元素时,各有什么特点?

List 以特定次序来持有元素,可有重复元素。Set 无法拥有重复元素,内部排序。Map 保存key-value值,value可多值。

110、J2EE是什么?

J2EE是Sun公司提出的多层(multi-diered),分布式(distributed),基于组件(component-base)的企业级应用模型(enterpriese application model).在这样的一个应用系统中,可按照功能划分为不同的组件,这些组件又可在不同计算机上,并且处于相应的层次(tier)中。所属层次包括客户层(clietn tier)组件,web层和组件,Business层和组件,企业信息系统(EIS)层。

111、UML方面

标准建模语言UML。用例图,静态图(包括类图、对象图和包图),行为图,交互图(顺序图,合作图),实现图。

112、说出一些常用的类,包,接口,请各举5个

常用的类:BufferedReader BufferedWriter  FileReader  FileWirter String  Integer

常用的包:java.lang  java.awt  java.io java.util  java.sql

常用的接口:Remote  List  Map Document  NodeList

113、开发中都用到了那些设计模式?用在什么场合?

每个模式都描述了一个在我们的环境中不断出现的问题,然后描述了该问题的解决方案的核心。通过这种方式,你可以无数次地使用那些已有的解决方案,无需在重复相同的工作。主要用到了MVC的设计模式。用来开发JSP/Servlet或者J2EE的相关应用。简单工厂模式等。

114、jsp有哪些动作?作用分别是什么?

JSP共有以下6种基本动作 jsp:include:在页面被请求的时候引入一个文件。 jsp:useBean:寻找或者实例化一个JavaBean。 jsp:setProperty:设置JavaBean的属性。 jsp:getProperty:输出某个JavaBean的属性。 jsp:forward:把请求转到一个新的页面。 jsp:plugin:根据浏览器类型为Java插件生成OBJECT或EMBED标记。

115、Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)?

可以继承其他类或完成其他接口,在swing编程中常用此方式。

116、应用服务器与WEB SERVER的区别?

应用服务器:Weblogic、Tomcat、Jboss

WEB SERVER:IIS、 Apache

117、BS与CS的联系与区别。

C/S是Client/Server的缩写。服务器通常采用高性能的PC、工作站或小型机,并采用大型数据库系统,如Oracle、Sybase、Informix或 SQL Server。客户端需要安装专用的客户端软件。

B/S是Brower/Server的缩写,客户机上只要安装一个浏览器(Browser),如Netscape Navigator或Internet Explorer,服务器安装Oracle、Sybase、Informix或 SQL Server等数据库。在这种结构下,用户界面完全通过WWW浏览器实现,一部分事务逻辑在前端实现,但是主要事务逻辑在服务器端实现。浏览器通过Web Server 同数据库进行数据交互。

C/S 与 B/S 区别:

1.硬件环境不同:

  C/S 一般建立在专用的网络上, 小范围里的网络环境, 局域网之间再通过专门服务器提供连接和数据交换服务.

  B/S 建立在广域网之上的, 不必是专门的网络硬件环境,例与电话上网, 租用设备. 信息自己管理. 有比C/S更强的适应范围, 一般只要有操作系统和浏览器就行

2.对安全要求不同

  C/S 一般面向相对固定的用户群, 对信息安全的控制能力很强. 一般高度机密的信息系统采用C/S 结构适宜. 可以通过B/S发布部分可公开信息.

  B/S 建立在广域网之上, 对安全的控制能力相对弱, 可能面向不可知的用户。

3.对程序架构不同

  C/S 程序可以更加注重流程, 可以对权限多层次校验, 对系统运行速度可以较少考虑.

  B/S 对安全以及访问速度的多重的考虑, 建立在需要更加优化的基础之上. 比C/S有更高的要求 B/S结构的程序架构是发展的趋势, 从MS的.Net系列的BizTalk 2000 Exchange 2000等, 全面支持网络的构件搭建的系统. SUN 和IBM推的JavaBean 构件技术等,使 B/S更加成熟.

4.软件重用不同

  C/S 程序可以不可避免的整体性考虑, 构件的重用性不如在B/S要求下的构件的重用性好.

  B/S 对的多重结构,要求构件相对独立的功能. 能够相对较好的重用.就入买来的餐桌可以再利用,而不是做在墙上的石头桌子

5.系统维护不同 

  C/S 程序由于整体性, 必须整体考察, 处理出现的问题以及系统升级. 升级难. 可能是再做一个全新的系统

  B/S 构件组成,方面构件个别的更换,实现系统的无缝升级. 系统维护开销减到最小.用户从网上自己下载安装就可以实现升级.

6.处理问题不同

  C/S 程序可以处理用户面固定, 并且在相同区域, 安全要求高需求, 与操作系统相关. 应该都是相同的系统

  B/S 建立在广域网上, 面向不同的用户群, 分散地域, 这是C/S无法作到的. 与操作系统平台关系最小.

7.用户接口不同

  C/S 多是建立的Window平台上,表现方法有限,对程序员普遍要求较高

  B/S 建立在浏览器上, 有更加丰富和生动的表现方式与用户交流. 并且大部分难度减低,减低开发成本.

8.信息流不同

  C/S 程序一般是典型的中央集权的机械式处理,交互性相对低

  B/S 信息流向可变化, B-B B-CB-G等信息、流向的变化, 更像交易中心。

118、LINUX下线程,GDI类的解释。

LINUX实现的就是基于核心轻量级进程的"一对一"线程模型,一个线程实体对应一个核心轻量级进程,而线程之间的管理在核外函数库中实现。

GDI类为图像设备编程接口类库。

119、STRUTS的应用(如STRUTS架构)

Struts是采用Java Servlet/JavaServer Pages技术,开发Web应用程序的开放源码的framework。 采用Struts能开发出基于MVC(Model-View-Controller)设计模式的应用构架。 Struts有如下的主要功能: 一.包含一个controller servlet,能将用户的请求发送到相应的Action对象。 二.JSP自由tag库,并且在controllerservlet中提供关联支持,帮助开发员创建交互式表单应用。 三.提供了一系列实用对象:XML处理、通过Javareflection APIs自动处理JavaBeans属性、国际化的提示和消息。

120、Jdo是什么?

JDO是Java对象持久化的新的规范,为java data object的简称,也是一个用于存取某种数据仓库中的对象的标准化API。JDO提供了透明的对象存储,因此对开发人员来说,存储数据对象完全不需要额外的代码(如JDBC API的使用)。这些繁琐的例行工作已经转移到JDO产品提供商身上,使开发人员解脱出来,从而集中时间和精力在业务逻辑上。另外,JDO很灵活,因为它可以在任何数据底层上运行。JDBC只是面向关系数据库(RDBMS)JDO更通用,提供到任何数据底层的存储功能,比如关系数据库、文件、XML以及对象数据库(ODBMS)等等,使得应用可移植性更强。

121、内部类可以引用他包含类的成员吗?有没有什么限制?

一个内部类对象可以访问创建它的外部类对象的内容

122、WEB SERVICE名词解释。JSWDL开发包的介绍。JAXP、JAXM的解释。SOAP、UDDI,WSDL解释。

Web ServiceWebService是基于网络的、分布式的模块化组件,它执行特定的任务,遵守具体的技术规范,这些规范使得Web Service能与其他兼容的组件进行互操作。

JAXP(Java APIfor XML Parsing) 定义了在Java中使用DOM, SAX, XSLT的通用的接口。这样在你的程序中你只要使用这些通用的接口,当你需要改变具体的实现时候也不需要修改代码。

JAXM(Java APIfor XML Messaging) 是为SOAP通信提供访问方法和传输机制的API。

WSDL是一种 XML 格式,用于将网络服务描述为一组端点,这些端点对包含面向文档信息或面向过程信息的消息进行操作。这种格式首先对操作和消息进行抽象描述,然后将其绑定到具体的网络协议和消息格式上以定义端点。相关的具体端点即组合成为抽象端点(服务)。

SOAP即简单对象访问协议(Simple Object Access Protocol),它是用于交换XML编码信息的轻量级协议。

UDDI 的目的是为电子商务建立标准;UDDI是一套基于Web的、分布式的、为Web Service提供的、信息注册中心的实现标准规范,同时也包含一组使企业能将自身提供的Web Service注册,以使别的企业能够发现的访问协议的实现标准。

 

123、JSP页面是如何被执行的?JSP执行效率比Servlet低吗?

 

当客户端向一个JSP页面发出请求时,WebContainer将JSP转化成Servlet的源代码(只在第一次请求时),然后编译转化后的Servlet并加载到内存中执行,执行的结果Response到客户端。

JSP只在第一次执行的时候会转化为Servlet,以后每次执行Web容器都是直接执行编译后的Servlet,所以JSP和Servlet只是在第一次执行的时候不一样,JSP慢一点,以后的执行都是相同的。

 

124、JSP如何处理运行时异常(run-time)exceptions?

 

可以使用页面的errorPage属性捕获没有处理的运行时异常,然后自动转向到一个错误处理页面,代码如下:

<%@ pageerrorPage=”error.jsp” %>

如果在页面请求时出现运行时异常是,以上代码会把页面转向到JSP页面error.jsp,在error.jsp里面,可以通过以下代码定义这个页面是错误处理页:

 

<%@pageisErrorPage=”true” %>

 

这样描述错误信息的Throwable对象就可以在error.jsp页面里面访问到。

 

125、如果jsp表单元素的值为空,如何避免null出现在页面上?

 

可以写一个简单的函数对空值进行处理,判断值是否为空,如果是空就返回空字符串。实例代码如下:

<%!

Stringblanknull(String s){

return (s ==null) ? “” : s;

}

%>

在你的JSP里面,可以使用以上函数输出文本框或者其他页面元素的值,实例代码如下:

<inputtype=”text” name=”shoesize” value=”<%=blanknull(shoesize)% >”>

 

126、如何避免JSP页面自动生成session对象?为什么要这么做?

 

在默认情况下,在对一个JSP页面发出请求时,如果session还没有建立,JSP页面会自动为请求建立一个session对象,但是session是比较消耗资源的,如果没必要保持和使用session,就不应该创建session, 例如一些只是用来宣传产品的网站,往往没必要使用session来保存信息,可以使用jsp页面指令session=”false”来避免JSP页面为每个请求都自动创建session.实例代码如下:

 

<%@pagesession=”false”>

 

127、在servlets和JSP之间能共享session对象吗?

 

当然可以,

HttpSessionsession = request.getSession(true);

session.putValue(”variable”,”value”);

 

128、Servlet都有哪些方法?主要作用是什么?

 

HttpServlet 类包含 init() 、destroy() 、 service() 等方法。其中init() 和 destroy() 方法是继承的。

(1) init() 方法

在 Servlet 的生命期中,仅执行一次 init() 方法。它是在服务器装入 Servlet 时执行的。 可以配置服务器,以在启动服务器或客户机首次访问Servlet 时装入 Servlet 。无论有多少客户机访问 Servlet ,都不会重复执行 init() 。

缺省的 init() 方法通常是符合要求的,但也可以用定制init() 方法来覆盖它,典型的是管理服务器端资源。例如,可能编写一个定制 init() 来只用于一次装入 GIF 图像,改进 Servlet 返回 GIF 图像和含有多个客户机请求的性能。另一个示例是初始化数据库连接。缺省的init() 方法设置了 Servlet 的初始化参数,并用它的 ServletConfig 对象参数来启动配置, 因此所有覆盖 init() 方法的 Servlet 应调用 super.init() 以确保仍然执行这些任务。在调用 service() 方法之前,应确保已完成了 init() 方法。

(2) service() 方法

service() 方法是 Servlet 的核心。每当一个客户请求一个 HttpServlet 对象,该对象的 service() 方法就要被调用,而且传递给这个方法一个“请求”( ServletRequest)对象和一个“响应”( ServletResponse )对象作为参数。 在 HttpServlet 中已存在 service() 方法。缺省的服务功能是调用与 HTTP 请求的方法相应的 do 功能。例如, 如果 HTTP 请求方法为 GET ,则缺省情况下就调用 doGet()。 Servlet 应该为 Servlet 支持的 HTTP 方法覆盖 do 功能。因为HttpServlet.service()方法会检查请求方法是否调用了适当的处理方法,不必要覆盖service() 方法。只需覆盖相应的 do 方法就可以了。

= 当一个客户通过 HTML 表单发出一个 HTTP POST请求时, doPost ()方法被调用。 与 POST 请求相关的参数作为一个单独的 HTTP 请求从浏览器发送到服务器。当需要修改服务器端的数据时,应该使用doPost() 方法。

= 当一个客户通过 HTML 表单发出一个 HTTP GET 请求或直接请求一个 URL 时, doGet() 方法被调用。 与 GET 请求相关的参数添加到 URL 的后面,并与这个请求一起发送。当不会修改服务器端的数据时,应该使用 doGet() 方法。

Servlet 的响应可以是下列几种类型:

一个输出流,浏览器根据它的内容类型(如 text/HTML )进行解释。

一个 HTTP 错误响应 , 重定向到另一个 URL 、 servlet 、 JSP。

(3) destroy() 方法

destroy() 方法仅执行一次,即在服务器停止且卸装 Servlet 时执行该方法。典型的,将 Servlet 作为服务器进程的一部分来关闭。缺省的 destroy() 方法通常是符合要求的,但也可以覆盖它,典型的是管理服务器端资源。例如,如果 Servlet 在运行时会累计统计数据,则可以编写一个 destroy() 方法,该方法用于在未装入 Servlet 时将统计数字保存在文件中。另一个示例是关闭数据库连接。

当服务器卸装 Servlet 时,将在所有 service()方法调用完成后,或在指定的时间间隔过后调用 destroy() 方法。一个 Servlet 在运行 service() 方法时可能会产生其它的线程,因此请确认在调用 destroy() 方法时,这些线程已终止或完成。

(4)GetServletConfig()方法

GetServletConfig()方法返回一个 ServletConfig 对象,该对象用来返回初始化参数和 ServletContext 。 ServletContext 接口提供有关 servlet 的环境信息。

(5)GetServletInfo()方法

GetServletInfo ()方法是一个可选的方法,它提供有关 servlet 的信息,如作者、版本、版权。

当服务器调用 sevlet 的 Service ()、 doGet ()和 doPost ()这三个方法时,均需要 “请求”和“响应”对象作为参数。“请求”对象提供有关请求的信息,而“响应”对象提供了一个将响应信息返回给浏览器的一个通信途径。 javax.servlet 软件包中的相关类为 ServletResponse 和 ServletRequest ,而 javax.servlet.http 软件包中的相关类为 HttpServletRequest 和 HttpServletResponse 。 Servlet 通过这些对象与服务器通信并最终与客户机通信。 Servlet 能通过调用“请求”对象的方法获知客户机环境,服务器环境的信息和所有由客户机提供的信息。 Servlet 可以调用“响应”对象的方法发送响应,该响应是准备发回客户机的。

 

129、Java Servlet的主要功能和作用是什么?

 

Servlet 通过创建一个框架来扩展服务器的能力,以提供在 Web 上进行请求和响应服务。当客户机发送请求至服务器时,服务器可以将请求信息发送给 Servlet ,并让 Servlet 建立起服务器返回给客户机的响应。当启动 Web 服务器或客户机第一次请求服务时,可以自动装入 Servlet 。装入后, Servlet 继续运行直到其它客户机发出请求。 Servlet 的功能涉及范围很广。例如, Servlet 可完成如下功能:

(1) 创建并返回一个包含基于客户请求性质的动态内容的完整的 HTML 页面。

(2) 创建可嵌入到现有 HTML 页面中的一部分 HTML 页面( HTML 片段)。

(3) 与其它服务器资源(包括数据库和基于 Java 的应用程序)进行通信。

(4) 用多个客户机处理连接,接收多个客户机的输入,并将结果广播到多个客户机上。例如, Servlet可

以是多参与者的游戏服务器。

(5) 当允许在单连接方式下传送数据的情况下,在浏览器上打开服务器至 applet 的新连接,并将该连

接保持在打开状态。当允许客户机和服务器简单、高效地执行会话的情况下, applet 也可以启动客户浏览器和服务器之间的连接。可以通过定制协议或标准(如 IIOP )进行通信。

(6) 对特殊的处理采用 MIME 类型过滤数据,例如图像转换和服务器端包括( SSI )。

(7) 将定制的处理提供给所有服务器的标准例行程序。例如, Servlet 可以修改如何认证用户。

 

130、Request对象的主要方法有哪些?

 

setAttribute(Stringname,Object):设置名字为name的request的参数值

getAttribute(Stringname):返回由name指定的属性值

getAttributeNames():返回request对象所有属性的名字集合,结果是一个枚举的实例

getCookies():返回客户端的所有Cookie对象,结果是一个Cookie数组

getCharacterEncoding():返回请求中的字符编码方式

getContentLength():返回请求的Body的长度

实例

getInputStream():返回请求的输入流,用于获得请求中的数据

getMethod():获得客户端向服务器端传送数据的方法

getParameter(Stringname):获得客户端传送给服务器端的有name指定的参数值

getParameterNames():获得客户端传送给服务器端的所有参数的名字,结果是一个枚举的实例

getParameterValues(Stringname):获得有name指定的参数的所有值

getProtocol():获取客户端向服务器端传送数据所依据的协议名称

getQueryString():获得查询字符串

getRequestURI():获取发出请求字符串的客户端地址

getRemoteAddr():获取客户端的IP地址

getRemoteHost():获取客户端的名字

getSession([Booleancreate]):返回和请求相关Session

getServerName():获取服务器的名字

getServletPath():获取客户端所请求的脚本文件的路径

getServerPort():获取服务器的端口号

removeAttribute(Stringname):删除请求中的一个属性

 

131、使用JSP连接到数据库连接缓冲池的最好方法是什么?

 

1.使用JDBC2。0中带有此服务的Driver

2.使用提供有此服务的Application server

3.自己写

 

132、在JSP中如何写文本文件?

 

使用PrintWriter对象,如:

<%@ pageimport=”java.io.*” %>

<%

String str =“print me”;

StringnameOfTextFile = “/usr/anil/imp.txt”;

try {

PrintWriter pw =new PrintWriter(new FileOutputStream(nameOfTextFile));

pw.println(str);

pw.close();

}catch(IOException e) {

out.println(e.getMessage());

}

%>

 

133、JSP的缺点?

 

1.对JAVA程序进行调试没有好东东

2.因大多数的servlet引擎不支持connectionpooling

3.Servlet引擎没有标准

4.JSP与其它脚本语言的交互

 

134、在JSP中如何删除一个COOKIE?

 

<%

CookiekillMyCookie = new Cookie(”mycookie”, null);

killMyCookie.setMaxAge(0);

killMyCookie.setPath(”/”);

response.addCookie(killMyCookie);

%>

 

135、如何现实servlet的单线程模式?

 

<%@pageisThreadSafe=”false”%>

 

136、说出Servlet和CGI的区别?

与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。

 

137、Servlet的生命周期?

 

Servlet是一种可以 在Servlet容器中运行的组件,那么理所当然就应该有一个从创建到销毁的过程,这个过程我们可以称之为Servlet生命周期。Servlet的生命周期可以分为加载、实例化、初始化、处理客户请求和卸载五个阶段,体现在方法上主要是init()、service()和destroy()三个方法。生命周期的具体说明如下:

 

· Servlet容器完成加载Servlet类和实例化一个Servlet对象

 

· init()方法完成初始化工作,该方法由Servlet容器调用完成

 

· service()方法处理客户端请求,并返回响应结果

 

· destroy()方法在Servlet容器卸载Servlet之前被调用,释放一些资源

 

138、介绍一下javax.servlet.Servlet接口及其主要方法?

 

Servlet接口的主要作用是提供Servlet生命周期的init()、service()和destroy()方法。

servlet接口中的主要方法有:

voidinit(ServletConfit config)throws ServletException     在servlet被载入后和实施服务前由servlet引擎进行一次性调用。如果init()产生溢出UnavailableException,则 servle退出服务。

ServletConfiggetServletConfig()     返回传递到servlet的init()方法的ServletConfig对象

voidservice(ServletRequest request, ServletResponseresponse)throwsServletException,IOException    处理request对象中描述的请求,使用response对象返回请求结果

StringgetServletInfo()         返回描述servlet的一个字符串

voiddestory()         当servlet将要卸载时由servlet引擎调用,销毁Servlet实例。

 

139、HttpServlet类中的主要方法都有哪些?各自的作用是什么?

 

HttpServlet的主要方法有 doGet, doPost, doPut, doDelete,doTrace等等

 

VoiddoGet(HttpServletRequestrequest,HttpServletResponse response)throwsServletException,IOException     由servlet引擎调用用处理一个HTTP GET请求。输入参数、HTTP头标和输入流可从request对象、response头标和response对象的输出流中获得。

VoiddoPost(HttpServletRequest request,HttpServletResponseresponse)throwsServletException,IOException    由servlet引擎调用用处理一个HTTP POST请求。输入参数、HTTP头标和输入流可从request对象、response头标和response对象的输出流中获得。

VoiddoPut(HttpServletRequest request,HttpServletResponseresponse)throwsServletException,IOException    由servlet引擎调用用处理一个HTTP PUT请求。本方法中请求URI指出被载入的文件位置。

VoiddoDelete(HttpServletRequest request,HttpServletResponseresponse)throwsServletException,IOException    由servlet引擎调用用处理一个HTTP DELETE请求。请求URI指出资源被删除。

VoiddoOptions(HttpServletRequest request,HttpServletResponseresponse)throwsServletException,IOException    由servlet引擎调用用处理一个HTTP OPTIONS请求。返回一个Allow响应头标表明此servlet支持的HTTP方法。一个servlet不需要覆盖此方法,因为 HttpServlet方法已经实现规范所需的功能。

VoiddoTrace(HttpServletRequest request,HttpServletResponseresponse)throwsServletException,IOException    由servlet引擎调用用处理一个HTTP TRACE请求。使得请求头标被反馈成响应关标。一个servlet不需要覆盖此方法,因为HttpServlet方法已经实现HTTP规范所需的功能。

Voidservice(HttpServletRequest request,HttpServletResponseresponse)throwsServletException,IOException    Service(Requestrequest,Response response)调用的一个立即方法,带有指定HTTP请求和响应。此方法实际上将请求导向doGet()、doPost()等等。不应该覆盖此方法。

Voidservice(Request request,Response response)throwsServletException,IOException     将请求和响应对象置入其指定的HTTP子类,并调用指定HTTP的service()方法。

 

140、XML文档定义有几种形式?它们之间有何本质区别?解析XML文档有哪几种方式?

 

a: 两种形式 dtd schema,

 

b: 本质区别:schema本身是xml的,可以被XML解析器解析(这也是从DTD上发展schema的根本目的)。

 

c:有DOM,SAX,STAX等

DOM:处理大型文件时其性能下降的非常厉害。这个问题是由DOM的树结构所造成的,这种结构占用的内存较多,而且DOM必须在解析文件之前把整个文档装入内存,适合对XML的随机访问;SAX:不现于DOM,SAX是事件驱动型的XML解析方式。它顺序读取XML文件,不需要一次全部装载整个文件。当遇到像文件开头,文档结束,或者标

 

签开头与标签结束时,它会触发一个事件,用户通过在其回调事件中写入处理代码来处理XML文件,适合对XML的顺序访问

STAX:StreamingAPI for XML (StAX)

 

141、你在项目中用到了xml技术的哪些方面?如何实现的?

 

用到了数据存贮,信息配置两方面。在做数据交换平台时,将不能数据源的数据组装成XML文件,然后将XML文件压缩打包加密后通过网络传送给接收者,接收解密与解压缩后再同XML文件中还原相关信息进行处理。在做软件配置时,利用XML可以很方便的进行,软件的各种配置参数都存贮在XML文件中。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

第二章:J2EE高级软件工程师面试题

 

----JAVA高级部分

 

ajax面试题部分

 

1、介绍一下Prototype的$()函数,$F()函数,$A()函数都是什么作用?

 

$() 方法是在DOM中使用过于频繁的document.getElementById() 方法的一个便利的简写,就像这个DOM方法一样,这个方法返回参数传入的id的那个元素。

 

$F()函数是另一个大收欢迎的“快捷键”,它能用于返回任何表单输入控件的值,比如textbox,drop-down list。这个方法也能用元素id或元素本身做为参数。

 

$A()函数能把它接收到的单个的参数转换成一个Array对象。

 

2、介绍一下XMLHttpRequest对象

 

通过XMLHttpRequest对象,Web开发人员可以在页面加载以后进行页面的局部更新。

 

AJAX开始流行始于Google在2005年使用的”GoogleSuggest”。

 

“Google Suggest”就是使用XMLHttpRequest对象来创建动态的Web接口:

 

当用户开始输入google的搜索框,Javascript发送用户输入的字符到服务器,然后服务器返回一个建议列表。

 

XMLHttpRequest对象在IE5.0+, Safari 1.2, Mozilla1.0/Firefox,Opera 8+ 和NetScapt7 开始被支持。

 

3、AJAX应用和传统Web应用有什么不同?

 

在传统的Javascript编程中,如果想得到服务器端数据库或文件上的信息,或者发送客户端信息到服务器,需要建立一个HTML form然后GET或者POST数据到服务器端。用户需要点击”Submit”按钮来发送或者接受数据信息,然后等待服务器响应请求,页面重新加载。

 

因为服务器每次都会返回一个新的页面,所以传统的web应用有可能很慢而且用户交互不友好。

 

使用AJAX技术,就可以使Javascript通过XMLHttpRequest对象直接与服务器进行交互。

 

通过HTTPRequest, 一个web页面可以发送一个请求到web服务器并且接受web服务器返回的信息(不用重新加载页面),展示给用户的还是通一个页面,用户感觉页面刷新,也看不到到Javascript后台进行的发送请求和接受响应。

 

4、AJAX的全称是什么? 介绍一下AJAX?

 

AJAX的全称是Asynchronous JavaScript And XML.

 

AJAX是2005年由Google发起并流行起来的编程方法, AJAX不是一个新的编程语言,但是它是一个使用已有标准的新的编程技术。

 

使用AJAX可以创建更好,更快,更用户界面友好的Web应用。

 

AJAX技术基于Javascript和HTTPRequest.

 

5、Ajax请求总共有多少种Callback?

 

Ajax请求总共有八种Callback

 

onSuccess

onFailure

onUninitialized

onLoading

onLoaded

onInteractive

onComplete

onException

6、Javascript如何发送一个Ajax请求?

 

代码:

 

newAjax.Request(’/your_url’),

 

{

 

method : ‘get’,

 

onSuccess:function(transport){

 

var response=transport.responseText || “no response text”;

 

alert(”Success!”);

 

} ,

 

onFailure:function(){ alert(’failure’)}

 

});

 

7、AJAX都有哪些有点和缺点?

 

1、最大的一点是页面无刷新,用户的体验非常好。

2、使用异步方式与服务器通信,具有更加迅速的响应能力。

3、可以把以前一些服务器负担的工作转嫁到客户端,利用客户端闲置的能力来处理,减轻服务器和带宽的负担,节约空间和宽带租用成本。并且减轻服务器的负担,ajax的原则是“按需取数据”,可以最大程度的减少冗余请求,和响应对服务器造成的负担。

4、基于标准化的并被广泛支持的技术,不需要下载插件或者小程序。

ajax的缺点

1、ajax不支持浏览器back按钮。

2、安全问题 AJAX暴露了与服务器交互的细节。

3、对搜索引擎的支持比较弱。

4、破坏了程序的异常机制。

5、不容易调试。

 

8、Ajax主要包含了哪些技术?

 

Ajax(Asynchronous JavaScript + XML)的定义

基于web标准(standards-basedpresentation)XHTML+CSS的表示;

使用 DOM(Document ObjectModel)进行动态显示及交互;

使用 XML 和 XSLT 进行数据交换及相关操作;

使用 XMLHttpRequest 进行异步数据查询、检索;

使用 JavaScript 将所有的东西绑定在一起。英文参见Ajax的提出者JesseJamesGarrett的原文,原文题目(Ajax: A New Approach to WebApplications)。

类似于DHTML或LAMP,AJAX不是指一种单一的技术,而是有机地利用了一系列相关的技术。事实上,一些基于AJAX的“派生/合成”式(derivative/composite)的技术正在出现,如“AFLAX”。

AJAX的应用使用支持以上技术的web浏览器作为运行平台。这些浏览器目前包括:Mozilla、Firefox、Internet Explorer、Opera、Konqueror及Safari。但是Opera不支持XSL格式对象,也不支持XSLT。

 

9、主要的Ajax框架都有什么?

 

* Dojo(dojotoolkit.org);

* Prototype和Scriptaculous (www.prototypejs.org和script.aculo.us);

* Direct WebReporting (getahead.org/dwr);

* Yahoo! UserInterface Library(developer.yahoo.com/yui);

* Google WebToolkit (code.google.com/webtoolkit)。

*JQuery

 

10、介绍一下XMLHttpRequest对象的常用方法和属性?

 

open(“method”,”URL”)建立对服务器的调用,第一个参数是HTTP请求    方式可以为GET,POST或任何服务器所支持的您想调用的方式。

第二个参数是请求页面的URL。

send()方法,发送具体请求

abort()方法,停止当前请求

readyState属性   请求的状态 有5个可取值 0=未初始化 ,1=正在加载

2=以加载,3=交互中,4=完成

responseText 属性 服务器的响应,表示为一个串

reponseXML 属性 服务器的响应,表示为XML

status    服务器的HTTP状态码,200对应ok 400对应notfound

 

11、XMLHttpRequest对象在IE和Firefox中创建方式有没有不同?

 

IE中通过new ActiveXObject()得到,Firefox中通过new XMLHttpRequest()得到

 

12、Ajax是什么及其工作原理是什么?

 

Ajax 由 HTML、JavaScript™ 技术、DHTML 和 DOM 组成,这一杰出的方法可以将笨拙的Web 界面转化成交互性的 Ajax 应用程序。

AJAX最核心的一个对象是XMLHttpRequest,所有的Ajax操作都离不开对这个对象的操作

XMLHttpRequest对象相关方法:

打开请求

XMLHttpRequest.open(传递方式,地址,是否异步请求)

准备就绪执行

XMLHttpRequest.onreadystatechange

获取执行结果

XMLHttpRequest.responseText

 

 

 

第三章:J2EE高级软件工程师面试题

 

                          --------数据库面试题部分

 

为数据库创建索引都需要注意些什么?

 

1. 索引能提高速度的关键就是索引所占的空间要比表小得多

2. 注意索引的大小,有一些表可以建成索引组织表

3. 索引的列不要太多,要选择一些selective比较低的列建B-tree索引,选择selective高的列建bitmap索引(在更新比较多的表不不要建bitmap索引)

4. 将selective较低的列放在前面

5. 在更新不多的表上建索引时,可以考虑用compress选择,以节约索引的空间

 

第一范式(1NF)、第二范式(2NF)和第三范式(3NF)之间的区别是什么?

 

构造数据库必须遵循一定的规则。在关系数据库中,这种规则就是范式。范式是符合某一种级别的关系模式的集合。关系数据库中的关系必须满足一定的要求,即满足不同的范式。目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、第四范式(4NF)、第五范式(5NF)和第六范式(6NF)。满足最低要求的范式是第一范式(1NF)。在第一范式的基础上进一步满足更多要求的称为第二范式(2NF),其余范式以次类推。一般说来,数据库只需满足第三范式(3NF)就行了。下面我们举例介绍第一范式(1NF)、第二范式(2NF)和第三范式(3NF)。

 

3.4.1 第一范式(1NF)

    在任何一个关系数据库中,第一范式(1NF)是对关系模式的基本要求,不满足第一范式(1NF)的数据库就不是关系数据库。

     所谓第一范式(1NF)是指数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。如果出现重复的属性,就可能需要定义一个新的实体,新的实体由重复的属性构成,新实体与原实体之间为一对多关系。在第一范式(1NF)中表的每一行只包含一个实例的信息。例如,对于图3-2 中的员工信息表,不能将员工信息都放在一列中显示,也不能将其中的两列或多列在一列中显示;员工信息表的每一行只表示一个员工的信息,一个员工的信息在表中只出现一次。简而言之,第一范式就是无重复的列。

 

3.4.2 第二范式(2NF)

    第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。第二范式(2NF)要求数据库表中的每个实例或行必须可以被惟一地区分。为实现区分通常需要为表加上一个列,以存储各个实例的惟一标识。如

图3-2 员工信息表中加上了员工编号(emp_id)列,因为每个员工的员工编号是惟一的,因此每个员工可以被惟一区分。这个惟一属性列被称为主关键字或主键、主码。

     第二范式(2NF)要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性,如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。为实现区分通常需要为表加上一个列,以存储各个实例的惟一标识。简而言之,第二范式就是非主属性非部分依赖于主关键字。

 

3.4.3 第三范式(3NF)

    满足第三范式(3NF)必须先满足第二范式(2NF)。简而言之,第三范式(3NF)要求一个数据库表中不包含已在其它表中已包含的非主关键字信息。例如,存在一个部门信息表,其中每个部门有部门编号(dept_id)、部门名称、部门简介等信息。那么在图3-2

的员工信息表中列出部门编号后就不能再将部门名称、部门简介等与部门有关的信息再加入员工信息表中。如果不存在部门信息表,则根据第三范式(3NF)也应该构建它,否则就会有大量的数据冗余。简而言之,第三范式就是属性不依赖于其它非主属性。

所谓范式就是符合某一种级别的关系模式的集合。通过分解把属于低级范式的关系模式转换为几个属于高级范式的关系模式的集合。这一过程称为规范化。 

  

  1、   第一范式(1NF):一个关系模式R的所有属性都是不可分的基本数据项。 

  2、   第二范式(2NF):关系模式R属于第一范式,且每个非主属性都完全函数依赖于键码。 

  3、   第三范式(3NF):关系模式R属于第一范式,且每个非主属性都不伟递领带于键码。 

  4、   BC范式(BCNF):关系模式R属于第一范式,且每个属性都不传递依赖于键码。

 

一组SQL面试题

 

1. 在表A中有数据

ID    MO

1    Y

2    N

请用一个SELECT 语句写出,如果MO的值为“Y”,返回“YES”,为N返回“NO”

效果如下:

ID    MO

1    YES

2    NO

SELECTID,MO=CASE

WHEN MO=’Y’ THEN‘YES’

WHEN MO=’N’ THEN‘NO’

END

FROM Az

2. 在表A中查询出自动增长列中31到40之间的数据(注意可能不是连续的)

select * from Awhere id between 31 and 40

3. 有一个表table中有一个自动增长字段ID,如果在存储过程中向这个表插入一条记录后,如何获得新记录的ID.(写出获取新记录ID的函数即可)

CREATE FUNCTIONc_currentId()

RETURNS int

AS

BEGIN

declare @lastIdint

select@lastId=max(cid) from c

RETURN (@lastId)

END

selecttempdb.dbo.c_currentId() as ‘当前C表中最新的编号’

4. having的用法, 是用来做什么的   having用来对group by 分组后的记录进行过滤。

5. sql中的什么函数可以转换为时间     selectconvert(datetime,’2000/01/01′)    selectcast(’2001/02/02′ as datetime)

6. 查询数据放入一张临时表   select * into #A fromTest   select * from #A

 

存储过程的优缺点是什么?

 

优点:

1.由于应用程序随着时间推移会不断更改,增删功能,T-SQL过程代码会变得更复杂,StoredProcedure为封装此代码提供了一个替换位置。

 

2.执行计划(存储过程在首次运行时将被编译,这将产生一个执行计划-- 实际上是Microsoft SQL Server为在存储过程中获取由 T-SQL 指定的结果而必须采取的步骤的记录。)缓存改善性能。

……..但sql server新版本,执行计划已针对所有T-SQL 批处理进行了缓存,而不管它们是否在存储过程中,所以没比较优势了。

 

3.存储过程可以用于降低网络流量,存储过程代码直接存储于数据库中,所以不会产生大量T-sql语句的代码流量。

 

4.使用存储过程使您能够增强对执行计划的重复使用,由此可以通过使用远程过程调用(RPC) 处理服务器上的存储过程而提高性能。RPC 封装参数和调用服务器端过程的方式使引擎能够轻松地找到匹配的执行计划,并只需插入更新的参数值。

 

5.可维护性高,更新存储过程通常比更改、测试以及重新部署程序集需要较少的时间和精力。

 

6.代码精简一致,一个存储过程可以用于应用程序代码的不同位置。

 

7.更好的版本控制,通过使用 Microsoft Visual SourceSafe或某个其他源代码控制工具,您可以轻松地恢复到或引用旧版本的存储过程。

 

8.增强安全性:

a、通过向用户授予对存储过程(而不是基于表)的访问权限,它们可以提供对特定数据的访问;

b、提高代码安全,防止 SQL注入(但未彻底解决,例如,将数据操作语言--DML,附加到输入参数);

c、SqlParameter 类指定存储过程参数的数据类型,作为深层次防御性策略的一部分,可以验证用户提供的值类型(但也不是万无一失,还是应该传递至数据库前得到附加验证)。

 

缺点:

 

1.如果更改范围大到需要对输入存储过程的参数进行更改,或者要更改由其返回的数据,则您仍需要更新程序集中的代码以添加参数、更新 GetValue() 调用,等等,这时候估计比较繁琐了。

 

2.可移植性差

 

由于存储过程将应用程序绑定到 SQL Server,因此使用存储过程封装业务逻辑将限制应用程序的可移植性。如果应用程序的可移植性在您的环境中非常重要,则将业务逻辑封装在不特定于 RDBMS 的中间层中可能是一个更佳的选择。

 

如何用SQL语句进行模糊查找?

 

LIKE条件一般用在指定搜索某字段的时候, 通过”% _” 通配符的作用实现模糊查找功能,通配符可以在前面也可以在后面或前后都有。

 

搜索以mian开头:

SELECT * FROMteble WHERE title LIKE ‘mian%’

 

搜索以mian结束:

SELECT * FROMteble WHERE title LIKE ‘%mian’

 

搜索包含mian:

SELECT * FROMteble WHERE title LIKE ‘%mian%’

注释:%表示0个或多个字符构成的字符串

_表示单个字符

 

介绍一下内联、左联、右联

 

一.先看一些最简单的例子

 

例子

 

Table A

aid adate

1 a1

2 a2

3 a3

 

TableB

 

bid bdate

1 b1

2 b2

4 b4

两个表a,b相连接,要取出id相同的字段

select * from ainner join b on a.aid = b.bid这是仅取出匹配的数据.

此时的取出的是:

1 a1 b1

2 a2 b2

 

那么left join 指:

select * from aleft join b on a.aid = b.bid

首先取出a表中所有数据,然后再加上与a,b匹配的的数据

此时的取出的是:

1 a1 b1

2 a2 b2

3 a3 空字符

 

同样的也有rightjoin

指的是首先取出b表中所有数据,然后再加上与a,b匹配的的数据

此时的取出的是:

1 a1 b1

2 a2 b2

4 空字符 b4

 

LEFT JOIN 或 LEFT OUTER JOIN。

左向外联接的结果集包括 LEFT OUTER 子句中指定的左表的所有行,而不仅仅是联接列所匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值

 

二. leftjoin/right join/inner join操作演示

 

表A记录如下:

aID aNum

1 a20050111

2 a20050112

3 a20050113

4 a20050114

5 a20050115

 

表B记录如下:

bID bName

1 2006032401

2 2006032402

3 2006032403

4 2006032404

8 2006032408

 

实验如下:

1. left join

sql语句如下:

 

SELECT * FROM A

LEFT JOIN B

ON A.aID = B.bID

结果如下:

aID aNum bIDbName

1 a20050111 12006032401

2 a20050112 22006032402

3 a20050113 32006032403

4 a20050114 42006032404

5 a20050115 NULLNULL

(所影响的行数为 5 行)

 

结果说明:

left join是以A表的记录为基础的,A可以看成左表,B可以看成右表,left join是以左表为准的.

换句话说,左表(A)的记录将会全部表示出来,而右表(B)只会显示符合搜索条件的记录(例子中为: A.aID = B.bID).

B表记录不足的地方均为NULL.

 

2. right join

sql语句如下:

 

SELECT * FROM A

RIGHT JOIN B

ON A.aID = B.bID

结果如下:

aID aNum bIDbName

1 a20050111 12006032401

2 a20050112 22006032402

3 a20050113 32006032403

4 a20050114 42006032404

NULL NULL 82006032408

(所影响的行数为 5 行)

 

结果说明:

仔细观察一下,就会发现,和left join的结果刚好相反,这次是以右表(B)为基础的,A表不足的地方用NULL填充.

 

3.inner join

sql语句如下:

 

SELECT * FROM A

INNERJOIN B

ON A.aID = B.bID

结果如下:

aID aNum bIDbName

1 a20050111 12006032401

2 a20050112 22006032402

3 a20050113 32006032403

4 a20050114 42006032404

 

结果说明:

很明显,这里只显示出了 A.aID =B.bID的记录.这说明inner join并不以谁为基础,它只显示符合条件的记录.

 

-----------------[以下为网上的一点资料]------------------

LEFT JOIN操作用于在任何的 FROM 子句中,组合来源表的记录。使用 LEFT JOIN 运算来创建一个左边外部联接。左边外部联接将包含了从第一个(左边)开始的两个表中的全部记录,即使在第二个(右边)表中并没有相符值的记录。

 

语法:

FROM table1 LEFTJOIN table2 ON table1.field1 compopr table2.field2

 

说明:

① table1, table2参数用于指定要将记录组合的表的名称。

② field1, field2参数指定被联接的字段的名称。且这些字段必须有相同的数据类型及包含相同类型的数据,但它们不需要有相同的名称。

③ compopr参数指定关系比较运算符:”=”, “<", ">“, “<=", ">=” 或 “<>“。

④ 如果在INNER JOIN操作中要联接包含Memo 数据类型或 OLE Object 数据类型数据的字段,将会发生错误。

 

说一下mysql, oracle等常见数据库的分页实现方案?

 

1.Oracle:

select * from (select row_.*, rownum rownum_ from ( query_SQL ) row_ whererownum =< max)where rownum_ >= min

2.SQL Server:

select top@pagesize * from tablename where id not in (select top@pagesize*(@page-1) idfrom tablename order by id) order by id

 

3.MySQL

select * fromtablename limit position, counter

 

4.DB2

select * from(select *,rownumber() as ROW_NEXT from tablename) where ROW_NEXTbetween min andmax

 

——————————————————————————————–

1.分页方案一:(利用NotIn和SELECT TOP分页)效率次之

语句形式:

SELECT TOP 10 *FROM TestTable

WHERE(ID NOT IN(SELECT TOP 20  id FROM  TestTable ORDERBY  id))  ORDERBYID

SELECT  TOP 页大小 * FROM TestTable

WHERE( ID NOT IN (SELECT TOP  每页大小-1*待查询页数-1  id  FROM  表 ORDERBY id)) ORDERBYID

思路:先查询出待查询页之前的全部条数的id,查询ID不在这些ID中的指定数量条数

 

2.分页方案二:(利用ID大于多少和SELECT TOP分页)效率最高

语句形式:

SELECT  TOP  10*   FROM TestTable

WHERE(ID>(SELECTMAX(id) FROM(SELECT TOP20 id  FROM  TestTableORDERBYid)AS T))ORDERBY ID

SELECT  TOP  页大小* FROM TestTable

WHERE(ID>(SELECTMAX(id) FROM(SELECT TOP 每页大小*待查询页数-1  id FROM 表  ORDERBY id)AS T))ORDERBY ID

思路:先获得待查询页的之前全部条数id,获得它们当中最大的ID号,以此最大ID号为标志,查找比这个ID号大的指定条数

 

3.分页方案三:

SELECT TOPPageSize * FROM(SELECT TOP nPage*PageSize * from YOURTABLE order byid)as aorder by id desc

SELECT TOP 每页条数 * FROM (SELECT TOP 待查询页*每页条数) * from YOURTABLE order by id)as aorder by id desc

思路:先正排序查询出待查询页之前(包括当前页)的全部条数,然后将其倒排序,取指定条数

 

几个SQL的面试题

 

1. 解释一下SQL里面的null

答案:null代表一个unknown的值或者一个不存在的值

2. 如何用SQL判断一个值是不是null?

答案:可以用is null来判断一个值是不是null

3.    所有包含null的计算表达式的返回结果都是null,这句话正确吗?比如5+ null返回null

答案:正确

4. 所有与null得比较运算都返回unknown正确吗?

答案:正确

5. (unknown ortrue) = true正确吗?

答案:正确

6. (unknown orfalse) = unknown正确吗?

答案:正确

7. (unknown orunknown) = unknown正确吗?

答案:正确

8. (true andunknown) = unknown正确吗?

答案:正确

9. (false andunknown) = false正确吗?

答案:正确

10. (unknown andunknown) = unknown正确吗?

答案:正确

11.   (not unknown) = unknown 正确吗?

答案:正确

 

介绍一下游标?

 

游标是从数据表中提取出来的数据,以临时表的形式存放在内存中,在游标中有一个数据指针,在初始状态下指向的是首记录,利用fetch语句可以移动该指针,从而对游标中的数据进行各种操作,然后将操作结果写回数据表中。

 

由 SELECT 语句返回的行集包括所有满足该语句 WHERE 子句中条件的行。由语句所返回的这一完整的行集被称为结果集。应用程序,特别是交互式联机应用程序,并不总能将整个结果集作为一个单元来有效地处理。这些应用程序需要一种机制以便每次处理一行或一部分行。游标就是提供这种机制的结果集扩展。

 

游标通过以下方式扩展结果处理:

 

l        允许定位在结果集的特定行。

 

l        从结果集的当前位置检索一行或多行。

 

l        支持对结果集中当前位置的行进行数据修改。

 

l        为由其他用户对显示在结果集中的数据库数据所做的更改提供不同级别的可见性支持。

 

l        提供脚本、存储过程和触发器中使用的访问结果集中的数据的Transact-SQL 语句。

 

存储过程的优点有哪些?

 

l        更快的执行速度:存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般SQL语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度;

 

l        与事务的结合,提供更好的解决方案:当对数据库进行复杂操作时(如对多个表进行Update、Insert、Query和Delete时),可将此复杂操作用存储过程封装起来与数据库提供的事务处理结合一起使用;

 

l        支持代码重用:存储过程可以重复使用,可减少数据库开发人员的工作量;

 

l        安全性高:可设定只有某此用户才具有对指定存储过程的使用权。

 

介绍一下SQL Server的全文索引?

 

全文索引可以对存储在SQLServer数据库中的文本数据执行快速检索功能。同LIKE谓词不同,全文索引只对字符模式进行操作,对字和语句执行搜索功能。全文索引对于查询非结构化数据非常有效。一般情况下,可以对char、varchar和nvarchar数据类型的列创建全文索引,同时,还可以对二进制格式的列创建索引,如image和varbinary数据类型列。对于这些二进制数据,无法使用LIKE谓词。

 

为了对表创建全文索引,表必须包含单个、唯一、非空列。当执行全文检索的时候,SQL Server搜索引擎返回匹配搜索条件的行的键值。一般情况,使用sqlserver中的全文索引,经过大体4个步骤:

 

l        安装全文索引服务;

 

l        为数据表建立全文索引目录;

 

l        使全文索引与数据表内容同步;

 

l        使用全文索引进行查询。

 

SQL Server里面什么样的视图才能创建索引?

 

在为视图创建索引前,视图本身必须满足以下条件:

 

l        视图以及视图中引用的所有表都必须在同一数据库中,并具有同一个所有者。

 

l        索引视图无需包含要供优化器使用的查询中引用的所有表。

 

l        必须先为视图创建唯一群集索引,然后才可以创建其它索引。

 

l        创建基表、视图和索引以及修改基表和视图中的数据时,必须正确设置某些 SET选项(在本文档的后文中讨论)。另外,如果这些 SET 选项正确,查询优化器将不考虑索引视图。

 

l        视图必须使用架构绑定创建,视图中引用的任何用户定义的函数必须使用SCHEMABINDING 选项创建。

 

l        另外,还要求有一定的磁盘空间来存放由索引视图定义的数据。

 

介绍一下SQL Server里面的索引视图?

 

复杂报表的场景经常会在数据仓储应用程序中遇到,它在查询过程中会对数据库服务器产生大量请求。当这些查询访问视图时,因为数据库将建立视图结果集所需的逻辑合并到从基本表数据建立完整查询结果集所需的逻辑中,所以性能将会下降。这一操作的开销可能会比较大,尤其当视图涉及到复杂的大量行处理–如大量数据聚合或多表联结时。因为结果集并不永久存放在数据库(标准视图)中,以后对该视图的访问可能导致在每次执行查询时建立结果集的代价。

 

SQL Server允许为视图创建独特的聚集索引,从而让访问此类视图的查询的性能得到极大地改善。在创建了这样一个索引后,视图将被执行,结果集将被存放在数据库中,存放的方式与带有聚集索引的表的存放方式相同。这就在数据库中有效地实现了查询结果。对于那些在FROM子句中不直接指定视图名的查询,SQLServer查询优化器将使用视图索引。现有查询将受益于从索引视图检索数据而无需重新编写程序原码的高效率。对于某些特定类型的视图,甚至可以获得指数级的性能改善。

 

如果在视图上创建索引,那么视图中的数据会被立即存储在数据库中,对索引视图进行修改,那么这些修改会立即反映到基础表中。同理,对基础表所进行的数据修改也会反映到索引视图那里。索引的惟一性大大提高了SQL Server 查找那些被修改的数据行。

 

维护索引视图比维护基础表的索引更为复杂。所以,如果认为值得以因数据修改而增加系统负担为代价来提高数据检索的速度,那么应该在视图上创建索引。

 

什么是唯一索引?

 

唯一索引可以确保索引列不包含重复的值。在多列唯一索引的情况下,该索引可以确保索引列中每个值组合都是唯一的。例如,如果在 last_name、first_name 和 middle_initial 列的组合上创建了唯一索引 full_name,则该表中任何两个人都不可以具有相同的全名。

 

聚集索引和非聚集索引都可以是唯一的。因此,只要列中的数据是唯一的,就可以在同一个表上创建一个唯一的聚集索引和多个唯一的非聚集索引。

 

只有当唯一性是数据本身的特征时,指定唯一索引才有意义。如果必须实施唯一性以确保数据的完整性,则应在列上创建 UNIQUE 或 PRIMARY KEY 约束,而不要创建唯一索引。例如,如果打算经常查询雇员表(主键为 emp_id)中的社会安全号码 (ssn) 列,并希望确保社会安全号码的唯一性,则在 ssn 列上创建 UNIQUE 约束。如果用户为一个以上的雇员输入了同一个社会安全号码,则会显示错误。

 

什么是聚集索引和非聚集索引?分布介绍一下

 

(1)非聚集索引

 

非聚集索引与课本中的索引类似。数据存储在一个地方,索引存储在另一个地方,索引带有指针指向数据的存储位置。索引中的项目按索引键值的顺序存储,而表中的信息按另一种顺序存储(这可以由聚集索引规定)。如果在表中未创建聚集索引,则无法保证这些行具有任何特定的顺序。

 

典型的桌面数据库使用的是非聚集索引。在这类索引中,索引键值是有序的,而每个索引节点所指向的数据行是无序的。一个SQL Server表最多可以拥有255个非聚集索引。

 

非聚集索引与聚集索引一样有B-树结构,但是有两个重大差别:

 

l        数据行不按非聚集索引键的顺序排序和存储。

 

l        非聚集索引的叶层不包含数据页。

 

相反,叶节点包含索引行。每个索引行包含非聚集键值以及一个或多个行定位器,这些行定位器指向有该键值的数据行(如果索引不唯一,则可能是多行)。非聚集索引可以在有聚集索引的表、堆集或索引视图上定义。在 SQL Server中,非聚集索引中的行定位器有两种形式:

 

l        如果表是堆集(没有聚集索引),行定位器就是指向行的指针。该指针用文件标识符(ID)、页码和页上的行数生成。整个指针称为行 ID。

 

l        如果表是堆集(没有聚集索引),行定位器就是指向行的指针。该指针用文件标识符(ID)、页码和页上的行数生成。整个指针称为行 ID。

 

由于非聚集索引将聚集索引键作为其行指针存储,因此使聚集索引键尽可能小很重要。如果表还有非聚集索引,请不要选择大的列作为聚集索引的键。

 

在创建非聚集索引之前,应先了解您的数据是如何被访问的。可考虑将非聚集索引用于:

 

l        包含大量非重复值的列,如姓氏和名字的组合(如果聚集索引用于其它列)。如果只有很少的非重复值,如只有 1 和 0,则大多数查询将不使用索引,因为此时表扫描通常更有效。

 

l        不返回大型结果集的查询。

 

l        返回精确匹配的查询的搜索条件(WHERE 子句)中经常使用的列。

 

l        经常需要联接和分组的决策支持系统应用程序。应在联接和分组操作中使用的列上创建多个非聚集索引,在任何外键列上创建一个聚集索引。

 

l        在特定的查询中覆盖一个表中的所有列。这将完全消除对表或聚集索引的访问。

 

(2)聚集索引

 

聚集索引确定表中数据的物理顺序。聚集索引类似于电话簿,后者按姓氏排列数据。由于聚集索引规定数据在表中的物理存储顺序,因此一个表只能包含一个聚集索引。但该索引可以包含多个列(组合索引),就像电话簿按姓氏和名字进行组织一样。

 

聚集索引在系统数据库表sysindexes内有一行,其 indid = 1。数据链内的页和其内的行按聚集索引键值排序。所有插入都在所插入行中的键值与排序顺序相匹配时执行。

 

SQL Server将索引组织为B-树。索引内的每一页包含一个页首,页首后面跟着索引行。每个索引行都包含一个键值以及一个指向较低级页或数据行的指针。索引的每个页称为索引节点。B-树的顶端节点称为根节点。索引的底层节点称为叶节点。每级索引中的页链接在双向链接列表中。在聚集索引内数据页组成叶节点。根和叶之间的任何索引级统称为中间级。

 

对于聚集索引,sysindexes.root指向它的顶端。SQL Server 沿着聚集索引浏览以找到聚集索引键对应的行。为找到键的范围,SQL Server 浏览索引以找到这个范围的起始键值,然后用向前或向后指针扫描数据页。为找到数据页链的首页,SQL Server 从索引的根节点开始沿最左边的指针进行扫描.

 

聚集索引对于那些经常要搜索范围值的列特别有效。使用聚集索引找到包含第一个值的行后,便可以确保包含后续索引值的行在物理相邻。例如,如果应用程序执行的一个查询经常检索某一日期范围内的记录,则使用聚集索引可以迅速找到包含开始日期的行,然后检索表中所有相邻的行,直到到达结束日期。这样有助于提高此类查询的性能。同样,如果对从表中检索的数据进行排序时经常要用到某一列,则可以将该表在该列上聚集(物理排序),避免每次查询该列时都进行排序,从而节省成本。

 

对于聚集索引,人们往往有一些错误的认识。其中,最常见的错误有:

 

l        聚集索引会降低insert操作的速度,因为必须要向后移动一半的数据来为新插入的行腾出空间。这种认识是错误的,因为可以利用填充因子控制填充的百分比,从而在索引页上为新插入的数据保留空间。如果索引页填满了,SQL Server将会进行页拆分,在这种情况下只有第一个页才会受到影响。

 

l        在使用标识列的主键上创建聚集索引是一种好的设计方法,它可以使对表的操作达到最快速度。这种认识是错误的,它浪费了创建其它更有效的聚集索引的机会。并且,使用这种方法会把每个新插入的记录行都存储到表尾部的同一个的数据页中,这将导致数据库的热点和锁争用。笔者曾经见过采用这种方法设计的数据库,对于每一个新订单,客户服务人员都不得不等待数分钟来加以确认。

 

l        聚集索引是具有魔力的。如果哪个查询的速度不够快,那么就在该列上创建聚集索引,对于表的操作速度一定会得到提高。这种认识也是错误的,聚集索引只是比非聚集索引稍稍快了那么一点点。因为在每个表上只能创建一个聚集索引,所以它也是一种宝贵的性能资源,只有在那些经常作为条件查询一组记录行的列上才应该建立聚集索引。

 

在创建聚集索引之前,应先了解数据是如何被访问的。可考虑将聚集索引用于:

 

l        包含大量非重复值的列。

 

l        使用下列运算符返回一个范围值的查询:BETWEEN、>、>=、< 和 <=。

 

l        被连续访问的列。

 

l        返回大型结果集的查询。

 

l        经常被使用联接或 GROUP BY 子句的查询访问的列;一般来说,这些是外键列。对 ORDER BY 或 GROUP BY 子句中指定的列进行索引,可以使 SQL Server 不必对数据进行排序,因为这些行已经排序。这样可以提高查询性能。

 

l        OLTP 类型的应用程序,这些程序要求进行非常快速的单行查找(一般通过主键)。应在主键上创建聚集索引。

 

注意,聚集索引不适用于:

 

l        频繁更改的列,这将导致整行移动(因为 SQL Server 必须按物理顺序保留行中的数据值)。这一点要特别注意,因为在大数据量事务处理系统中数据是易失的。

 

l        宽键,来自聚集索引的键值由所有非聚集索引作为查找键使用,因此存储在每个非聚集索引的叶条目内。

 

SQL Server提供的3种恢复模型都是什么? 有什么区别?

 

SQL Server提供了3种恢复模型,分别是:

 

l        简单恢复 ,允许将数据库恢复到最新的备份。

 

l        完全恢复,允许将数据库恢复到故障点状态。

 

l        大容量日志记录恢复,允许大容量日志记录操作。

 

这些模型中的每个都是针对不同的性能、磁盘和磁带空间以及保护数据丢失的需要。例如,当选择恢复模型时,必须考虑下列业务要求之间的权衡:

 

l        大规模操作的性能(如创建索引或大容量装载)。

 

l        数据丢失表现(如已提交的事务丢失)。

 

l        事务日志空间损耗

 

l        备份和恢复过程的简化。

 

根据正在执行的操作,可以有多个适合的模型。选择了恢复模型后,设计所需的备份和恢复过程。表6提供了三种恢复模型的优点和含义的概述。

 

表 6备份模型之间的比较

 

恢复模型

优点

工作损失表现

能否恢复到即时点?

简单

允许高性能大容量复制操作。

收回日志空间以使空间要求最小。

必须重做自最新的数据库或差异备份后所发生的更改。

可以恢复到任何备份的结尾处。随后必须重做更改。

完全

数据文件丢失或损坏不会导致工作损失。

可以恢复到任意即时点(例如,应用程序或用户错误之前)。

正常情况下没有。

如果日志损坏,则必须重做自最新的日志备份后所发生的更改。

可以恢复到任何即时点。

大容量日志记录的

允许高性能大容量复制操作。大容量操作使用最少的日志空间。

如果日志损坏,或者自最新的日志备份后发生了大容量操作,则必须重做自上次备份后所做的更改。否则不丢失任何工作。

可以恢复到任何备份的结尾处。随后必须重做更改。

简单恢复所需的管理最少。在简单恢复模型中,数据只能恢复到最新的完整数据库备份或差异备份的状态。不使用事务日志备份,而使用最小事务日志空间。一旦不再需要日志空间从服务器故障中恢复,日志空间便可重新使用。与完整模型或大容量日志记录模型相比,简单恢复模型更容易管理,但如果数据文件损坏,则数据损失表现会更高。

 

完全恢复和大容量日志记录恢复模型为数据提供了最大的保护性。这些模型依靠事务日志提供完全的可恢复性,并防止最大范围的故障情形所造成的工作损失。完全恢复模型提供最大的灵活性,可将数据库恢复到更早的即时点。

 

大容量日志记录模型为某些大规模操作(如创建索引或大容量复制)提供了更高的性能和更低的日志空间损耗。不过这将牺牲时点恢复的某些灵活性。很多数据库都要经历大容量装载或索引创建的阶段,因此可能希望在大容量日志记录模型和完全恢复模型之间进行切换。

 

SQL Server的固定数据库角色都有哪些?对应的服务器权限有哪些?

 

固定服务器角色

对应的服务器级权限

bulkadmin

授予的权限: ADMINISTER BULK OPERATIONS

dbcreator

授予的权限: CREATE DATABASE

diskadmin

授予的权限: ALTER RESOURCES

processadmin

授予的权限: ALTER SERVER STATE

processadmin

授予的权限: ALTER ANY CONNECTION

securityadmin

授予的权限: ALTER ANY LOGIN

serveradmin

授予的权限: ALTER SETTINGS

serveradmin

授予的权限: SHUTDOWN

serveradmin

授予的权限: CREATE ENDPOINT

serveradmin

授予的权限: ALTER SERVER STATE

serveradmin

授予的权限: ALTER ANY ENDPOINT

serveradmin

授予的权限: ALTER RESOURCES

setupadmin

授予的权限: ALTER ANY LINKED SERVER

sysadmin

带GRANT 选项授予的权限:CONTROL SERVER

 

 

在SQL Server中创建数据库主要有那种方式?

 

在SQL Server中创建数据库主要有两种方法,第一种是在SQL Server Management Studio中使用向导创建数据库;第二种是执行Transact-SQL语句创建数据库。下面我们分别进行介绍。

 

(1)使用SQL ServerManagement Studio创建数据库

 

在SQL ServerManagement Studio中,可以使用向导创建数据库,步骤如下:

 

1.  打开SQLServer Management Studio。

 

2.    右击“数据库”对象,在弹出式菜单中选择“新建数据库”菜单项,打开“新建数据库”对话框

 

3.  在“常规”页,可以定义数据库的名称为EAMS、数据库文件、数据库的所有者、排序规则、恢复模型,以及是否使用全文索引。

 

4.   在“选项”页,可以定义数据库的一些选项,包括自动选项、游标选项、混杂选项、恢复选项、行级版本选项和状态选项

 

5.   在“文件组”页,显示文件组和文件的统计信息,同时还可以设置是否采用默认值

 

6.  在“扩展属性”页,可以定义数据库的一些扩展属性,如图5所示。

 

7.  当完成各个选项的定义之后,单击【OK】按钮,SQL Server数据库引擎会创建所定义的数据库。

 

(2)使用Transact-SQL创建数据库

 

Transact-SQL提供了创建数据库的语句:CREATE DATABASE,其语法格式如下:

 

CREATEDATABASEdatabase_name

 

[ ON

 

[<filespec>[ ,...n ] ]

 

[,<filegroup> [ ,...n ] ]

 

]

 

[

 

[ LOG ON{<filespec> [ ,...n ] } ]

 

[COLLATEcollation_name ]

 

[ FOR { ATTACH[WITH <service_broker_option> ]

 

|ATTACH_REBUILD_LOG} ]

 

[WITH<external_access_option> ]

 

]

 

[;]

 

<filespec>::=

 

[ PRIMARY ]

 

(

 

[ NAME=logical_file_name , ]

 

FILENAME =‘os_file_name’

 

[ , SIZE = size[KB | MB | GB | TB ] ]

 

[ , MAXSIZE ={max_size [ KB | MB | GB | TB ] | UNLIMITED } ]

 

[ , FILEGROWTH=growth_increment [ KB | MB | % ] ]

 

) [ ,...n ]

 

<filegroup>::=

 

FILEGROUPfilegroup_name

 

<filespec>[,...n ]

 

<external_access_option>::=

 

DB_CHAINING { ON|OFF }

 

| TRUSTWORTHY {ON| OFF }

 

<service_broker_option>::=

 

ENABLE_BROKER

 

| NEW_BROKER

 

|ERROR_BROKER_CONVERSATIONS

 

Create aDatabaseSnapshot

 

CREATEDATABASEdatabase_snapshot_name

 

ON

 

(

 

NAME=logical_file_name,

 

FILENAME=‘os_file_name’

 

) [ ,...n ]

 

AS SNAPSHOTOFsource_database_name

 

[;]

 

参数说明如下:

 

l        database_name,新数据库的名称。数据库名称在服务器中必须唯一,并且符合标识符的规则。database_name最多可以包含 128 个字符,除非没有为日志指定逻辑名。如果没有指定日志文件的逻辑名,则SQL Server会通过向 database_name 追加后缀来生成逻辑名。该操作要求 database_name 在 123 个字符之内,以便生成的日志文件逻辑名少于 128 个字符。

 

l        ON,指定显式定义用来存储数据库数据部分的磁盘文件(数据文件)。该关键字后跟以逗号分隔的 <filespec> 项列表,<filespec> 项用以定义主文件组的数据文件。主文件组的文件列表后可跟以逗号分隔的 <filegroup> 项列表(可选),<filegroup>项用以定义用户文件组及其文件。

 

l        N,占位符,表示可以为新数据库指定多个文件。

 

l        LOG ON,指定显式定义用来存储数据库日志的磁盘文件(日志文件)。该关键字后跟以逗号分隔的 <filespec> 项列表,<filespec> 项用以定义日志文件。如果没有指定 LOG ON,将自动创建一个日志文件,该文件使用系统生成的名称,大小为数据库中所有数据文件总大小的 25%。

 

l        FOR LOAD,支持该子句是为了与早期版本的SQL Server 兼容。数据库在打开 dbo use only 数据库选项的情况下创建,并且将其状态设置为正在装载。

 

l        FOR ATTACH,指定从现有的一组操作系统文件中附加数据库。必须有指定第一个主文件的<filespec> 条目。至于其它 <filespec> 条目,只需要与第一次创建数据库或上一次附加数据库时路径不同的文件的那些条目。必须为这些文件指定 <filespec> 条目。附加的数据库必须使用与 SQL Server 相同的代码页和排序次序创建。应使用 sp_attach_db 系统存储过程,而不要直接使用 CREATE DATABASEFOR ATTACH。只有必须指定 16 个以上的<filespec>项目时,才需要使用 CREATE DATABASEFOR ATTACH。如果将数据库附加到的服务器不是该数据库从中分离的服务器,并且启用了分离的数据库以进行复制,则应该运行 sp_removedbreplication从数据库删除复制。

 

l        collation_name,指定数据库的默认排序规则。排序规则名称既可以是 Windows 排序规则名称,也可以是 SQL 排序规则名称。如果没有指定排序规则,则将 SQL Server 实例的默认排序规则指派为数据库的排序规则。

 

l        PRIMARY,指定关联的 <filespec> 列表定义主文件。主文件组包含所有数据库系统表。还包含所有未指派给用户文件组的对象。主文件组的第一个 <filespec> 条目成为主文件,该文件包含数据库的逻辑起点及其系统表。一个数据库只能有一个主文件。如果没有指定 PRIMARY,那么 CREATE DATABASE 语句中列出的第一个文件将成为主文件。

 

l        NAME,为由 <filespec> 定义的文件指定逻辑名称。如果指定了 FOR ATTACH,则不需要指定 NAME 参数。

 

l        logical_file_name,用来在创建数据库后执行的Transact-SQL 语句中引用文件的名称。logical_file_name 在数据库中必须唯一,并且符合标识符的规则。该名称可以是字符或 Unicode 常量,也可以是常规标识符或定界标识符。

 

l        FILENAME,为<filespec> 定义的文件指定操作系统文件名。

 

l        os_file_name,操作系统创建<filespec> 定义的物理文件时使用的路径名和文件名。os_file_name 中的路径必须指定 SQL Server 实例上的目录。os_file_name 不能指定压缩文件系统中的目录。如果文件在原始分区上创建,则 os_file_name 必须只指定现有原始分区的驱动器字母。每个原始分区上只能创建一个文件。原始分区上的文件不会自动增长;因此,os_file_name 指定原始分区时,不需要指定 MAXSIZE 和 FILEGROWTH 参数。

 

l        SIZE,指定 <filespec> 中定义的文件的大小。如果主文件的 <filespec> 中没有提供 SIZE 参数,那么 SQL Server 将使用 model 数据库中的主文件大小。如果次要文件或日志文件的 <filespec> 中没有指定 SIZE 参数,则 SQL Server 将使文件大小为 1 MB。

 

l        Size,<filespec> 中定义的文件的初始大小。可以使用千字节 (KB)、兆字节 (MB)、千兆字节(GB) 或兆兆字节 (TB) 后缀。默认值为 MB。指定一个整数,不要包含小数位。size的最小值为 512 KB。如果没有指定 size,则默认值为 1 MB。为主文件指定的大小至少应与model 数据库的主文件大小相同。

 

l        MAXSIZE,指定 <filespec> 中定义的文件可以增长到的最大大小。

 

l        max_size,<filespec>中定义的文件可以增长到的最大大小。可以使用千字节 (KB)、兆字节 (MB)、千兆字节 (GB) 或兆兆字节 (TB) 后缀。默认值为 MB。指定一个整数,不要包含小数位。如果没有指定 max_size,那么文件将增长到磁盘变满为止。

 

l        UNLIMITED,指定<filespec> 中定义的文件将增长到磁盘变满为止。

 

l        FILEGROWTH,指定<filespec> 中定义的文件的增长增量。文件的 FILEGROWTH 设置不能超过 MAXSIZE 设置。

 

l        growth_increment,每次需要新的空间时为文件添加的空间大小。指定一个整数,不要包含小数位。0 值表示不增长。该值可以 MB、KB、GB、TB 或百分比 (%) 为单位指定。如果未在数量后面指定MB、KB 或 %,则默认值为 MB。如果指定 %,则增量大小为发生增长时文件大小的指定百分比。如果没有指定 FILEGROWTH,则默认值为 10%,最小值为 64 KB。指定的大小舍入为最接近的 64 KB 的倍数。

 

l        <filegroup>,控制文件组的属性。文件组不能在数据库快照上定义。

 

l        FILEGROUP,定义文件组的逻辑名。

 

l        filegroup_name,表示在创建数据库之后,在Transact-SQL语句中引用文件组的名称。filegroup_name在数据库中必须唯一,不能是系统提供的名称,如PRIMARY和PRIMARY_LOG。名称必须同标识符的规则保持一致。

 

l        default,定义文件组为特定文件组类型的默认数据库文件组。

 

l        DB_CHAINING { ON | OFF },当设置为ON的时候,数据库可以为交叉数据库所有者关系链中的源或者目标。当设置为OFF的时候,数据库不能参与交叉数据库所有者关系链,对于用户数据库,可以修改这个选项,但是不能修改系统数据库的该选项。默认值为OFF。

 

l        TRUSTWORTHY { ON | OFF },当设置为ON的时候,数据库模块(如视图、用户自定义函数或者存储过程)允许访问数据库外的资源。当设置为OFF的时候,数据库模块不能访问数据库之外的资源。默认值为OFF。

 

l        <service_broker_options> ,当授予FOR ATTACH子句的时候,才能设置Service Broker选项。

 

l        ENABLE_BROKER,定义数据库是否启用ServiceBroker。

 

l        NEW_BROKER,在sys数据库中和恢复数据库中创建新的service_broker_guid。

 

l        ERROR_BROKER_CONVERSATIONS,终止所有发生错误的会话。

 

l        database_snapshot_name,定义新数据库的快照名。

 

l        ON (NAME =logical_file_name, FILENAME =’os_file_name’) [ ,... n ] ,对于创建一个数据库快照,在源数据库中定义文件列表。

 

l        AS SNAPSHOT OF source_database_name,定义创建的数据库为一个源数据库的数据库快照。

 

几道数据库的面试题或笔试题难度适中

 

1.张表,学生表S,课程C,学生课程表SC,学生可以选修多门课程,一门课程可以被多个学生选修,通过SC表关联;(SQL)

1)写出建表语句;

答:建表语句如下(mysql数据库):

create tables(id integer primary key, name varchar(20));

create tablec(id integer primary key, name varchar(20));

create table sc(

sid integerreferences s(id),

cid integerreferences c(id),

primarykey(sid,cid)

);

2)写出SQL语句,查询选修了所有选修课程的学生;

答:SQL语句如下:

select stu.id,stu.name from s stu

where (selectcount(*) from sc where sid=stu.id) =

(select count(*)from c);

3)写出SQL语句,查询选修了至少5门以上的课程的学生。

答:SQL语句如下:

select stu.id,stu.name from s stu

where (selectcount(*) from sc where sid=stu.id)>=5;

 

2.数据库表(Test)结构如下:(SQL)

IDNAMEAGEMANAGER(所属主管人ID)

106A30104

109B19104

104C20111

107D35109

112E25120

119F45NULL

要求:列出所有年龄比所属主管年龄大的人的ID和名字?

答:SQL语句如下:

selectemployee.name from test employee where employee.age>

(selectmanager.age from test manager where manager.id=employee.manager);

 

3.有3个表(15分钟):(SQL)

Student 学生表 (学号,姓名,性别,年龄,组织部门)

Course 课程表 (编号,课程名称)

Sc 选课表 (学号,课程编号,成绩)

表结构如下:

 

1)写一个SQL语句,查询选修了’计算机原理’的学生学号和姓名(3分钟)

答:SQL语句如下:

select stu.sno,stu.sname from Student stu

where (selectcount(*) from sc where sno=stu.sno and cno =

(select cno fromCourse where cname=’计算机原理’)) != 0;

2)写一个SQL语句,查询’周星驰’同学选修了的课程名字(3分钟)

答:SQL语句如下:

select cnamefrom Course where cno in (select cno from sc where sno=(select snofrom Studentwhere sname=’周星驰’));

3)写一个SQL语句,查询选修了5门课程的学生学号和姓名(9分钟)

答:SQL语句如下:

select stu.sno,stu.sname from student stu

where (selectcount(*) from sc where sno=stu.sno) = 5;

 

ORACLE面试测试题目

 

1.    解释FUNCTION,PROCEDURE和PACKAGE区别

答:function 和procedure是PL/SQL代码的集合,通常为了完成一个任务。procedure 不需要返回任何值而function将返回一个值在另一方面,Package是为了完成一个商业功能的一组function和procedure的集合。

 

2.    取某个序列的当前值的PL/SQL语句怎么写?

答:SELECT 序列名.CURRVAL FROM  DUAL;

 

3.    说明ORACLE数据库实例与ORACLE用户的关系?

答:实例可以包含多个用户,一个用户只能在一个实例下

 

4.    创建数据库时,自动建立的tablespace名称?

答:SYSTEM tablespace

 

5.    创建用户时,需要赋予新用户什么权限才能使它连上数据库?

答:CONNECT

 

6.   IMPORT和SQL*LOADER这2个工具的不同点?

答:这两个ORACLE工具都是用来将数据导入数据库的。

区别是:IMPORT工具只能处理由另一个ORACLE工具EXPORT生成的数据。而SQL*LOADER可以导入不同的ASCII格式的数据源。

 

7.解释冷备份和热备份的不同点以及各自的优点?

答:热备份针对归档模式的数据库,在数据库仍旧处于工作状态时进行备份。而冷备份指在数据库关闭后,进行备份,适用于所有模式的数据库。热备份的优点在于当备份时,数据库仍旧可以被使用并且可以将数据库恢复到任意一个时间点。冷备份的优点在于它的备份和恢复操作相当简单,并且由于冷备份的数据库可以工作在非归档模式下,数据库性能会比归档模式稍好。(因为不必将archive log写入硬盘)

 

8.比较truncate和delete命令?

答:两者都可以用来删除表中所有的记录。区别在于:truncate是DDL(data defininglanguage数据定义语言),它移动HWK,不需要rollback segment(处理事务回滚操作)而Delete是DML(datamanufacturinglanguage数据操作语言)操作,需要rollbacksegment(处理事务回滚操作)且花费较长时间。

 

9.给出数据的相关约束类型?

答:主键约束,外键约束,非空约束,唯一约束,检查约束。

 

10.说明索引的类型与作用?

答:索引类型上分为聚集索引,非聚集索引其作用是加快查询速度。

 

11.解释归档和非归档模式之间的不同和它们各自的优缺点

答:归档模式是指你可以备份所有的数据库 transactions并恢复到任意一个时间点。非归档模式则相反,不能恢复到任意一个时间点。但是非归档模式可以带来数据库性能上的少许提高。

 

12.解释$ORACLE_HOME和$ORACLE_BASE的区别?

答:ORACLE_BASE是oracle的根目录,ORACLE_HOME是oracle产品的目录。

 

13.获取某个字符字段的最后3个字符的函数是什么?

答:select substr (字段,(length(字段)-3)) from 表

 

14.取当前系统时间点日期(不包括年月)的SQL写法是怎样的?

答:Select substr(to_char(sysdate,’YYYYMMDDh24hh:MM:SS’),5) from dual;

 

15.返回大于等于N的最小整数值?

答:select ceil(N) from dual;

 

16.将根据字符查询转换后结果,规则为:’A’转换为’男’,’B’转换为’女’,其他字符转换为’未知’,请用一个SQL语句写出。

答:select decode(字符,’A’,’男’,’B’,’女’,’未知’) fromdual;

 

17.如何搜索出前N条记录?

答:select * from 表 where Rownum <= N;

 

18.如何搜索出第N~M条记录?

答:select * from 表 where Rownum<= M

Minus

select * from 表 where Rownum <= N;

 

19.有一个数据表(TEST),字段如下:

ID      number

PARENT_ID      number

NAME      Varchar(20)

请使用PL/SQL来按父子层次关系查询出该表的所有数据

答:Select * from test a, test b Where a.parent_id =b.id;

 

20.怎样用SQL语句实现查找一列中的第N大值?

答:select * from (select * from 表 order by 列名 Desc) where Rownum <= N

Minus

select * from(select * from 表 order by 列名 Desc) where Rownum <= N-1;

 

腾讯公司的一个sql题

 

小小+霸霸+王王=小霸王

小=?,霸=?,王=?

用sql求证

 

参考答案:

 

declare@dataint,@i int,@j int,@l int

set @data=100

while(@data<=999)

begin

   set @i=@data/100

   set @j=@data/10 % 10

   set @l=@data % 10

   if((@i+@j+@l)*11=@data)

   begin

      Select @data data,@i i,@j j,@l l

      break

   end

   set @data=@data+1

end;

分析:

II+JJ+LL=IJL

I*10+I+J*10+J+L*10+L   =   I*100+J*10+L

(I+J+L)*11

 

1、  一套Oracle面试题笔试题

 

完成下列操作,写出相应的SQL语句

 

创建表空间neuspace,数据文件命名为neudata.dbf,存放在d:\data目录下,文件大小为200MB,设为自动增长,增量5MB,文件最大为500MB。(8分)

答:createtablespace neuspace datafile ‘d:\data\neudata.dbf’ size 200m auto extend on next 5m maxsize 500m;

 

2. 假设表空间neuspace已用尽500MB空间,现要求增加一个数据文件,存放在e:\appdata目录下,文件名为appneudata,大小为500MB,不自动增长。(5分)

 

答:altertablespace neuspace add datafile ‘e:\appdata\appneudata.dbf’ size 500m;

 

3. 以系统管理员身份登录,创建账号tom,设置tom的默认表空间为neuspace。为tom分配connect和resource系统角色,获取基本的系统权限。然后为tom分配对用户scott的表emp的select权限和对SALARY, MGR属性的update权限。(8分)

 

答:create usertom identified by jack default tablespace neuspace;

 

Grantconnect,resource to tom;

 

Grantselect,update(salary, mgr) on scott.emp to tom;

 

4. 按如下要求创建表class和student。(15分)

 

属性

类型(长度)

默认值

约束

含义

CLASSNO

数值 (2)

主键

班级编号

CNAME

变长字符 (10)

非空

班级名称

 

 

属性

类型(长度)

默认值

约束

含义

STUNO

数值 (8)

主键

学号

SNAME

变长字符 (12)

非空

姓名

SEX

字符 (2)

性别

BIRTHDAY

日期

生日

EMAIL

变长字符 (20)

唯一

电子邮件

SCORE

数值 (5, 2)

检查

成绩

CLASSNO

数值 (2)

外键,关联到表CLASS的CLASSNO主键

班级编号

答:createtable class

 

(classnonumber(2)constraint class_classno_pk primary key,

 

cnamevarchar2(10)not null);

 

createtablestudent

 

(stunonumber(8)constraint student_stuno_pk primary key,

 

snamevarchar2(12)not null,

 

sexchar(2)default ‘男’,

 

birthday date,

 

emailvarchar2(20)constraint student_email_uk unique,

 

scorenumber(5,2)constraint student_score_ck check(score>=0 and score<=100),

 

classnonumber(2)constraint student_classno_fk references class(classno)

 

);

 

5. 在表student的SNAME属性上创建索引student_sname_idx(5分)

 

答:createindex student_sname_idx on student(sname);

 

6. 创建序列stuseq,要求初值为20050001,增量为1,最大值为20059999。(6分)

 

答:createsequence stuseq increment by 1 start with 20050001 maxvalue20059999 nocachenocycle;

 

7. 向表student中插入如下2行。(5分)

 

STUNO

SNAME

SEX

BIRTHDAY

EMAIL

SCORE

CLASSNO

从stuseq取值

tom

1979-2-314:30:25

tom@163.net

89.50

1

从stuseq取值

jerry

默认值

2

答:insert intostudent values(stuseq.nextval, ’tom’, ’男’, to_date(‘1979-2-3

 

14:30:25’,’yyyy-mm-dd fmhh24:mi:ss’), ’tom@163.net’,89.50, 1);

 

insertintostudent (stuno, sname, classno) values(stuseq.nextval, ’jerry’, 2);

 

8. 修改表student的数据,将所有一班的学生成绩加10分。(4分)

 

答:updatestudent set score=score+10 where classno=1;

 

9. 删除表student的数据,将所有3班出生日期小于1981年5月12日的记录删除。(4分)

 

答:delete fromstudent where classno=3 and birthday > ’12-5月-81’;

 

10. 完成以下SQL语句。(40分)

 

(1) 按班级升序排序,成绩降序排序,查询student表的所有记录。

 

答:select *from student order by classno, score desc;

 

(2) 查询student表中所有二班的成绩大于85.50分且出生日期大于1982-10-31日的男生的记录。

 

答:select *from student where classno=2 and score>85.50 and birthday< ’31-10月-82’and sex=’男’;

 

(3) 查询student表中所有三班成绩为空的学生记录。

 

答:select *from student where classno=3 and score is null;

 

(4) 表student与class联合查询,要求查询所有学生的学号,姓名,成绩,班级名称。(使用oracle与SQL 99两种格式)

 

答:selects.stuno, s.sname, s.score, c.cname from student s, class cwheres.classno=c.classno;

 

(5) 按班级编号分组统计每个班的人数,最高分,最低分,平均分,并按平均分降序排序。

 

答:selectclassno, count(*), max(score), min(score), avg(score) fromstudent group byclassno order by avg(score) desc;

 

(6) 查询一班学生记录中所有成绩高于本班学生平均分的记录。

 

答:select *from student where classno=1 and score > (selectavg(score) from studentwhere classno=1);

 

(7) 统计二班学生中所有成绩大于所有班级平均分的人数。

 

答:selectcount(*) from student where classno=2 and score > all(select avg(socre)from student group by classno);

 

(8) 查询平均分最高的班级编号与分数。

 

答:selectclassno, avg(score) from student group by classno havingavg(score) = (selectmax(avg(score)) from student group by classno);

 

(9) 查询所有学生记录中成绩前十名的学生的学号、姓名、成绩、班级编号。

 

答:selectstuno, sname, score, classno from (select * from student orderby score desc)where rownum<=10;

 

(10) 创建视图stuvu,要求视图中包含student表中所有一班学生的stuno, sname, score, classno四个属性,并具有with check option限制。

 

答:create viewstuvu

 

as

 

selectstuno,sname,score,classno from student where classno=1 with check option;

 

2、  一道Oracle笔试题

 

表结构说明:

create tableemployee(

id number(10)not null, — 员工工号

salarynumber(10,2) default 0 not null, — 薪水

namevarchar2(24) not null — 姓名

);

1.创建序列seq_employee,该序列每次取的时候它会自动增加,从1开始计数,不设最大值,并且一直累加,不循环。(10分)

2.写一个PL/SQL块,插入表user.employee中100条数据。插入该表中字段id用序列seq_employee实现,薪水和姓名字段可以任意填写。(15分)

 

 

 

6.写一个匿名语句块,用于执行函数f_employee,并打印执行该函数的结果。(8分)

7.创建存储过程p_create_emp,用于判断表employee是否存在,如果存在则删除该表。(15分)

8.写一个匿名语句块,用于执行存储过程p_create_emp。(7分)

答案如下:

SQL> createtable employee(

2 id number(10)not null, — 员工工号

3 salarynumber(10,2) default 0 not null, — 薪水

4 namevarchar2(24) not null — 姓名

5 );

表已创建。

—第一题答案:

SQL> Createsequence seq_employee increment by 1 start with 1 nomaxvaluenocycle;

序列已创建。

—第二题答案:

SQL> declarei number;

2 begin

3 for i in 1 ..100

4 loop

5 insert intoemployee

6values(seq_employee.nextval,1950+i,’王明’||to_char(i));

7 commit;

8 end loop;

9 end;

10 /

PL/SQL 过程已成功完成。

SQL> select *from employee where rownum<11;

ID SALARY NAME

———- ———- ————————

1 1951 王明1

2 1952 王明2

3 1953 王明3

4 1954 王明4

5 1955 王明5

6 1956 王明6

7 1957 王明7

8 1958 王明8

9 1959 王明9

10 1960 王明10

已选择10行。

3.写一个语句块,在语句块中定义一个显式游标,按id升序排列,打印表employee中前十条数据。(15分)

——-第三题答案:

SQL> declare

2 cursor c isselect id,salary,name from(select * from employee order by id)whererownum<11;

3 v_recordc%rowtype;

4 begin

5 open c;

6 loop

7 fetch c intov_record;

8 exit whenc%notfound;

9dbms_output.put_line(to_char(v_record.id)||’,'||to_char(v_record.salary)||’,'||v_record.name);

10 end loop;

11 close c;

12 end;

13 /

1,1951,王明1

2,1952,王明2

3,1953,王明3

4,1954,王明4

5,1955,王明5

6,1956,王明6

7,1957,王明7

8,1958,王明8

9,1959,王明9

10,1960,王明10

PL/SQL 过程已成功完成。

4.创建存储过程p_employee,输入员工薪水范围,返回员工工号、姓名、薪水结果集,结果集按员工薪水升序排列。(15分)

——-第四题答案

SQL> createor replace procedure p_employee

2 (iminsalary innumber,

3 imaxsalary innumber)

4 is

5 begin

6 for xin(select id,salary,name from(select * from employee where salarybetweeniminsalary and imaxsalary) order by salary)

7 loop

8dbms_output.put_line(to_char(x.id)||to_char(x.salary)||x.name);

9 end loop;

10 end;

11 /

过程已创建。

SQL> execp_employee(2000,2007);

502000王明50

512001王明51

522002王明52

532003王明53

542004王明54

552005王明55

562006王明56

572007王明57

PL/SQL 过程已成功完成。

5.创建函数f_employee实现更新员工薪水的功能,将薪水低于2000且姓wang的员工薪水加5%,其他不变,更新成功则返回0,否则返回1。(15分)

———第五题答案

SQL> createor replace function f_employee return number

is

begin

update employeeset salary=salary+salary*0.05 where salary<2000 and namelike ‘王%’;

commit;

ifsql%rowcount=0 then

return 1;

else

return 0;

end if;

end;

/

函数已创建。

—–第六题答案

SQL> declarea number;

2 begin

3a:=f_employee();

4dbms_output.put_line(to_char(a));

5 end;

6 /

0

PL/SQL 过程已成功完成。

SQL> select *from employee where salary<2000 and name like ‘王%’;

未选定行

SQL> select *from employee where rownum<50;

ID SALARY NAME

———- ———- ————————

1 2048.55 王明1

2 2049.6 王明2

3 2050.65 王明3

4 2051.7 王明4

5 2052.75 王明5

6 2053.8 王明6

7 2054.85 王明7

8 2055.9 王明8

9 2056.95 王明9

10 2058 王明10

11 2059.05 王明11

ID SALARY NAME

———- ———- ————————

12 2060.1 王明12

13 2061.15 王明13

14 2062.2 王明14

15 2063.25 王明15

16 2064.3 王明16

17 2065.35 王明17

18 2066.4 王明18

19 2067.45 王明19

20 2068.5 王明20

21 2069.55 王明21

22 2070.6 王明22

ID SALARY NAME

———- ———- ————————

23 2071.65 王明23

24 2072.7 王明24

25 2073.75 王明25

26 2074.8 王明26

27 2075.85 王明27

28 2076.9 王明28

29 2077.95 王明29

30 2079 王明30

31 2080.05 王明31

32 2081.1 王明32

33 2082.15 王明33

ID SALARY NAME

———- ———- ————————

34 2083.2 王明34

35 2084.25 王明35

36 2085.3 王明36

37 2086.35 王明37

38 2087.4 王明38

39 2088.45 王明39

40 2089.5 王明40

41 2090.55 王明41

42 2091.6 王明42

43 2092.65 王明43

44 2093.7 王明44

ID SALARY NAME

———- ———- ————————

45 2094.75 王明45

46 2095.8 王明46

47 2096.85 王明47

48 2097.9 王明48

49 2098.95 王明49

已选择49行。

—–第七题答案

SQL> createor replace procedure p_create_emp

2 is

3 v_countnumber;

4 begin

5 selectcount(*) into v_count from user_tables where table_name=’EMPLOYEE’;

6 if v_count=0then

7 return;

8 else

9 executeimmediate ‘drop table employee’;

10 end if;

11 end;

12 /

过程已创建。

 

———第八题答案

SQL> execp_create_emp;

PL/SQL 过程已成功完成。

SQL> select *from employee;

select * fromemployee

*

ERROR 位于第 1 行:

ORA-00942: 表或视图不存在

 

如何查询Oracle数据库中已经创建的索引?

 

查询数据字典user_indexes和user_ind_columns

 

例子:

 

SQL>SELECTic.index_name, ic.column_name,

 

2        ic.column_positioncol_pos,ix.uniqueness

 

3 FROM    user_indexes ix, user_ind_columns ic

 

4 WHERE   ic.index_name = ix.index_name

 

5  AND ic.table_name= ‘S_EMP’;

 

注意: 数据字典里存放的字符都是大写的.

 

哪些情况下不应该使用索引?

 

1. 表很小的情况下,没有必要使用索引

 

2. 不经常在Where后使用的比较字段

 

3. 如果表数据需要频繁修改,不建议使用索引

 

4. 如果查询返回记录很多,不建议使用索引

 

5. 如果where后含IS NULL/IS NOT NULL/ like ‘%输入符%’等条件,不建议使用索引。

 

SQL里面如何插入自动增长序列号字段?

 

INSERT时如果要用到从1开始自动增长的数字做唯一关键字, 应该先建立一个序列号.

 

CREATE SEQUENCE 序列号的名称 (最好是表名+序列号标记) INCREMENTBY 1 START WITH 1 MAXVALUE 99999 NOCYCLE NOCACHE;

 

其中最大的值按字段的长度来定,比如定义的自动增长的序列NUMBER(6), 最大值为999999

 

INSERT 语句插入这个字段值为: 序列号的名称.NEXTVAL

 

例子: SQL>insert into s_dept(id, name, region_id) values(s_dept_id.nextval, ‘finance’,2);

 

1 row created.

 

只有运行了序列号的名称.nextval后序列号的名称. currval 才有效才有值.

 

不用游标的SQL语句有哪些?

 

1. 说明性语句

2. 数据定义语句

3. 数据控制语句

4. 查询结果为单记录的SELECT语句

5. 非CURRENT形式的UPDATE语句

6. 非CURRENT形式的DELETE语句

7. INSERT语句

所有的说明性语句及数据定义与控制语句都不需要使用游标,他们是嵌入式SQL中最简单的一类语句,不需要返回结果数据,也不需要使用主变量。在主语言中嵌入说明性语句及数据定义与控制语句,只要给语句加上前缀EXEC SQL 和预计结束符即可。

INSERT语句也不需要使用游标,但通常需要使用主变量

SELECT语句,UPDATE语句,DELETE语句则要复杂些。

 

必须要使用游标的SQL语句有那些?

 

必须要使用游标的SQL语句有:

1. 查询结果为多结果的SELECT语句

2. CURRENT形式的UPDATE语句

3. CURRENT形式的DELETE语句

 

查询优化的一般准则有哪些?

 

1. 选择运算应尽可能先做。这是优化策略中最重要最基本的一条

2. 在执行连接前对关系适当的预处理,方法有两种:在连接属性上建立索引和对关系排序,然后执行连接,第一种称为索引连接方法,第二种称为排序合并连接方法

3. 把投影运算和选择运算同时进行。

4. 把投影同其前或者其后的双目运算结合起来,没有必要为了去掉某些字段而扫描一下关系

5. 把某些选择同它前面要执行的笛卡尔积结合起来成为一个连接运算,连接特别是等值连接运算要比同样关系上的笛卡尔积节省很多时间

6. 找出公共子表达式,先计算出公共子表达式的值才参与运算。

 

ORACLE二十问

 

1. Oracle安裝完成后的初始口令? 

 

  internal/oracle

   sys/change_on_install

    system/manager

    scott/tiger

    sysman/oem_temp  

 

  2.ORACLE9IAS WEB CACHE的初始默认用户和密码?  

 

  administrator/administrator 

 

  3. oracle 8.0.5怎么创建数据库?  

 

   用orainst。如果有motif界面,可以用orainst /m 

 

  4. oracle 8.1.7怎么创建数据库?

 

   dbassist 

 

  5. oracle9i 怎么创建数据库? 

 

   dbca  

 

  6. oracle中的裸设备指的是什么?  

 

   裸设备就是绕过文件系统直接访问的储存空间 

 

  7. oracle如何区分 64-bit/32bit 版本??? 

 

  $ sqlplus‘/ AS SYSDBA’

  SQL*Plus: Release 9.0.1.0.0– Production on Mon Jul 14 17:01:09 2003

  (c) Copyright 2001 Oracle Corporation. All rightsreserved.

  Connected to:

  Oracle9i Enterprise Edition Release 9.0.1.0.0 –Production

  With the Partitioning option

  JServer Release 9.0.1.0.0 – Production

  SQL> select * from v$version;

  BANNER

  Oracle9i Enterprise Edition Release 9.0.1.0.0 –Production

  PL/SQL Release 9.0.1.0.0 – Production

  CORE 9.0.1.0.0 Production

  TNS for Solaris: Version 9.0.1.0.0 – Production

  NLSRTL Version 9.0.1.0.0 – Production

  SQL>  

 

  8. SVRMGR什么意思? 

 

  svrmgrl,Server Manager.

 

  9i下没有,已经改为用SQLPLUS了

 

  sqlplus/nolog

  变为归档日志型的 

 

  9. 请问如何分辨某个用户是从哪台机器登陆ORACLE的?

 

  SELECTmachine , terminal FROM V$SESSION;  

 

  10. 用什么语句查询字段呢? 

 

  desctable_name 可以查询表的结构

  select field_name,… from … 可以查询字段的值

  select * from all_tables where table_name like ‘%’

  select * from all_tab_columns where table_name=’??’  

 

  11. 怎样得到触发器、过程、函数的创建脚本? 

 

  descuser_source

  user_triggers   

 

  12. 怎样计算一个表占用的空间的大小? 

 

selectowner,table_name,

  NUM_ROWS,

  BLOCKS*AAA/1024/1024 “Size M”,

  EMPTY_BLOCKS,

  LAST_ANALYZED

  from dba_tables

  where table_name=’XXX’;

  Here: AAA is the value of db_block_size ;

  XXX is the table name you want to check 

 

 14. 如何查看系统被锁的事务时间?

  select * from v$locked_object ;

 

  15. 如何以archivelog的方式运行oracle。

  init.ora

  log_archive_start = true

  RESTART DATABASE

  16. 怎么获取有哪些用户在使用数据库

  select username from v$session;

 

  17. 数据表中的字段最大数是多少?

 

  表或视图中的最大列数为1000  

 

  18. 怎样查得数据库的SID ?

 

  select namefrom v$database;

 

  也可以直接查看init.ora文件

 

  19. 如何在Oracle服务器上通过SQLPLUS查看本机IP地址 ?

 

  selectsys_context(’userenv’,'ip_address’) from dual;

 

  如果是登陆本机数据库,只能返回127.0.0.1,呵呵  

 

  20. unix 下怎么调整数据库的时间?

 

  su -root

 

  date -u08010000

 

 

 

如何高效率的查找一个月以内的数据?

 

进行时间比较要尽量避免用sysdate.比如:如果使用select * from eventtable whereeventdate>sysdate-30进行查找,当数据量小的时候看不出来,数据量大一些就会发现执行很慢,但日期型字段上也是有索引的,为什么会慢呢?原来是Oracle在进行查找的时候不断地去取sysdate这个不断变化的值,而不是我们想象中的一次产生一个条件语句然后进行查找。为了加快速度,我 们可以先把当天的日期取出来,然后转成字符串后再用如下语句查,select * fromeventtable where eventdate > to_date(’2001-12-1′,’yyyy-mm-dd’)。速度相差几十倍。

 

Oracle怎样计算一个表占用的空间的大小?

 

可以使用一下语句来进行计算:

 

select owner ,

table_name,

NUM_ROWS,

BLOCKS*AAA/1024/1024“Size M”,

EMPTY_BLOCKS,

LAST_ANALYZED

from dba_tables

wheretable_name= XXX ;

AAA 是指 db_block_size的值 ;

XXX 是你要查询的表名

 

如何在Oracle中查看各个表、表空间占用空间的大小?

 

使用以下语句查看当前用户每个表占用空间的大小:

SelectSegment_Name,Sum(bytes)/1024/1024 From User_Extents Group BySegment_Name

 

使用一下语句查看每个表空间占用空间的大小:

SelectTablespace_Name,Sum(bytes)/1024/1024 From Dba_Segments Group ByTablespace_Name

 

介绍一下Oracle的操作符优化?

 

IN :

 

IN写出来的SQL比较容易写及清晰易懂但是性能总是比较低的,从ORACLE执行的步骤来分析用IN的SQL与不用IN的SQL有以下区别:

 

ORACLE 试图将IN转换成多个表的连接,如果转换不成功会先执行IN里面的子查询,再查询外层的表记录,如果转换成功,则直接采用多个表的连接方式查询。所以用 IN的SQL至少多了一个转换的过程。一般的SQL都可以转换成功,但对于含有分组统计等方面的SQL就不能转换了。

 

推荐方法:在业务密集的SQL当中尽量不要采用IN操作符。

 

NOT IN:

 

不推荐使用,因为NOTIN不能应用表的索引。

 

推荐方案:用NOTEXISTS 或(外连接+判断为空)

 

<> 操作符(不等于)

 

不等于操作符不会用到索引的,对它的处理只会产生全表扫描。

 

推荐方案:用其它相同功能的操作运算代替,如 a<>0 改为 a>0 or a<0 a<>’’ 改为 a>’’

 

IS NULL 或ISNOT NULL操作(判断字段是否为空)

 

判断字段是否为空一般不会应用索引,因为B树索引是不索引空值的。

 

推荐方案:

 

用其它相同功能的操作运算代替,如 a is not null 改为 a>0 或a>’’等。

 

不允许字段为空,而用一个缺省值代替空值,如业扩申请中状态字段不允许为空,缺省为申请。

 

建立位图索引(有分区的表不能建,位图索引比较难控制,如字段值太多索引会使性能下降,多人更新操作会增加数据块锁的现象)。

 

> 及 < 操作符(大于或小于操作符)

 

大于或小于操作符一般不用调整,因为它有索引就会采用索引查找,但有的情况下可以对它进行优化,如一个表有100万记录,一个数值型字段A, 30万记录的A=0,30万记录的A=1,39万记录的A=2,1万记录的A=3。那么执行A>2与A>=3的效果就有很大的区别了,因为 A>2时ORACLE会先找出为2的记录索引再进行比较,而A>=3时ORACLE则直接找到=3的记录索引。

 

LIKE:

 

LIKE 操作符可以应用通配符查询,里面的通配符组合可能达到几乎是任意的查询,但是如果用得不好则会产生性能上的问题,如LIKE ‘%5400%’ 这种查询不会引用索引,而LIKE ‘X5400%’则会引用范围索引。一个实际例子:用YW_YHJBQK表中营业编号后面的户标识号可来查询营业编号 YY_BH LIKE‘%5400%’ 这个条件会产生全表扫描,如果改成YY_BH LIKE ’X5400%’ OR YY_BHLIKE ’B5400%’ 则会利用YY_BH的索引进行两个范围的查询,性能肯定大大提高。

 

Oracle如何查询登陆客户端的机器名?

 

可以用一下语句查询登陆客户端的机器名:

 

selectmachine,terminal from V$SESSION

 

如何提高MySql的安全性?

 

1.如果MYSQL客户端和服务器端的连接需要跨越并通过不可信任的网络,那么需要使用ssh隧道来加密该连接的通信。

 

2.使用set password语句来修改用户的密码,先“mysql -u root”登陆数据库系统,然后“mysql> updatemysql.user set password=password(’newpwd’)”,最后执行“flushprivileges”就可以了。

 

3.Mysql需要提防的攻击有,防偷听、篡改、回放、拒绝服务等,不涉及可用性和容错方面。对所有的连接、查询、其他操作使用基于acl即访问控制列表的安全措施来完成。也有一些对ssl连接的支持。

 

4.设置除了root用户外的其他任何用户不允许访问mysql主数据库中的user表;

 

加密后存放在user表中的加密后的用户密码一旦泄露,其他人可以随意用该用户名/密码相应的数据库;

 

5.使用grant和revoke语句来进行用户访问控制的工作;

 

6.不要使用明文密码,而是使用md5()和sha1()等单向的哈系函数来设置密码;

 

7.不要选用字典中的字来做密码;

 

8.采用防火墙可以去掉50%的外部危险,让数据库系统躲在防火墙后面工作,或放置在dmz区域中;

 

9.从因特网上用nmap来扫描3306端口,也可用telnetserver_host 3306的方法测试,不允许从非信任网络中访问数据库服务器的3306号tcp端口,需要在防火墙或路由器上做设定;

 

10.为了防止被恶意传入非法参数,例如where id=234,别人却输入where id=234 or 1=1导致全部显示,所以在web的表单中使用”或”"来用字符串,在动态url中加入%22代表双引号、%23代表井号、%27代表单引号;传递未检查过的值给mysql数据库是非常危险的;

 

11.在传递数据给mysql时检查一下大小;

 

12.应用程序需要连接到数据库应该使用一般的用户帐号,开放少数必要的权限给该用户;

 

$page_devide$

 

13.在各编程接口(c c++ php perl java jdbc等)中使用特定‘逃脱字符’函数;

 

在因特网上使用mysql数据库时一定少用传输明文的数据,而用ssl和ssh的加密方式数据来传输;

 

14.学会使用tcpdump和strings工具来查看传输数据的安全性,例如tcpdump -l -i eth0 -w -src or dst port 3306 strings。以普通用户来启动mysql数据库服务;

 

15.不使用到表的联结符号,选用的参数 –skip-symbolic-links;

 

16.确信在mysql目录中只有启动数据库服务的用户才可以对文件有读和写的权限;

 

17.不许将process或super权限付给非管理用户,该mysqladminprocesslist可以列举出当前执行的查询文本;super权限可用于切断客户端连接、改变服务器运行参数状态、控制拷贝复制数据库的服务器;

 

18.file权限不付给管理员以外的用户,防止出现load data‘/etc/passwd’到表中再用select 显示出来的问题;

 

19.如果不相信dns服务公司的服务,可以在主机名称允许表中只设置ip数字地址;

 

20.使用max_user_connections变量来使mysqld服务进程,对一个指定帐户限定连接数;

 

21.grant语句也支持资源控制选项;

 

22.启动mysqld服务进程的安全选项开关,–local-infile=0或1 若是0则客户端程序就无法使用local load data了,赋权的一个例子grant insert(user)on mysql.user to ‘user_name’@'host_name’;若使用–skip-grant-tables系统将对任何用户的访问不做任何访问控制,但可以用 mysqladminflush-privileges或mysqladminreload来开启访问控制;默认情况是showdatabases语句对所有用户开放,可以用–skip-show-databases来关闭掉。

 

23.碰到error 1045(28000) access denied foruser ‘root’@'localhost’ (using password:no)错误时,你需要重新设置密码,具体方法是:先用–skip-grant-tables参数启动mysqld,然后执行 mysql -u rootmysql,mysql>update user set password=password(’newpassword’) whereuser=’root’;mysql>flushprivileges;,最后重新启动mysql就可以了。

 

什么是ddl dml和dcl?

 

DDL :数据定义语言,用于定义和管理 SQL 数据库中的所有对象的语言

1.CREATE – to create objects in the database   创建数据库对象

2.ALTER – alters the structure of the database   修改数据库对象

3.DROP – delete objects from the database   删除数据库对象

4.TRUNCATE –remove all records from a table, including all spaces allocatedfor the recordsare removed

TRUNCATE TABLE[Table Name]。

下面是对Truncate语句在MSSQLServer2000中用法和原理的说明:

Truncate table 表名 速度快,而且效率高,因为:

TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同:二者均删除表中的全部行。但 TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少。

DELETE 语句每次删除一行,并在事务日志中为所删除的每行记录一项。TRUNCATE TABLE 通过释放存储表数据所用的数据页来删除数据,并且只在事务日志中记录页的释放。

TRUNCATE TABLE 删除表中的所有行,但表结构及其列、约束、索引等保持不变。新行标识所用的计数值重置为该列的种子。如果想保留标识计数值,请改用 DELETE。如果要删除表定义及其数据,请使用 DROP TABLE 语句。

对于由 FOREIGN KEY 约束引用的表,不能使用TRUNCATE TABLE,而应使用不带 WHERE 子句的DELETE 语句。由于 TRUNCATE TABLE 不记录在日志中,所以它不能激活触发器。

TRUNCATE TABLE 不能用于参与了索引视图的表。

5.COMMENT – add comments to the data dictionary 注释

6.GRANT – gives user’s access privileges to database 授权

7.REVOKE – withdraw access privileges given with theGRANT command   收回已经授予的权限

 

DML:数据操作语言,SQL中处理数据等操作统称为数据操纵语言

1.SELECT – retrieve data from the adatabase           查询数据

2.INSERT – insert data into atable                   添加数据

3.UPDATE – updates existing data within a table    更新数据

4.DELETE – deletes all records from a table, the spacefor the recordsremain   删除

5.CALL – call aPL/SQL or Java subprogram

6.EXPLAIN PLAN –explain access path to data

Oracle RDBMS执行每一条SQL语句,都必须经过Oracle优化器的评估。所以,了解优化器是如何选择(搜索)路径以及索引是如何被使用的,对优化SQL语句有很大的帮助。Explain可以用来迅速方便地查出对于给定SQL语句中的查询数据是如何得到的即搜索路径(我们通常称为Access Path)。从而使我们选择最优的查询方式达到最大的优化效果。

7.LOCK TABLE – control concurrency 锁,用于控制并发

 

DCL:数据控制语言,用来授予或回收访问数据库的某种特权,并控制数据库操纵事务发生的时间及效果,对数据库实行监视等

COMMIT – save work done 提交

SAVEPOINT – identify a point in a transaction to whichyou can later roll back 保存点

ROLLBACK – restore database to original since the lastCOMMIT   回滚

SET TRANSACTION – Change transaction options like what rollbacksegment touse   设置当前事务的特性,它对后面的事务没有影响.

 

什么是数据库的约束?

 

数据库约束是防止非法记录的规则,约束保存在数据字典(datadictionary)中, 约束可以被定义在列级或者表级。

 

Oracle中包括一下集中约束:

 

1. Not Null – 明确一列数据不能包含null值

 

2. Unique – 强制所有数据行不能有重复值

 

3. Primary Key – 每一行数据的唯一标示

 

4. Foreign Key – 强制一列数据与引用表的外键约束关系

 

5. Check – 检查,明确规定一个必须为true的condition

 

Oracle数据库架构中包括几层?每层都有什么元素?

 

Oracle数据库包括一个逻辑层和物理层,物理层包括Oracle磁盘上的文件, 逻辑层用来映射数据和物理层的文件。

 

逻辑层包括一下元素:

 

一个或者多个表空间。

 

数据库Schema: 包括表,集群,索引,视图,存储过程,数据库触发器和sequences.

 

介绍一下SQL中union, intersect 和 minus

 

Union用来返回多个查询的结果的总和去掉重复的结果

 

语法:

SELECT column1,column2 FROM tablename1

UNION

SELECT column1,column2 FROM tablename2;

 

Intersect 用来返回多个查询中共同的结果,intersect会忽略null值

 

语法:

 

SELECTcolumn1,column2 FROM tablename1

INTERSECT

SELECT column1,column2 FROM tablename2;

 

MUNUS返回出现在第一个查询结果中但是不出现在第二个查询结果的结果集。

 

语法:

 

SELECTcolumn1,column2 FROM tablename1

MINUS

SELECT column1,column2 FROM tablename2;

 

主键(Primary Key)约束和唯一性(UNIQUE)约束有什么区别?

 

一个表只能由一个主键,一个表可以有很多个唯一键(UNIQUE Key)

 

主键不允许有null值,UNIQUE允许null值

 

Oracle中delete, truncate 和 drop的区别?

 

Delete命令用来删除表的全部或者一部分数据行,执行delete之后,用户需要提交(commmit)或者回滚(rollback) transaction 来执行删除或者撤销删除, delete命令会触发这个表上所有的delete触发器。

 

Truncate删除表中的所有数据, 这个操作不能回滚,也不会触发这个表上的触发器,TRUNCATE比delete更快,占用的空间更小。

 

Drop命令从数据库中删除表, 所有的数据行,索引和权限也会被删除,所有的DML触发器也不会被触发,这个命令也不能回滚。

 

rowid和rownum有什么不同?

 

RowId是一个数据库内部的概念,表示表的一行,用来快速的访问某行数据

 

Rownum是结果集的一个功能, 例如select * from Student whererownum = 2 就是得到结果集的第二行。

 

视图的作用是什么?

 

数据库视图的作用只要有:

 

1. 数据库视图隐藏了数据的复杂性。

 

2. 数据库视图有利于控制用户对表中某些列的访问。

 

3. 数据库视图使用户查询变得简单。

 

视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据。但是,视图并不在数据库中以存储的数据值集形式存在。行和列数据来自由定义视图的查询所引用的表,并且在引用视图时动态生成。

 

对其中所引用的基础表来说,视图的作用类似于筛选。定义视图的筛选可以来自当前或其它数据库的一个或多个表,或者其它视图。分布式查询也可用于定义使用多个异类源数据的视图。如果有几台不同的服务器分别存储组织中不同地区的数据,而您需要将这些服务器上相似结构的数据组合起来,这种方式就很有用。

 

通过视图进行查询没有任何限制,通过它们进行数据修改时的限制也很少。

 

什么是Oracle的同义词(synonym)? 如何创建synonym?

 

同义词是相当于别名,是为了简化一些表名或者数据对象。当我们以一个用户登陆而要去访问另一个用户创建的数据对象时,我们需要使用用户名.对象名的方法来使用,这样造成对象名难记,麻烦,使用同义词可以解决这个问题。

 

假定我们现在以system的身份的登陆进去,我们需要访问scott用户下面的一个表emp;

 

常规的写法是:select* from scott.emp;

 

现在我们可以先建立一个同义词:

create synonymmy_syn for scott.emp;

 

然后我们这样来访问这个表了:

select * frommy_syn;

 

什么是数据库锁?Oracle中都有哪些类型的锁?

 

锁是用来在多个用户同时访问同一个表的时候保护数据的。它是Oracle的一种并发控制技术。锁使数据库最大并发的情况下保证数据的完整性。Oracle会在需要的时候自动的提供锁的功能。

 

锁的种类:

 

共享锁: 这个锁是数据在被viewed的时候放置的。

 

排他锁: 这种锁在Insert,Update, Delete命令执行的时候放置的,每一条记录同一时间只能有一个排他锁。

 

触发器(trigger)的功能都有哪些?写出一个触发器的例子

 

触发器是数据库中由一个时间触发的特殊的存储过程,他不是由程序条用也不是手工启动的。触发器的执行可以由对一个表的insert,delete, update等操作来触发,触发器经常用于加强数据的完整性约束和业务规则等等。

 

触发器的功能主要有一下六种:

 

1、 允许/限制对表的修改

 

2、 自动生成派生列,比如自增字段

 

3、 强制数据一致性

 

4、 提供审计和日志记录

 

5、 防止无效的事务处理

 

6、 启用复杂的业务逻辑

 

Create tablefoo(a number);

Create triggerbiud_foo

Before insert orupdate or delete

On foo

Begin

If user not in(‘DONNY’) then

Raise_application_error(-20001,‘You don’t have access to modify this table.’);

End if;

End;

 

如何杀掉ORACLE里面长期没有释放的锁?

 

如果一个数据库insertupdate delete操作很长时间没有反应,就可能出现了没有正常释放的锁。

 

可以用以下SQL语句杀掉没有正常释放的锁:

 

alter systemkillsession ’sid,serial#’;

 

如何查看当前ORACLE数据库里面锁的情况?

 

查看数据库锁的情况必须要有DBA权限,可以使用一下SQL 语句:

 

         selectobject_id,session_id,locked_modefrom v$locked_object;

 

        selectt2.username,t2.sid,t2.serial#,t2.logon_time

 

         fromv$locked_object t1,v$session t2

 

         wheret1.session_id=t2.sid order byt2.logon_time;

 

长时间出现的锁可能是没有正常释放的锁。

 

Oracle的锁有几种模式?

 

Oracle里面的锁共有一下几种模式:

 

0: none

 

1:  null 空

 

2:Row-S 行共享(RowShare RS): 共享表锁

 

3:Row-X 行专用(RX): 用于行数据的修改

 

4:Share 共享锁(S): 阻止其他DML操作

 

5:S/Row-X 共享行专用(SRX):阻止其他事务操作

 

6:exclusive 专用(X):独立访问使用

 

以上可以看出,数字越大的锁影响的操作越多,锁的级别越高。

 

一般的查询语句是小于2的锁,如select * from*

 

select … from …for update 是2的锁,这时候返回集的数据行都将处于行级(Row-X)独占式锁定,其他对象只能对这些数据进行查询,而不能进行更新或者selectfor update操作。

 

insert/update/delete是3的锁, 在这些操作没有commit之前插入同样的记录会没有反应,因为3的锁必须要等到前一个3的锁执行释放掉以后才能继续。 创建索引的时候也会产生3,4级别的锁。

 

locked_mod为2,3,4的锁,不影响DML(insert,delete,update,select)操作,但是DDL(alter,drop)等修改表结构的操作会提示ora-00054错误。

 

当有主外键约束时执行update/delete操作可能会产生4,5的锁。

 

DDL语句时是6的锁。

 

 

 

 

 

第四章:J2EE高级软件工程师面试题

 

                         -----程序设计题部分

 

 

 

常用排序算法

 

 

packagecom.sort;

 

importjava.util.Random;

 

publicclassNo1Maopao {

    public static void main(String[] args) {

        Random rd = new Random();

//生成随即数组

        int [] src = new int[10];

        for(int i=0;i<10;i++){

           src[i]=rd.nextInt(100);

        }

//排序前打印数组所有元素

        for(int i:src)

           System.out.println(i);

       System.out.println("---------------可爱的分割线-------------------");

        src = sort(src);

//排序后打印数组所有元素

        for(int i:src)

           System.out.println(i);

    }

 

   public static int[] sort(int [] src){

        for (int i = 0; i < src.length;i++){

            for(intj=i;j<src.length;j++){

               if(src[j]<src[i]){

                   int temp = src[j];

                   src[j]=src[i];

                   src[i]=temp;

               }

            }

        }

        return src;

    }

}

二、选择排序:

packagecom.sort;

 

importjava.util.Random;

 

publicclassNo2XuanZhe {

    public static void main(String[] args) {

        Random rd = new Random();

        int[] src = new int[10];

        for (int i = 0; i < 10; i++) {

            src[i] =rd.nextInt(100);

        }

        for (int i : src)

           System.out.println(i);

       System.out.println("---------------可爱的分割线-------------------");

        src = sort(src);

        for (int i : src)

           System.out.println(i);

    }

 

   public static int[] sort(int[] src) {

        int min;

        for (int i = 0; i < src.length;i++){

            min =src[i];

            for (int j =i + 1; j <src.length; j++) {

               if (src[j] < min) {

                   min = src[j];

                   int temp = src[i];

                   src[i] = src[j];

                   src[j] = temp;

               }

            }

        }

        return src;

    }

}

三、插入排序:

package com.sort;

 

importjava.util.Random;

 

publicclassNo3ChaRu {

    public static void main(String[] args) {

        Random rd = new Random();

        int[] src = new int[10];

        for (int i = 0; i < 10; i++) {

            src[i] =rd.nextInt(100);

        }

        for (int i : src)

           System.out.println(i);

       System.out.println("---------------可爱的分割线-------------------");

        src = sort(src);

        for (int i : src)

           System.out.println(i);

    }

 

   public static int[] sort(int[] src) {

        int in, out;

        for (in = 1; in < src.length;in++) {

            int temp =src[in];

            out = in;

            while (out> 0 && src[out- 1] >= temp) {

               src[out] = src[out - 1];

               --out;

            }

            src[out] =temp;

        }

        return src;

    }

}

四、希尔排序:

packagecom.sort;

 

importjava.util.Random;

 

publicclassNo4Xier {

    public static void main(String[] args) {

        Random rd = new Random();

        int[] src = new int[10];

        for (int i = 0; i < 10; i++) {

            src[i] =rd.nextInt(100);

        }

        for (int i : src)

           System.out.println(i);

       System.out.println("---------------可爱的分割线-------------------");

        src = sort(src);

        for (int i : src)

           System.out.println(i);

    }

 

   public static int[] sort(int[] src) {

        int len = src.length;

        int temp, i, j;

        int h = 1;

        while (h <= len / 3)

            h = h * 3 +1;

        while (h > 0) {

            for (i = h;i < len; i++) {

               temp = src[i];

               j = i;

               while (j > h - 1 &&src[j - h] >= temp) {

                   src[j] = src[j - h];

                   j -= h;

               }

               src[j] = temp;

            }

            h = (h - 1)/ 3;

        }

        return src;

    }

}

五、快速排序:

public classNo5Kuaisu {

 

   public static void quickSort(int[] array) {

        quickSort(array, 0, array.length -1);

    }

 

   private static void quickSort(int[] array,int low, int high) {

        if (low < high) {

            int p =partition(array, low, high);

           quickSort(array, low, p - 1);

            quickSort(array,p + 1, high);

        }

 

   }

 

   private static int partition(int[] array,int low, int high) {

        int s = array[high];

        int i = low - 1;

        for (int j = low; j < high; j++){

            if (array[j]< s) {

               i++;

               swap(array, i, j);

            }

        }

        swap(array, ++i, high);

        return i;

    }

 

   private static void swap(int[] array, int i,int j) {

        int temp;

        temp = array[i];

        array[i] = array[j];

        array[j] = temp;

    }

 

   public static void main(String[] args) {

        Random rd = new Random();

        int[] src = new int[10];

        for (int i = 0; i < 10; i++) {

            src[i] =rd.nextInt(100);

        }

        for (int i : src)

           System.out.println(i);

       System.out.println("---------------可爱的分割线-------------------");

        quickSort(src);

        for (int i : src)

           System.out.println(i);

       System.out.println("---------------可爱的分割线-------------------");

    }

}

 

常见算法题目

 

本题的splitStringByComma(String )方法纯属多余,可以用String的split方法一句话代替,且可读性也更强,下面的一段话源自JDK1.6API,StringTokenizer类已不再提倡使用,保留仅为旧代码。

 

StringTokenizer是出于兼容性的原因而被保留的遗留类(虽然在新代码中并不鼓励使用它)。建议所有寻求此功能的人使用String的split方法或 java.util.regex 包。

 

importjava.util.*;

 

publicclassbycomma{

 

   public static String[]splitStringByComma(String source){

 

     if(source==null||source.trim().equals(""))    

 

          return null; 

 

     StringTokenizer commaToker = newStringTokenizer(source,",");

 

     String[] result = new String[commaToker.countTokens()]; 

 

      int i=0; 

 

      while(commaToker.hasMoreTokens()){ 

 

           result[i] =commaToker.nextToken(); 

 

           i++; 

 

       } 

 

      return result;

 

   }

 

   public static void main(String args[]){

 

       String[] s =splitStringByComma("5,8,7,4,3,9,1");

 

        int[] ii = new int[s.length];

 

        for(int i = 0; i<ii.length;i++){

 

            ii[i] =Integer.parseInt(s[i]);

 

           }  

 

       Arrays.sort(ii);   

 

       //asc  

 

       for(int i=0;i<ii.length;i++ ){

 

         System.out.println(ii[i]);  

 

        }

 

      //desc   

 

       for(int i=(s.length-1);i>=0;i--){

 

         System.out.println(ii[i]);   

 

      }           

 

   }

 

}

 

2.编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串。 但是要保证汉字不被截半个,如"我ABC"4,应该截为"我AB",输入"我ABC汉DEF",6,应该输出为"我ABC"而不是"我ABC+汉的半个"。

 

代码:

 

publicstaticboolean isLetter(char c){

 

int k=0X80;

 

returnc/k==0?true:false;

 

 

 

}

 

publicstatic intlengths(String strSrc){

 

if(strSrc==null){

 

return 0;

 

}

 

int len=0;

 

char[]strChar=strSrc.toCharArray();

 

for(inti=0;i<strChar.length;i++){

 

len++;

 

if(!isLetter(strChar[i]))len++;

 

}

 

return len;

 

}

 

 

 

publicstaticString subString(String origin,int len){

 

if(origin==null|| origin.equals("")|| len<1){

 

return"";

 

}

 

if(len>lengths(origin)){

 

returnorigin;

 

}

 

byte[]strByte=newbyte[len];

 

System.arraycopy(origin.getBytes(),0,strByte,0,len);

 

intcount=0;

 

for(inti=0;i<len;i++){

 

intvalue=(int)strByte[i];

 

if(value<0)count++;

 

}

 

if (count %2!=0){

 

//len=(len==1)?++len:--len;

 

--len;

 

}

 

returnnewString(strByte,0,len);

 

}

 

publicstaticvoid main(String[] args) {

 

System.out.println(""+subString("我ABC汉DEF",6));

 

}

 

3、排序都有哪几种方法?请列举。用JAVA实现一个快速排序。

 

排序的方法有:插入排序(直接插入排序、希尔排序),交换排序(冒泡排序、快速排序),选择排序(直接选择排序、堆排序),归并排序,分配排序(箱排序、基数排序)

 

快速排序的伪代码。

 

/ /使用快速排序方法对a[ 0 :n- 1 ]排序从a[ 0 :n- 1 ]中选择一个元素作为m I d d l e,该元素为支点把余下的元素分割为两段left 和r I g h t,使得le f t中的元素都小于等于支点,而right 中的元素都大于等于支点递归地使用快速排序方法对left 进行排序递归地使用快速排序方法对right进行排序所得结果为l e f t + m I dd l e + r I g h t

 

//以下为java程序实现的快速排序算法:

 

publicstaticvoid sort(int[] data) {

 

quickSort(data,0,data.length-1);

 

}

 

publicstaticvoid quickSort(int[] data,int low,int high){

 

intpivotIndex=(low+high)/2;

 

swap(data,pivotIndex,high);

 

intk=partition(data,low-1,high,data[high]);

 

swap(data,k,high);

 

if((k-low)>1)partition(data,low,k-1);

 

if((high-k)>1)partition(data,k+1,high);

 

}

 

publicstatic intpartition(int[] data int low,int high, int pivot ){

 

do {

 

while(data[++low]<pivot);

 

while(high!=0   && data[--high]>pivot);

 

swap(data,low,high);

 

}

 

while(low<high);

 

swap(data,low,high);

 

return low;

 

}

 

publicstaticvoid swap(int[] data int low,int high){

 

inttmp=data[low];

 

data[low]=data[high];

 

data[high]=tmp;

 

}

 

publicstaticvoid main(String[] args){

 

int[] data= newint[]{89,32,425,32,78,1,53,92};

 

sort(data);

 

}

 

4.试用递归的方法写一下计算菲波那契数列的通项f(n),已知f1=1,f2=1,以后每项都是前两项的和。

 

..............

 

publicstaticlong fibonacci(long m){

 

if (m==0 ||m==1)return m;

 

elsereturnfibonacci(m-1)+fibonacci(m-2);

 

}

 

5. 写一个Singleton出来。

 

Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。

 

我的评论:第一种形式是饿汉式单例类,第二种是懒汉式单例类;可以如此速记,饿汉式太饿了,所以迫不及待在内部new出一个实例,而懒汉式太懒了,所以知道应用时才检查有没有实例存在,如不存在才new一个实例出来。

 

一般Singleton模式通常有几种种形式:

 

第一种形式: 定义一个类,它的构造函数为private的,它有一个static的private的该类变量,在类初始化时实例话,通过一个public的getInstance方法获取对它的引用,继而调用其中的方法。

 

PublicclassSingleton {

 

privateSingleton(){}

 

//在自己内部定义自己一个实例,是不是很奇怪?

 

//注意这是private 只供内部调用

 

privatestaticSingleton instance = new Singleton();

 

//这里提供了一个供外部访问本class的静态方法,可以直接访问

 

publicstaticSingleton getInstance() {

 

returninstance;

 

}

 

}

 

第二种形式:

 

publicclassSingleton {

 

privatestaticSingleton instance = null;

 

publicstaticsynchronized Singleton getInstance() {

 

//这个方法比上面有所改进,不用每次都进行生成对象,只是第一次

 

//使用时生成实例,提高了效率!

 

if(instance==null)

 

instance=new Singleton();

 

returninstance;

 

}

 

}

 

其他形式:

 

定义一个类,它的构造函数为private的,所有方法为static的。

 

一般认为第一种形式要更加安全些

 

6、创建一个静态方法,给它传入一个对象,请循环的打印出该对象所在类的类名和所实现的方法名(华为笔试最后一道编程)

 

importjava.lang.reflect.*;

 

publicclassTest{

 

publicstaticvoid test(Object obj){

 

Classclazz=obj.getClass();

 

//System.out.println("类名:"+clazz.getName());

 

Method[]ms=clazz.getDeclaredMethods();

 

longlen=Array.getLength(ms);

 

for(inti=0;i<len;i++){

 

System.out.println("类名:"+clazz.getName()+"方法名:"+ms[i].getName());

 

}

 

}

 

class A{

 

public voidb(){}

 

public voidc(){}

 

public voidd(){}

 

public voide(){}

 

}

 

publicstaticvoid main(String[] args){

 

Testt=newTest();

 

Test.Aa=t.newA();

 

test(a);

 

}

 

}

 

7、假设字符串类似这样的aba和aab就相等,现在随便给你二组字符串,请编程比较他们看是否相等

 

BufferedReaderbr= new BufferedReader(new InputStreamReader(System.in));

 

String s =null;

 

try {

 

s=br.readLine();

 

}catch(IOException e) {

 

e.printStackTrace();

 

}

 

StringTokenizerst= new StringTokenizer(s);

 

String s1=st.nextToken();

 

String s2=st.nextToken();

 

byte[] sa1=s1.getBytes();

 

byte[] sb2=s2.getBytes();

 

Arrays.sort(sa1);

 

Arrays.sort(sb2);

 

String ss1= newString(sa1);

 

String ss2= newString(sb2);

 

if(ss1.equals(ss2))

 

System.out.println("equal");

 

else

 

System.out.println("notequal");

 

8、给你一组字符串如:iu7i8hy4jnb2,让你编程输出里面的数字:7842

 

用正规表达式:"iu7i8hy4jnb2".replaceAll("[^\\d]","");

 

9、给你一组字符串让你把它倒叙输出

 

publicstaticString flashBack(String origin) {

 

Stringresult ="";

 

for (int i=origin.length(); i > 0; i--) {

 

String tmp=origin.substring(i - 1, i);

 

result +=tmp;

 

}

 

returnresult;

 

}

 

10、给你一组字符如{1,3,4,7,2,1,1,5,2},让你输出里面出现次数最多且数值最大的一个,出现几次

 

publicvoidfun4() {

 

int[] a = {4, 1,2, 4, 5, 1, 1, 1, 5, 1, 3, 4, 5 };

 

Arrays.sort(a);

 

for (int i= 0; i< a.length; i++) {

 

System.out.print(a[i]+" ");

 

}

 

System.out.println();

 

intmaxNumber =a[a.length - 1], maxCount = 1;

 

intcurNumber =a[a.length - 1], curCount = 1;

 

for (int i=a.length - 1; i > 0; i--) {

 

curNumber =a[i];

 

if (a[i] ==a[i -1]) {

 

curCount++;

 

} else {

 

System.out.println("i="+i + ",curCount=" + curCount+ ",maxCount=" + maxCount+",maxNumber=" + maxNumber);

 

if(curCount >maxCount) {

 

maxCount=curCount;

 

maxNumber=curNumber;

 

}

 

curCount =1;

 

}

 

}

 

if(curCount >maxCount) {

 

maxCount=curCount;

 

//maxNumber=curNumber;

 

}

 

System.out.println("curCount="+curCount + ",maxCount=" + maxCount + ",maxNumber="+maxNumber);

 

}

 

11、求两个数的公约数,M,N

 

int divisor=1;

 

for (int i= 2; i<= b; i++) {

 

if(a%i==0&&b%i==0){

 

divisor =i;

 

}

 

}

 

System.out.println(a+"和"+b+"的最大公约数是:"+divisor);

 

}

 

12、实现数组复制

 

我的理解:这是深复制,数组a,b不再有关联

 

publicvoidfun8(){

 

int[] a={1,2,3,4,56,7,8};

 

int[] b=(int[])a.clone();

 

Conica.print(a);

 

Conica.print(b);

 

b[0]=100;

 

Conica.print(a);

 

Conica.print(b);

 

}

 

13、冒泡排序的实现

 

publicvoidfun9(){

 

int[] a={1,5,2,6,8,74,1,25,69,8};

 

Conica.print(a);

 

for(inti=0;i<a.length-1; i++){

 

for(intj=0;j<a.length-i-1;j++){

 

if(a[j]>a[j+1]){

 

int temp =a[j];

 

a[j] =a[j+1];

 

a[j+1] =temp;

 

}

 

}

 

}

 

Conica.print(a);

 

}

 

14、编程显示某一文件目录下的文件名

 

publicvoidfun10(){

 

File file =newFile("G:\\03月份");

 

if(file.exists()){

 

if(file.isDirectory()){

 

String[]files =file.list();

 

Conica.println(files);

 

}

 

}

 

}

 

15、从键盘输入4个十进制数字字符,将其转换为4位时间之数并显示出来

 

16、编程实现统计文本文件中某个单词的出现频率,并输出统计结果

 

用HashMap来解决

 

假设单词不存在跨行的,每个单词用,. ;分割

 

publicstaticvoid countNum() throws IOException {

 

BufferedReaderbr= null;

 

try {

 

br =newBufferedReader(new FileReader("c://file.txt"));

 

Map map =newHashMap();

 

for (Strings =br.readLine(); s != null; s = br.readLine()) {

 

StringTokenizerst= new StringTokenizer(s, ",.  ;");

 

while(st.hasMoreTokens()){

 

String temp=st.nextToken();

 

if(map.containsKey(temp)){

 

map.put(temp,newInteger((Integer)map.get(temp) + 1));

 

} else {

 

map.put(temp,newInteger(1));

 

}

 

}

 

}

 

for(Iterator it= map.entrySet().iterator(); it.hasNext();) {

 

Map.Entryentry =(Map.Entry) it.next();

 

System.out.println(entry.getKey()+"-->" + entry.getValue()

 

+"times");

 

}

 

} finally {

 

br.close();

 

}

 

}

 

17、编程模仿DOS下的dir命令,列出某个目录下的内容

 

18、编程说明String和StringBuffer字符串的区别

 

19、编程计算N!的程序,一个使用递归方法,一个不用递归方法

 

递归 :

 

longfuction(intn){

 

if (n==0)return1;

 

else

 

returnn*fuction(n-1);

 

}

 

不递 :

 

long s=1;

 

for(inti=2;i<=n;i++)

 

{

 

s*=i;

 

}

 

20、编程实现ASCII码和Unicode码之间的转换

 

21.用1、2、2、3、4、5这六个数字,用java写一个main函数,打印出所有不同的排列,如:512234、412345等,要求: "4 "不能在第三位, "3 "与 "5 "不能相连.

 

import   java.util.*;

public   class  test   {

       static  int   count=0;

        public  static   void  main(String[]   arg)  {

                Scanner   r=new Scanner(System.in);

                String  s=r.nextLine();

                Pailie(s, "");

                System.out.println("Total:"+count);

           }

            static   void  Pailie(String  s,String   p)   {

                if(s.length() <1)  {

               System.out.println(p);//字符串长度小于1,换行

                count++;

                }

                else   {

                int   index[]=new int[s.length()];

                for(int   i=0; i <s.length();   i++)

 

//该循环将所有字符的第一次出现的位置记      录在数组index中

               index[i]=s.indexOf(s.charAt(i));

                for(int   i=0; i <s.length();   i++)   {

                if(i==index[i])

 

//只有当循环数与第一次记录数相等时才递归,保证相同字符中  的第一个调用

               Pailie(s.substring(1),p+s.substring(0,1));//递归,打印其它字符

              s=s.substring(1)+s.substring(0,1);//循环移位

                       }

                }

        }

}

 

22。一个字符串中可能包含a~z中的多个字符,如有重复,如String data="aavzcadfdsfsdhshgWasdfasdf",求出现次数最多的那个字母及次数,如有多个重复的则都求出。〔金山公司面试题〕

 

importjava.util.ArrayList;

 

importjava.util.Collections;

 

importjava.util.Iterator;

 

importjava.util.TreeSet;

 

publicclassFindRepeatChar {

 

publicstaticvoid doString(String strInput) {

 

char[]chars =strInput.toCharArray();

 

ArrayListlists =new ArrayList();

 

TreeSet set= newTreeSet();

 

for (int i= 0; i< chars.length; i++) {

 

lists.add(String.valueOf(chars[i]));

 

set.add(String.valueOf(chars[i]));

 

}

 

System.out.println(set);

 

Collections.sort(lists);

 

System.out.println(lists);

 

StringBuffersb =new StringBuffer();

 

for (int i= 0; i< lists.size(); i++) {

 

sb.append(lists.get(i));

 

}

 

strInput=sb.toString();

 

System.out.println(strInput);

 

int max =0;

 

StringmaxString= "";

 

ArrayListmaxList= new ArrayList();

 

for(Iterator its= set.iterator(); its.hasNext();) {

 

String os=(String) its.next();

 

int begin=strInput.indexOf(os);

 

int end=strInput.lastIndexOf(os);

 

int value =end -begin + 1;

 

if (value>max && value > 1) {

 

max =value;

 

maxString =os;

 

maxList.add(os);

 

} else if(value== max) {

 

maxList.add(os);

 

}

 

}

 

int index =0;

 

for (int i= 0; i< maxList.size(); i++) {

 

if(maxList.get(i).equals(maxString)){

 

index = i;

 

break;

 

}

 

}

 

System.out.println("出现最多的字符为:");

 

for (int i= 0; i< maxList.size(); i++) {

 

System.out.println(maxList.get(i)+"");

 

}

 

System.out.println();

 

System.out.println("出现最多的次数为:" + max);

 

}

 

publicstaticvoid main(String[] args) {

 

StringstrInput =new String("aavzcadfdsfsdhshgWasdfasdf");

 

doString(strInput);

 

}

 

}

 

 

 

 

 

 

 

第五章:工行数据库相关面试题

 

如何保证数据库的健壮性,容错性

 

为了提高程序的健壮性,可以在PL/SQL块中引

 

入异常处理部分,进行捕捉异常,并根据异常出现的情况进行相应的处理。

 

一、异常的类型

 

    ORACLE异常分为两种类型:系统异常、自定义异常。

 

    其中系统异常又分为:预定义异常和非预定义异常。

 

    1.预定义异常

 

        ORACLE定义了他们的错误编号和异常名字,常见的预定义异常处理Oracle常见的错误

 

  

 

        NO_DATA_FOUND          SELECT ... INTO ... 时,没有找到数据

 

        DUL_VAL_ON_INDEX       试图在一个有惟一性约束的列上存储重复值

 

        CURSOR_ALREADY_OPEN    试图打开一个已经打开的游标

 

        TOO_MANY_ROWS          SELECT ... INTO ... 时,查询的结果是多值

 

        ZERO_DIVIDE            零被整除

 

 

 

    2.非预定义异常

 

        ORACLE为它定义了错误编号,但没有定义异常名字。我们使用的时候,先声名一个异常名,

 

        通过伪过程PRAGMA EXCEPTION_INIT,将异常名与错误号关联起来。

 

 

 

    3.自定义异常

 

        程序员从我们业务角度出发,制定的一些规则和限制。

 

二、异常处理

 

    PL/SQL中,异常处理按个步骤进行:

 

        定义异常

 

        抛出异常

 

        捕获及处理异常

 

 

 

    a.定义异常

 

        exception_name EXCEPTION;

 

 

 

    b.抛出异常

 

        RAISE exception_name

 

 

 

    c.捕获及处理异常

 

        EXCEPTION

 

            WHENe_name1 [OR e_name2 ... ] THEN

 

                statements;

 

            WHENe_name3 [OR e_name4 ... ] THEN

 

                statements;

 

               ......

 

            WHENOTHERS THEN

 

                statements;

 

        END;

 

        /

 

四、使用异常函数处理异常          

 

    1.SQLCODE与SQLERRM函数

 

        函数SQLCODE用于取得Oracle错误号

 

        函数SQLERRM用于取得与错误号对应的相关错误消息

 

2.RAISE_APPLICATION_ERROR

 

        是将应用程序专有的错误从服务器端转达到客户端应用程序(其他机器上的SQLPLUS或者其他前台开发语言)。

 

        该函数用于在PL/SQL中定义错误消息,且只能在数据库端的子程序中使用(存储过程、函数、包、触发器),不能在匿名块和客户端的

 

        子程序中使用

 

五、PL/SQL编译警告

 

    1.PL/SQL警告的分裂

 

        SEVERE: 用于检查可能出现的不可预料结果或错误结果,例如参数的别名问题.

 

        PERFORMANCE:用于检查可能引起性能问题,如在INSERT操作是为NUMBER列提供了VARCHAR2类型数据.

 

        INFORMATIONAL: 用于检查程序中的死代码.

 

        ALL: 用于检查所有警告.

 

  

 

    2.控制PL/SQL警告消息

 

        通过设置初始化参数PLSQL_WARNINGS来启用在编译PL/SQL子程序时发出警告消息,缺省为DISABLE:ALL

 

        警告消息设置的级别

 

            系统级别

 

            会话级别

 

            ALTERPROCEDURE

 

            既可以激活或禁止所有警告类型,也可以激活或禁止特定消息号

 

            scott@ORCL>show parameterplsql%ings;

 

 

 

            NAME                                 TYPE        VALUE

 

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

 

            plsql_warnings                       string      DISABLE:ALL      

 

          

 

            scott@ORCL>ALTER SYSTEMSETPLSQL_WARNINGS='ENABLE:ALL'|'DISABLE:ALL'

 

            scott@ORCL>ALTER SESSIONSETPLSQL_WARNINGS='ENABLE:PERFORMANCE'|'DISABLE:ALL'

 

            scott@ORCL>ALTER PROCEDUREuspCOMPILE PLSQL_WARNINGS='ENABLE:PERFORMANCE';

 

            scott@ORCL>ALTER SESSIONSETPLSQL_WARNINGS='ENABLE:SEVERE','DISABLE:PERFORMANCE','ERROR:06002';

 

  

 

    3.演示PL/SQL编译告警

 

        a.检测死代码

 

            在下面的代码中,ELSE子句永远不会执行,应该避免出现类似的死代码.

 

            从Oracle 10g开始,在编写PL/SQL子程序之前开发人员可以激活警告检查.

 

          

 

                scott@ORCL> get/u01/bk/scripts/dead_code.sql

 

                 1  CREATEOR REPLACE PROCEDURE dead_code AS

 

                 2     x number := 10;

 

                 3  BEGIN

 

                 4     IFx>0 THEN

 

                 5            x:=1;

 

                 6     ELSE            

 

                 7             x:=2;    --死代码

 

                 8     ENDIF;

 

                 9* ENDdead_code;

 

              

 

                scott@ORCL> start/u01/bk/scripts/dead_code.sql

 

              

 

                scott@ORCL> alter sessionset plsql_warnings='enable:informational';

 

              

 

                scott@ORCL> show parameterplsql%ings

 

 

 

                NAME                                 TYPE        VALUE

 

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

 

                plsql_warnings                       string      ENABLE:INFORMATIONAL, DISABLE:

 

                                                                 PERFORMANCE,DISABLE:SEVERE

 

                                                                

 

                scott@ORCL> alter proceduredead_code compile;

 

 

 

                SP2-0805: Procedure alteredwith compilation warnings         

 

 

 

                scott@ORCL> show errors;

 

                Errors forPROCEDURE DEAD_CODE:

 

 

 

                LINE/COLERROR

 

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

 

                4/6      PLW-06002: Unreachable code

 

                7/3      PLW-06002: Unreachablecode

 

      

 

        b.检测引起性能问题的代码

 

            scott@ORCL>create or replaceprocedureupdate_sal

 

             2  (nonumber,salaryvarchar2)

 

             3 as

 

             4 begin

 

             5      updateemp set sal=salarywhere empno=no;

 

             6 end;

 

             7 /

 

 

 

            Procedurecreated.

 

 

 

            scott@ORCL>alter sessionsetplsql_warnings='enable:performance';

 

 

 

            scott@ORCL>alterprocedureupdate_sal compile;

 

 

 

            SP2-0805: Procedure altered withcompilation warnings

 

 

 

            scott@ORCL>show errors

 

            Errors forPROCEDURE UPDATE_SAL:

 

 

 

            LINE/COLERROR

 

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

 

            5/24     PLW-07202: bind type wouldresult inconversion away from column     

 

 

 

索引相关理解

 

1.1 索引的创建语法:

 

CREATEUNIUQE |BITMAP INDEX <schema>.<index_name>

 

      ON <schema>.<table_name>

 

           (<column_name> |<expression> ASC| DESC,

            <column_name> |<expression> ASC| DESC,...)

     TABLESPACE<tablespace_name>

     STORAGE<storage_settings>

     LOGGING |NOLOGGING

    COMPUTESTATISTICS

     NOCOMPRESS | COMPRESS<nn>

     NOSORT |REVERSE

     PARTITION| GLOBALPARTITION<partition_setting>

 

 

 

相关说明

 

1) UNIQUE | BITMAP:指定UNIQUE为唯一值索引,BITMAP为位图索引,省略为B-Tree索引。

2)<column_name> |<expression> ASC |DESC:可以对多列进行联合索引,当为expression时即“基于函数的索引”

3)TABLESPACE:指定存放索引的表空间(索引和原表不在一个表空间时效率更高)

4)STORAGE:可进一步设置表空间的存储参数

5)LOGGING | NOLOGGING:是否对索引产生重做日志(对大表尽量使用NOLOGGING来减少占用空间并提高效率)

6)COMPUTE STATISTICS:创建新索引时收集统计信息

7)NOCOMPRESS |COMPRESS<nn>:是否使用“键压缩”(使用键压缩可以删除一个键列中出现的重复值)

8)NOSORT | REVERSE:NOSORT表示与表中相同的顺序创建索引,REVERSE表示相反顺序存储索引值

9)PARTITION | NOPARTITION:可以在分区表和未分区表上对创建的索引进行分区

 

 

 

 

 

1.2 索引特点:

 

第一,通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。

 

第二,可以大大加快数据的检索速度,这也是创建索引的最主要的原因。

 

第三,可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。

 

第四,在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。

 

第五,通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。

 

 

 

 

 

1.3 索引不足:

 

第一,创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。

 

第二,索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。

 

第三,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。

 

 

 

 

 

1.4 应该建索引列的特点:

 

1)在经常需要搜索的列上,可以加快搜索的速度;

 

2)在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;

 

3)在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;

 

4)在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;

 

5)在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;

 

6)在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。

 

 

 

 

 

1.5 不应该建索引列的特点:

 

第一,对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。

 

第二,对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。

 

第三,对于那些定义为blob数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。

 

第四,当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。

 

 

 

 

 

1.6 限制索引

限制索引是一些没有经验的开发人员经常犯的错误之一。在SQL中有很多陷阱会使一些索引无法使用。下面讨论一些常见的问题:

   1.6.1 使用不等于操作符(<>、!=)     

   下面的查询即使在cust_rating列有一个索引,查询语句仍然执行一次全表扫描。    

   select cust_Id,cust_name fromcustomerswhere  cust_rating <>'aa';       

把上面的语句改成如下的查询语句,这样,在采用基于规则的优化器而不是基于代价的优化器(更智能)时,将会使用索引。       

  select cust_Id,cust_name from customerswherecust_rating < 'aa' or cust_rating > 'aa';

  特别注意:通过把不等于操作符改成OR条件,就可以使用索引,以避免全表扫描。

   1.6.2使用ISNULL 或IS NOT NULL

   使用ISNULL 或IS NOTNULL同样会限制索引的使用。因为NULL值并没有被定义。在SQL语句中使用NULL会有很多的麻烦。因此建议开发人员在建表时,把需要索引的列设成NOTNULL。如果被索引的列在某些行中存在NULL值,就不会使用这个索引(除非索引是一个位图索引,关于位图索引在稍后在详细讨论)。

   1.6.3使用函数

   如果不使用基于函数的索引,那么在SQL语句的WHERE子句中对存在索引的列使用函数时,会使优化器忽略掉这些索引。 下面的查询不会使用索引(只要它不是基于函数的索引)

 select empno,ename,deptno from emp  where trunc(hiredate)='01-MAY-81';

   把上面的语句改成下面的语句,这样就可以通过索引进行查找。

selectempno,ename,deptno from emp where hiredate<(to_date('01-MAY-81')+0.9999);

 

  1.6.4 比较不匹配的数据类型      

也是比较难于发现的性能问题之一。注意下面查询的例子,account_number是一个VARCHAR2类型,在account_number字段上有索引。

 

下面的语句将执行全表扫描:

 

 selectbank_name,address,city,state,zip frombanks where account_number = 990354;

  Oracle可以自动把where子句变成to_number(account_number)=990354,这样就限制了索引的使用,改成下面的查询就可以使用索引:

 select bank_name,address,city,state,zipfrombanks where account_number ='990354';

 

特别注意:不匹配的数据类型之间比较会让Oracle自动限制索引的使用,即便对这个查询执行ExplainPlan也不能让您明白为什么做了一次“全表扫描”。

 

 

 

 

 

1.7 查询索引

查询DBA_INDEXES视图可得到表中所有索引的列表,注意只能通过USER_INDEXES的方法来检索模式(schema)的索引。访问USER_IND_COLUMNS视图可得到一个给定表中被索引的特定列。

 

 

1.8 组合索引

当某个索引包含有多个已索引的列时,称这个索引为组合(concatented)索引。在 Oracle9i引入跳跃式扫描的索引访问方法之前,查询只能在有限条件下使用该索引。比如:表emp有一个组合索引键,该索引包含了empno、 ename和deptno。在Oracle9i之前除非在where之句中对第一列(empno)指定一个值,否则就不能使用这个索引键进行一次范围扫描。

   特别注意:在Oracle9i之前,只有在使用到索引的前导索引时才可以使用组合索引!

 

 

1.9 ORACLE ROWID

通过每个行的ROWID,索引Oracle提供了访问单行数据的能力。ROWID其实就是直接指向单独行的线路图。如果想检查重复值或是其他对ROWID本身的引用,可以在任何表中使用和指定rowid列。

 

 

 

1.10 选择性

   使用USER_INDEXES视图,该视图中显示了一个distinct_keys列。比较一下唯一键的数量和表中的行数,就可以判断索引的选择性。选择性越高,索引返回的数据就越少。

 

 

1.11 群集因子(ClusteringFactor)

  Clustering Factor位于USER_INDEXES视图中。该列反映了数据相对于已建索引的列是否显得有序。如果ClusteringFactor列的值接近于索引中的树叶块(leafblock)的数目,表中的数据就越有序。如果它的值接近于表中的行数,则表中的数据就不是很有序。

 

 

1.12 二元高度(Binaryheight)

  索引的二元高度对把ROWID返回给用户进程时所要求的I/O量起到关键作用。在对一个索引进行分析后,可以通过查询DBA_INDEXES的B- level列查看它的二元高度。二元高度主要随着表的大小以及被索引的列中值的范围的狭窄程度而变化。索引上如果有大量被删除的行,它的二元高度也会增加。更新索引列也类似于删除操作,因为它增加了已删除键的数目。重建索引可能会降低二元高度。

 

 

1.13快速全局扫描

  从Oracle7.3后就可以使用快速全局扫描(Fast FullScan)这个选项。这个选项允许Oracle执行一个全局索引扫描操作。快速全局扫描读取B-树索引上所有树叶块。初始化文件中的DB_FILE_MULTIBLOCK_READ_COUNT参数可以控制同时被读取的块的数目。

 

 

1.14跳跃式扫描

  从Oracle9i开始,索引跳跃式扫描特性可以允许优化器使用组合索引,即便索引的前导列没有出现在WHERE子句中。索引跳跃式扫描比全索引扫描要快的多。

 

 

下面的比较他们的区别:

SQL> settiming on

 

SQL> createindexTT_index on TT(teamid,areacode);

 

索引已创建。

 

已用时间: 00: 02: 03.93

 

SQL>selectcount(areacode) from tt;

 

COUNT(AREACODE)

 

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

 

 7230369

 

已用时间: 00: 00: 08.31

 

SQL> select/*+ index(tt TT_index )*/ count(areacode) from tt;

 

COUNT(AREACODE)

 

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

 

7230369

 

已用时间: 00: 00: 07.37

 

 

1.15索引的类型

B-树索引    位图索引  HASH索引     索引编排表

 

反转键索引 基于函数的索引  分区索引   本地和全局索引

 

 

 

 

 

 

 

 

 

二. 索引分类

 

Oracle提 供了大量索引选项。知道在给定条件下使用哪个选项对于一个应用程序的性能来说非常重要。一个错误的选择可能会引发死锁,并导致数据库性能急剧下降或进程终止。而如果做出正确的选择,则可以合理使用资源,使那些已经运行了几个小时甚至几天的进程在几分钟得以完成,这样会使您立刻成为一位英雄。下面就将简单的讨论每个索引选项。

 

下面讨论的索引类型:

B树索引(默认类型)

位图索引

HASH索引

索引组织表索引

反转键(reverse key)索引

基于函数的索引

分区索引(本地和全局索引)

位图连接索引

 

2.1  B树索引(默认类型)

 B树索引在Oracle中是一个通用索引。在创建索引时它就是默认的索引类型。B树索引可以是一个列的(简单)索引,也可以是组合/复合(多个列)的索引。B树索引最多可以包括32列。

在下图的例子中,B树索引位于雇员表的last_name列上。这个索引的二元高度为3;接下来,Oracle会穿过两个树枝块(branchblock),到达包含有ROWID的树叶块。在每个树枝块中,树枝行包含链中下一个块的ID号。

树叶块包含了索引值、ROWID,以及指向前一个和后一个树叶块的指针。Oracle可以从两个方向遍历这个二叉树。B树索引保存了在索引列上有值的每个数据行的ROWID值。Oracle不会对索引列上包含NULL值的行进行索引。如果索引是多个列的组合索引,而其中列上包含NULL值,这一行就会处于包含NULL值的索引列中,且将被处理为空(视为NULL)。

                       

 

技巧:索引列的值都存储在索引中。因此,可以建立一个组合(复合)索引,这些索引可以直接满足查询,而不用访问表。这就不用从表中检索数据,从而减少了I/O量。

 

 

B-tree特点:

  适合与大量的增、删、改(OLTP)

不能用包含OR操作符的查询;

适合高基数的列(唯一值多)

典型的树状结构;

每个结点都是数据块;

大多都是物理上一层、两层或三层不定,逻辑上三层;

叶子块数据是排序的,从左向右递增;

在分支块和根块中放的是索引的范围;

 

 

2.2  位图索引

位图索引非常适合于决策支持系统(DecisionSupport System,DSS)和数据仓库,它们不应该用于通过事务处理应用程序访问的表。它们可以使用较少到中等基数(不同值的数量)的列访问非常大的表。尽管位图索引最多可达30个列,但通常它们都只用于少量的列。

例如,您的表可能包含一个称为Sex的列,它有两个可能值:男和女。这个基数只为2,如果用户频繁地根据Sex列的值查询该表,这就是位图索引的基列。当一个表内包含了多个位图索引时,您可以体会到位图索引的真正威力。如果有多个可用的位图索引,Oracle就可以合并从每个位图索引得到的结果集,快速删除不必要的数据。

 

 

Bitmapt 特点:

适合与决策支持系统;

做UPDATE代价非常高;

非常适合OR操作符的查询;

基数比较少的时候才能建位图索引;

 

技巧:对于有较低基数的列需要使用位图索引。性别列就是这样一个例子,它有两个可能值:男或女(基数仅为2)。位图对于低基数(少量的不同值)列来说非常快,这是因为索引的尺寸相对于B树索引来说小了很多。因为这些索引是低基数的B树索引,所以非常小,因此您可以经常检索表中超过半数的行,并且仍使用位图索引。

当大多数条目不会向位图添加新的值时,位图索引在批处理(单用户)操作中加载表(插入操作)方面通常要比B树做得好。当多个会话同时向表中插入行时不应该使用位图索引,在大多数事务处理应用程序中都会发生这种情况。

 

示例

下面来看一个示例表PARTICIPANT,该表包含了来自个人的调查数据。列Age_Code、Income_Level、Education_Level和Marital_Status都包括了各自的位图索引。下图显示了每个直方图中的数据平衡情况,以及对访问每个位图索引的查询的执行路径。图中的执行路径显示了有多少个位图索引被合并,可以看出性能得到了显著的提高。

 

                    

 

 

如上图图所示,优化器依次使用4个单独的位图索引,这些索引的列在WHERE子句中被引用。每个位图记录指针(例如0或1),用于指示表中的哪些行包含位图中的已知值。有了这些信息后,Oracle就执行BITMAP AND操作以查找将从所有4个位图中返回哪些行。该值然后被转换为ROWID值,并且查询继续完成剩余的处理工作。注意,所有4个列都有非常低的基数,使用索引可以非常快速地返回匹配的行。

 

技巧:在一个查询中合并多个位图索引后,可以使性能显著提高。位图索引使用固定长度的数据类型要比可变长度的数据类型好。较大尺寸的块也会提高对位图索引的存储和读取性能。

 

下面的查询可显示索引类型。

SQL> selectindex_name, index_type from user_indexes;

 

INDEX_NAME         INDEX_TYPE

 

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

 

TT_INDEX            NORMAL

 

IX_CUSTADDR_TP    NORMAL

 

B树索引作为NORMAL列出;而位图索引的类型值为BITMAP。

 

技巧:如果要查询位图索引列表,可以在USER _INDEXES视图中查询index_type列。

建议不要在一些联机事务处理(OLTP)应用程序中使用位图索引。B树索引的索引值中包含ROWID,这样Oracle就可以在行级别上锁定索引。位图索引存储为压缩的索引值,其中包含了一定范围的ROWID,因此Oracle必须针对一个给定值锁定所有范围内的ROWID。这种锁定类型可能在某些DML语句中造成死锁。SELECT语句不会受到这种锁定问题的影响。

位图索引的使用限制:

 

基于规则的优化器不会考虑位图索引。

当执行ALTER TABLE语句并修改包含有位图索引的列时,会使位图索引失效。

位图索引不包含任何列数据,并且不能用于任何类型的完整性检查。

位图索引不能被声明为唯一索引。

位图索引的最大长度为30。

 

技巧:不要在繁重的OLTP环境中使用位图索引

 

2.3  HASH索引

使用HASH索引必须要使用HASH集群。建立一个集群或HASH集群的同时,也就定义了一个集群键。这个键告诉Oracle如何在集群上存储表。在存储数据时,所有与这个集群键相关的行都被存储在一个数据库块上。如果数据都存储在同一个数据库块上,并且将HASH索引作为WHERE子句中的确切匹配,Oracle就可以通过执行一个HASH函数和I/O来访问数据——而通过使用一个二元高度为4的B树索引来访问数据,则需要在检索数据时使用4个I/O。如下图所示,其中的查询是一个等价查询,用于匹配HASH列和确切的值。Oracle可以快速使用该值,基于HASH函数确定行的物理存储位置。

HASH索引可能是访问数据库中数据的最快方法,但它也有自身的缺点。集群键上不同值的数目必须在创建HASH集群之前就要知道。需要在创建HASH集群的时候指定这个值。低估了集群键的不同值的数字可能会造成集群的冲突(两个集群的键值拥有相同的HASH值)。这种冲突是非常消耗资源的。冲突会造成用来存储额外行的缓冲溢出,然后造成额外的I/O。如果不同HASH值的数目已经被低估,您就必须在重建这个集群之后改变这个值。

 

ALTERCLUSTER命令不能改变HASH键的数目。HASH集群还可能浪费空间。如果无法确定需要多少空间来维护某个集群键上的所有行,就可能造成空间的浪费。如果不能为集群的未来增长分配好附加的空间,HASH集群可能就不是最好的选择。如果应用程序经常在集群表上进行全表扫描,HASH集群可能也不是最好的选择。由于需要为未来的增长分配好集群的剩余空间量,全表扫描可能非常消耗资源。

在实现HASH集群之前一定要小心。您需要全面地观察应用程序,保证在实现这个选项之前已经了解关于表和数据的大量信息。通常,HASH对于一些包含有序值的静态数据非常有效。

 

技巧:HASH索引在有限制条件(需要指定一个确定的值而不是一个值范围)的情况下非常有用。

                       

 

2.4  索引组织表

索引组织表会把表的存储结构改成B树结构,以表的主键进行排序。这种特殊的表和其他类型的表一样,可以在表上执行所有的DML和DDL语句。由于表的特殊结构,ROWID并没有被关联到表的行上。

对于一些涉及精确匹配和范围搜索的语句,索引组织表提供了一种基于键的快速数据访问机制。基于主键值的UPDATE和DELETE语句的性能也同样得以提高,这是因为行在物理上有序。由于键列的值在表和索引中都没有重复,存储所需要的空间也随之减少。

如果不会频繁地根据主键列查询数据,则需要在索引组织表中的其他列上创建二级索引。不会频繁根据主键查询表的应用程序不会了解到使用索引组织表的全部优点。对于总是通过对主键的精确匹配或范围扫描进行访问的表,就需要考虑使用索引组织表。

 

技巧:可以在索引组织表上建立二级索引。

 

2.5  反转键索引

当载入一些有序数据时,索引肯定会碰到与I/O相关的一些瓶颈。在数据载入期间,某部分索引和磁盘肯定会比其他部分使用频繁得多。为了解决这个问题,可以把索引表空间存放在能够把文件物理分割在多个磁盘上的磁盘体系结构上。

为了解决这个问题,Oracle还提供了一种反转键索引的方法。如果数据以反转键索引存储,这些数据的值就会与原先存储的数值相反。这样,数据1234、1235和1236就被存储成4321、5321和6321。结果就是索引会为每次新插入的行更新不同的索引块。

 

技巧:如果您的磁盘容量有限,同时还要执行大量的有序载入,就可以使用反转键索引。

不可以将反转键索引与位图索引或索引组织表结合使用。因为不能对位图索引和索引组织表进行反转键处理。

 

 

2.6  基于函数的索引

可以在表中创建基于函数的索引。如果没有基于函数的索引,任何在列上执行了函数的查询都不能使用这个列的索引。例如,下面的查询就不能使用JOB列上的索引,除非它是基于函数的索引:

select * fromemp where UPPER(job) = 'MGR';

下面的查询使用JOB列上的索引,但是它将不会返回JOB列具有Mgr或mgr值的行:

select * fromemp where job = 'MGR';

 

 

可以创建这样的索引,允许索引访问支持基于函数的列或数据。可以对列表达式UPPER(job)创建索引,而不是直接在JOB列上建立索引,如:

create indexEMP$UPPER_JOB on emp(UPPER(job));

 

 

尽管基于函数的索引非常有用,但在建立它们之前必须先考虑下面一些问题:

能限制在这个列上使用的函数吗?如果能,能限制所有在这个列上执行的所有函数吗

是否有足够应付额外索引的存储空间?

在每列上增加的索引数量会对针对该表执行的DML语句的性能带来何种影响?

 

基于函数的索引非常有用,但在实现时必须小心。在表上创建的索引越多,INSERT、UPDATE和DELETE语句的执行就会花费越多的时间。

 

注意:对于优化器所使用的基于函数的索引来说,必须把初始参数QUERY_REWRITE _ ENABLED设定为TRUE。

 

示例:

select  count(*) from sample where ratio(balance,limit) >.5;

Elapsed time:20.1 minutes

 

 

create indexratio_idx1 on sample(ratio(balance, limit));

 

 

select  count(*) from samplewhereratio(balance,limit) >.5;

Elapsed time: 7seconds!!!

 

2.7  分区索引

分区索引就是简单地把一个索引分成多个片断。通过把一个索引分成多个片断,可以访问更小的片断(也更快),并且可以把这些片断分别存放在不同的磁盘驱动器上(避免I/O问题)。B树和位图索引都可以被分区,而HASH索引不可以被分区。可以有好几种分区方法:表被分区而索引未被分区;表未被分区而索引被分区;表和索引都被分区。不管采用哪种方法,都必须使用基于成本的优化器。分区能够提供更多可以提高性能和可维护性的可能性

有两种类型的分区索引:本地分区索引和全局分区索引。每个类型都有两个子类型,有前缀索引和无前缀索引。表各列上的索引可以有各种类型索引的组合。如果使用了位图索引,就必须是本地索引。把索引分区最主要的原因是可以减少所需读取的索引的大小,另外把分区放在不同的表空间中可以提高分区的可用性和可靠性。

在使用分区后的表和索引时,Oracle还支持并行查询和并行DML。这样就可以同时执行多个进程,从而加快处理这条语句。

2.7.1.本地分区索引(通常使用的索引)

可以使用与表相同的分区键和范围界限来对本地索引分区。每个本地索引的分区只包含了它所关联的表分区的键和ROWID。本地索引可以是B树或位图索引。如果是B树索引,它可以是唯一或不唯一的索引。

这种类型的索引支持分区独立性,这就意味着对于单独的分区,可以进行增加、截取、删除、分割、脱机等处理,而不用同时删除或重建索引。Oracle自动维护这些本地索引。本地索引分区还可以被单独重建,而其他分区不会受到影响。

 

 

2.7.1.1 有前缀的索引

有前缀的索引包含了来自分区键的键,并把它们作为索引的前导。例如,让我们再次回顾participant表。在创建该表后,使用survey_id和survey_date这两个列进行范围分区,然后在survey_id列上建立一个有前缀的本地索引,如下图所示。这个索引的所有分区都被等价划分,就是说索引的分区都使用表的相同范围界限来创建。

               

 

 

技巧:本地的有前缀索引可以让Oracle快速剔除一些不必要的分区。也就是说没有包含WHERE条件子句中任何值的分区将不会被访问,这样也提高了语句的性能。

 

2.7.1.2 无前缀的索引

无前缀的索引并没有把分区键的前导列作为索引的前导列。若使用有同样分区键(survey_id和survey_date)的相同分区表,建立在survey_date列上的索引就是一个本地的无前缀索引,如下图所示。可以在表的任一列上创建本地无前缀索引,但索引的每个分区只包含表的相应分区的键值。

                         

 

 

 

 

如果要把无前缀的索引设为唯一索引,这个索引就必须包含分区键的子集。在这个例子中,我们必须把包含survey和(或)survey_id的列进行组合(只要survey_id不是索引的第一列,它就是一个有前缀的索引)。

 

技巧:对于一个唯一的无前缀索引,它必须包含分区键的子集。

 

2.7.2.全局分区索引

全局分区索引在一个索引分区中包含来自多个表分区的键。一个全局分区索引的分区键是分区表中不同的或指定一个范围的值。在创建全局分区索引时,必须定义分区键的范围和值。全局索引只能是B树索引。Oracle在默认情况下不会维护全局分区索引。如果一个分区被截取、增加、分割、删除等,就必须重建全局分区索引,除非在修改表时指定ALTER TABLE命令的UPDATE GLOBAL INDEXES子句。

 

 

2.7.2.1 有前缀的索引

通常,全局有前缀索引在底层表中没有经过对等分区。没有什么因素能限制索引的对等分区,但Oracle在生成查询计划或执行分区维护操作时,并不会充分利用对等分区。如果索引被对等分区,就必须把它创建为一个本地索引,这样Oracle可以维护这个索引,并使用它来删除不必要的分区,如下图所示。在该图的3个索引分区中,每个分区都包含指向多个表分区中行的索引条目。

        

                      

 

 

         分区的、全局有前缀索引

 

技巧:如果一个全局索引将被对等分区,就必须把它创建为一个本地索引,这样Oracle可以维护这个索引,并使用它来删除不必要的分区。

 

 

2.7.2.2 无前缀的索引

Oracle不支持无前缀的全局索引。

 

2.8  位图连接索引

位 图连接索引是基于两个表的连接的位图索引,在数据仓库环境中使用这种索引改进连接维度表和事实表的查询的性能。创建位图连接索引时,标准方法是连接索引中常用的维度表和事实表。当用户在一次查询中结合查询事实表和维度表时,就不需要执行连接,因为在位图连接索引中已经有可用的连接结果。通过压缩位图连接索引中的ROWID进一步改进性能,并且减少访问数据所需的I/O数量。

 

 

创建位图连接索引时,指定涉及的两个表。相应的语法应该遵循如下模式:

create bitmapindex FACT_DIM_COL_IDX onFACT(DIM.Descr_Col) from FACT,DIM

whereFACT.JoinCol = DIM.JoinCol;

 

 

位图连接的语法比较特别,其中包含FROM子句和WHERE子句,并且引用两个单独的表。索引列通常是维度表中的描述列——就是说,如果维度是CUSTOMER,并且它的主键是CUSTOMER_ID,则通常索引Customer_Name这样的列。如果事实表名为SALES,可以使用如下的命令创建索引:

create bitmapindex SALES_CUST_NAME_IDX

 

on  SALES(CUSTOMER.Customer_Name)  fromSALES, CUSTOMER

whereSALES.Customer_ID=CUSTOMER.Customer_ID;

 

 

如果用户接下来使用指定Customer_Name列值的WHERE子句查询SALES和CUSTOMER表,优化器就可以使用位图连接索引快速返回匹配连接条件和Customer_Name条件的行。

 

 

位图连接索引的使用一般会受到限制:

 

1)只可以索引维度表中的列。

 

2)用于连接的列必须是维度表中的主键或唯一约束;如果是复合主键,则必须使用连接中的每一列。

 

3)不可以对索引组织表创建位图连接索引,并且适用于常规位图索引的限制也适用于位图连接索引。

 

 

 

常见执行计划

 

1,什么是执行计划

 

所谓执行计划,顾名思义,就是对一个查询任务,做出一份怎样去完成任务的详细方案。举个生活中的例子,我从珠海要去英国,我可以

 

选择先去香港然后转机,也可以先去北京转机,或者去广州也可以。但是到底怎样去英国划算,也就是我的费用最少,这是一件值得考究

 

的事情。同样对于查询而言,我们提交的SQL仅仅是描述出了我们的目的地是英国,但至于怎么去,通常我们的SQL中是没有给出提示信息

 

的,是由数据库来决定的。

 

  我们先简单的看一个执行计划的对比:

 

  SQL> set autotrace traceonly

 

  执行计划一:

 

  SQL> select count(*) from t;

  COUNT(*)

  ----------

  24815

  Execution Plan

  0   SELECTSTATEMENTOptimizer=CHOOSE

  1  0 SORT (AGGREGATE)

  2  1   TABLE Access (FULL) OF 'T'

 

  执行计划二:

 

  SQL> select count(*) from t;

  COUNT(*)

  24815

  Execution Plan

  0   SELECTSTATEMENTOptimizer=CHOOSE (Cost=26 Card=1)

  1  0 SORT (AGGREGATE)

  2  1   INDEX (FULL SCAN) OF 'T_INDEX' (NON-UNIQUE)(Cost=26 Card=28180)

 

  这两个执行计划中,第一个表示求和是通过进行全表扫描来做的,把整个表中数据读入内存来逐条累加;第二个表示根据表中索引,把

 

整个索引读进内存来逐条累加,而不用去读表中的数据。但是这两种方式到底哪种快呢?通常来说可能二比一快,但也不是绝对的。这是一

 

个很简单的例子演示执行计划的差异。对于复杂的SQL(表连接、嵌套子查询等),执行计划可能几十种甚至上百种,但是到底那种最好呢?

 

我们事前并不知道,数据库本身也不知道,但是数据库会根据一定的规则或者统计信息(statistics)去选择一个执行计划,通常来说选择的是

 

比较优的,但也有选择失误的时候,这就是这次讨论的价值所在。

 

Oracle优化器模式

 

  Oracle优化器有两大类,基于规则的和基于代价的,在SQLPLUS中我们可以查看init文件中定义的缺省的优化器模式。

 

  SQL> show parameters optimizer_mode

  NAME                TYPE  VALUE

  optimizer_mode          string  CHOOSE

  SQL>

 

  这是Oracle8.1.7 企业版,我们可以看出,默认安装后数据库优化器模式为CHOOSE,我们还可以设置为 RULE、

 

FIRST_ROWS,ALL_ROWS。可以在init文件中对整个instance的所有会话设置,也可以单独对某个会话设置:

 

  SQL> ALTER SESSION SET optimizer_mode =RULE;

  会话已更改。

  SQL> ALTER SESSION SEToptimizer_mode = FIRST_ROWS;

  会话已更改。

  SQL> ALTER SESSION SEToptimizer_mode = ALL_ROWS;

  会话已更改。

 

  基于规则的查询,数据库根据表和索引等定义信息,按照一定的规则来产生执行计划;基于代价的查询,数据库根据搜集的表和索引的

 

数据的统计信息(通过analyze 命令或者使用dbms_stats包来搜集)综合来决定选取一个数据库认为最优的执行计划(实际上不一定最优)。

 

RULE是基于规则的,CHOOSE表示如果查询的表存在搜集的统计信息则基于代价来执行(在CHOOSE模式下Oracle采用的是 FIRST_ROWS)

 

,否则基于规则来执行。在基于代价的两种方式中,FIRST_ROWS指执行计划采用最少资源尽快的返回部分结果给客户端,对于排序分页

 

页显示这种查询尤其适用,ALL_ROWS指以总体消耗资源最少的方式返回结果给客户端。

 

  基于规则的模式下,数据库的执行计划通常比较稳定。但在基于代价的模式下,我们才有更大的机会选择最优的执行计划。也由于

 

Oracle的很多查询方面的特性必须在基于代价的模式下才能体现出来,所以我们通常不选择RULE(并且Oracle宣称从 Oracle 10i版本数据库

 

开始将不再支持 RULE)。既然是基于代价的模式,也就是说执行计划的选择是根据表、索引等定义和数据的统计信息来决定的,这个统计

 

信息是根据 analyze 命令或者dbms_stats包来定期搜集的。首先存在着一种可能,就是由于搜集信息是一个很消耗资源和时间的动作,尤

 

其当表数据量很大的时候,因为搜集信息是对整个表数据进行重新的完全统计,所以这是我们必须慎重考虑的问题。我们只能在服务器空

 

闲的时候定期的进行信息搜集。这说明我们在一段时期内,统计信息可能和数据库本身的数据并不吻合;另外就是Oracle的统计数据本身也

 

存在着不精确部分(详细参考OracleDOCUMENT),更重要的一个问题就是及时统计数据相对已经比较准确,但是Oracle的优化器的选择也

 

并不是始终是最优的方案。这也倚赖于Oracle对不同执行计划的代价的计算规则(我们通常是无法知道具体的计算规则的)。这好比我们决定

 

从香港还是从北京去英国,车票、机票等实际价格到底是怎么核算出来的我们并不知道,或者说我们现在了解的价格信息,在我们乘车前

 

往的时候,真实价格跟我们的预算已经发生了变化。所有的因素,都将影响我们的整个开销。

 

  执行计划稳定性能带给我们什么

 

  Oracle存在着执行计划选择失误的可能。这也是我们经常遇见的一些现象,比如总有人说我的程序在测试数据库中跑的很好,但在产

 

品数据库上就是跑的很差,甚至后者硬件条件比前者还好,这到底是为什么?硬件资源、统计信息、参数设置都可能对执行计划产生影响。

 

由于因素太多,我们总是对未来怀着一种莫名的恐惧,我的产品数据库上线后到底跑的好不好?于是Oracle提供了一种稳定执行计划的能力

 

,也就是把在测试环境中的运行良好的执行计划所产生的OUTLINES移植到产品数据库,使得执行计划不会随着其他因素的变化而变化。

 

  那么OUTLINES是什么呢?先要介绍一个内容,Oracle提供了在SQL中使用HINTS来引导优化器产生我们想要的执行计划的能力。这在

 

多表连接、复杂查询中特别有效。HINTS的类型很多,可以设置优化器目标(RULE、CHOOSE、FIRST_ROWS、ALL_ROWS),可以指定表

 

连接的顺序,可以指定使用哪个表的哪个索引等等,可以对SQL进行很多精细的控制。通过这种方式产生我们想要的执行计划的这些

 

HINTS,Oracle可以存储这些HINTS,我们称之为OUTLINES。通过STORE OUTLINES可以使得我们拥有以后产生相同执行计划的能力,也

 

就是使我们拥有了稳定执行计划的能力。

 

  这里想给出一个附加的说明就是,实际上,我们通过工具改写SQL,比如使用SQL EXPERT改写后的SQL,这些不仅仅是加了HINTS

 

而且文本都已经发生了变化的SQL,也可以存储OUTLINES,并可被应用到应用中。但这不是一定生效,我们必须测试检查是否生效。但由

 

于就算给了错误的OUTLINES,数据库在执行的时候,也只是忽略过去重新生成执行计划而不会返回错误,所以我们才敢放心的这么使用。

 

当然在Oracle文档中并没有指明可以这样做,文档中只是说明,如果存在OUTLINES的同时又在SQL中加了HINTS,则会使用OUTLINES而

 

忽略HINTS。这个功能在LECCO将发布的产品中会使用这一功能,这样可以将SQL EXPERT的改写SQL的能力和稳定执行计划的能力结合起

 

来,那么我们就对不能更改源代码的应用具有了相当强大的SQL优化能力。

 

  也许我们会有疑问,假如稳定了执行计划,那还搜集统计信息干吗?这是因为几个原因造成的,首先,现在的执行计划对于未来发生了

 

变化的数据未必就是合适的,存在着当前的执行计划不满足未来数据的变化后的效率,而新的统计信息的情况下所产生的执行计划也并不

 

是全部都合理的。那这个时候,我们可以采用新搜集的统计信息,但是却对新统计信息下不良的执行计划采用Oracle提供的执行计划稳定

 

性这个能力固定执行计划,这样结合起来我们可以建立满意的高效的数据库运行环境。

 

  我们还需要关注的一个东西,Oracle提供的dbms_stats包除了具有搜集统计信息的能力,还具有把数据库中统计信息(statistics)

 

export/import的能力,还具有只搜集统计信息而使得统计信息不应用于数据库的能力(把统计信息搜集到一个特定的表中而不是立即生效)

 

,在这个基础上我们就可以把统计信息export出来再import到一个测试环境中,再运行我们的应用,在测试环境中我们观察最新的统计信

 

息会导致哪些执行计划发生变化(DB EXPERT的Plan Version Tracer是模拟不同环境并自动检查不同环境中执行计划变化的工具),是变好了

 

还是变差了。我们可以把变差的这一部分在测试环境中使用hints或者利用工具(SQL EXPERT是在重写SQL这一领域目前最强有力的工具)产

 

生良好的执行计划的SQL,利用这些SQL可以产生OUTLINES,然后在产品数据库应用最新的统计信息的同时移植进这些OUTLINES。

 

  最后说一下我们不得不使用执行计划稳定性能力的场合。我们假定Oracle的优化器的选择都是准确的,但是优化器选择的基础就是我

 

们的SQL,这些SQL才从根本上决定了运行效率,这是更重要的一个优化的环节。SQL是基础(当然数据库的设计是基础的基础),一个SQL写

 

的好不好,就相当于我们同样是要想去英国,但是我的起点在珠海,你的起点却在西藏的最边缘偏僻的一个地方,那不管你做怎样的最优

 

路线选择,你都不如我在珠海去英国所花费的代价小。

 

2,怎么生成的

 

1.Explain plan

explain plan for

select * fromaa;

查看结果:

select * fromtable(dbms_xplan.display());

2.Autotrace Settiming on --记录所用时间

Set autot trace--自动记录执行计划

3.SQL_TRACE

ORACLE SQL_TRACE

 

“SQL TRACE”是Oracle提供的用于进行SQL跟踪的手段,是强有力的辅助诊断工具。在日常的数据库问题诊断和解决中,“SQLTRACE”是

 

非常常用的方法。

 

一般,一次跟踪可以分为以下几步:

 

1、界定需要跟踪的目标范围,并使用适当的命令启用所需跟踪。

 

 

2、经过一段时间后,停止跟踪。此时应该产生了一个跟踪结果文件。

 

 

3、找到跟踪文件,并对其进行格式化,然后阅读或分析。

 

 

本文就“SQL TRACE”的这些使用作简单探讨,并通过具体案例对SQL_TRACE的使用进行说明。

 

3,怎么查看执行计划

 

从Oracle10g开始,可以通过EXPLAINPLAN FOR查看DDL语句的执行计划了。

 

 

 

 

 

在9i及以前版本,Oracle只能看到DML的执行计划,不过从10g开始,通过EXPLAIN PLANFOR的方式,已经可以看到DDL语句的执行计划

 

了。

 

这对于研究CREATE TABLE AS SELECT、CREATE MATERIALIZEDVIEW AS SELECT以及CREATE INDEX,ALTERINDEX REBUILD等语

 

句有很大的帮助。

 

举个简单的例子,Oracle的文档上对于索引的建立有如下描述:

 

The optimizercan use an existing index to build another index. Thisresults in a much fasterindex build.

 

如果看不到DDL的执行计划,只能根据执行时间的长短去猜测Oracle的具体执行计划,但是这种方法没有足够的说服力。但是通过DDL的执

 

行计划,就使得结果一目了然了。

 

SQL> CREATETABLE T AS SELECT * FROM DBA_OBJECTS;

 

表已创建。

 

SQL> EXPLAINPLAN FOR

2 CREATE INDEXIND_T_NAME ON T(OBJECT_NAME);

 

已解释。

 

SQL> SELECT *FROM TABLE(DBMS_XPLAN.DISPLAY);

 

PLAN_TABLE_OUTPUT

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

Plan hash value:3035241083

 

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

| Id | Operation| Name | Rows | Bytes | Cost (%CPU)| Time |

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

| 0 | CREATEINDEX STATEMENT | | 57915 | 3732K| 75 (2)| 00:00:01 |

| 1 | INDEXBUILD NON UNIQUE| IND_T_NAME | | | | |

| 2 | SORTCREATE INDEX | | 57915 | 3732K| | |

| 3 | TABLEACCESS FULL | T | 57915 | 3732K| 41 (3)| 00:00:01 |

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

 

Note

-----

- estimatedindex size: 5242K bytes

 

已选择14行。

 

SQL> CREATEINDEX IND_T_OWNER_NAME ON T(OWNER, OBJECT_NAME);

 

索引已创建。

 

SQL> EXPLAINPLAN FOR

2 CREATE INDEXIND_T_NAME ON T(OBJECT_NAME);

 

已解释。

 

SQL> SELECT *FROM TABLE(DBMS_XPLAN.DISPLAY);

 

PLAN_TABLE_OUTPUT

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

Plan hash value:517242163

 

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

| Id | Operation| Name | Rows | Bytes | Cost (%CPU)| Time |

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

| 0 | CREATEINDEX STATEMENT | | 57915 | 3732K| 75 (2)| 00:00:01 |

| 1 | INDEXBUILD NON UNIQUE| IND_T_NAME | | | | |

| 2 | SORTCREATE INDEX | | 57915 | 3732K| | |

| 3 | INDEX FASTFULL SCAN| IND_T_OWNER_NAME | | | | |

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

 

Note

-----

- estimatedindex size: 5242K bytes

 

已选择14行。

 

SQL> SETAUTOT ON

SQL> CREATEINDEX IND_T_NAME ON T(OBJECT_NAME);

 

索引已创建。

 

注意,查看DDL的执行计划需要使用EXPLAINPLAN FOR,AUTOTRACE对于DDL是无效的。

 

 

4,如何读懂执行计划:

Execution Plan

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

0 SELECTSTATEMENT ptimizer=CHOOSE

1 0 SORT(AGGREGATE)

2 1 TABLE ACCESS(BY INDEX ROWID) OF 'USER_INFO'

3 2 NESTED LOOPS

4 3 TABLE ACCESS(FULL) OF 'USER_NUM_TABLE'

5 3 INDEX (RANGESCAN) OF 'PK_USER_INFO' (UNIQUE)

请问以上执行计划语句是如何看的?语句的执行顺序是什么?

让我们来解释一下怎么看吧,左边的两列数字,第一列表示这条计划的编号,第二列是这条计划的父计划的编号;如果一条计划有子计划,

 

那么先要执行其子计划;在这个例子中:从第一条编号为0的(SELECTSTATEMENT ptimizer=CHOOSE)开始,他有个子计划1(SORT

 

(AGGREGATE)),然后1有个子计划2,2有子计划3, 3 有子计划4和5,4是3的第一个子计划,所以先执行4(TABLEACCESS (FULL)

 

OF'USER_NUM_TABLE'),再执行5(INDEX(RANGESCAN) OF 'PK_USER_INFO' (UNIQUE)),4和5执行完返回到其父计划3(NESTED

 

LOOPS),3把4和5取到的rows进行nestedloops,结果再返回到2,再到1排序,再到0select.

 

 

 

CBO,RBO

 

Oracle的优化器有两种优化方式,即基于规则的优化方式(Rule-Based Optimization,简称为RBO)和基于代价的优化方式(Cost-BasedOptimization,简称为CBO),在Oracle8及以后的版本,Oracle强列推荐用CBO的方式

    RBO方式:优化器在分析SQL语句时,所遵循的是Oracle内部预定的一些规则。比如我们常见的,当一个where子句中的一列有索引时去走索引。

 

    CBO方式:它是看语句的代价(Cost),这里的代价主要指Cpu和内存。优化器在判断是否用这种方式时,主要参照的是表及索引的统计信息。统计信息给出表的大小、有少行、每行的长度等信息。这些统计信息起初在库内是没有的,是做analyze后才出现的,很多的时侯过期统计信息会令优化器做出一个错误的执行计划,因些应及时更新这些信息。

 

    注意:走索引不一定就是优的,比如一个表只有两行数据,一次IO就可以完成全表的检索,而此时走索引时则需要两次IO,这时全表扫描(full table scan)是最好

 

 

 

    show parameter optimizer_mode --看ORACLE处于何种模式,Oracle 7以来缺省的设置应是"choose",即如果对已分析的表查询的话选择CBO,是否选择RBO.如果该参数设置为"rule",则不论表是否分析过,一概选用RBO,除非在语句中用hint强制.

 

    优化模式包括Rule、Choose、First rows、Allrows四种方式:

 

    Rule:基于规则的方式。

 

    Choose:默认的情况下Oracle用的便是这种方式。指的是当一个表或索引有统计信息,则走CBO的方式,如果表或索引没统计信息,表又不是特别的小,而且相应的列有索引时,那么就走索引,走RBO的方式。

 

    First Rows:它与Choose方式是类似的,所不同的是当一个表有统计信息时,它将是以最快的方式返回查询的最先的几行,从总体上减少了响应时间。

 

    All Rows:也就是我们所说的Cost的方式,当一个表有统计信息时,它将以最快的方式返回表的所有的行,从总体上提高查询的吞吐量。没有统计信息则走RBO的方式。

 

    设定选用哪种优化模式:

 

    A、Instance级别我们可以通过在initSID.ora文件中设定OPTIMIZER_MODE=RULE/CHOOSE/FIRST_ROWS/ALL_ROWS如果没设定OPTIMIZER_MODE参数则默认用的是Choose方式。

    B、Sessions级别通过ALTER SESSION SET OPTIMIZER_MODE=RULE/CHOOSE/FIRST_ROWS/ALL_ROWS来设定。

    C、语句级别用Hint()来设定

 

    为什么表的某个字段明明有索引,但执行计划却不走索引?

 

    1、优化模式是all_rows的方式

    2、表作过analyze,有统计信息(最可能的就是统计信息有误)

    3、表很小,上文提到过的,Oracle的优化器认为不值得走索引。

 

我们可以查看一下一个表或索引是否是统计信息

     SELECT * FROM user_tables

     WHERE table_name=<table_name>

     AND num_rows is not null;

     SELECT * FROM user_indexes

     WHERE table_name=<table_name>

      AND num_rows is not null;

 

     当我们使用CBO的方式,就应当及时去更新表和索引的统计信息,以免生形不切合实的执行计划。

     ANALYZE table table_name COMPUTESTATISTICS;

     ANALYZE INDEX index_name ESTIMATE STATISTICS;

 

 

 

数据表系统分析

 

数据字典dict总是属于Oracle用户sys的。

  1、用户:

   selectusername from dba_users;

  改口令

   alter userspgroup identified by spgtest;

  2、表空间:

   select *from dba_data_files;

   select *from dba_tablespaces;//表空间

 

   selecttablespace_name,sum(bytes), sum(blocks)

    fromdba_free_space group by tablespace_name;//空闲表空间

 

   select *from dba_data_files

    wheretablespace_name=''''RBS'''';//表空间对应的数据文件

 

   select *from dba_segments

    wheretablespace_name=''''INDEXS'''';

  3、数据库对象:

   select *from dba_objects;

   CLUSTER、DATABASE LINK、FUNCTION、INDEX、LIBRARY、PACKAGE、PACKAGE BODY、

   PROCEDURE、SEQUENCE、SYNONYM、TABLE、TRIGGER、TYPE、UNDEFINED、VIEW。

  4、表:

   select *from dba_tables;

   analyzemy_table compute statistics;->dba_tables后6列

   selectextent_id,bytes from dba_extents

   where segment_name=''''CUSTOMERS''''and segment_type=''''TABLE''''

   order byextent_id;//表使用的extent的信息。segment_type=''''ROLLBACK''''查看回滚段的空间分配信息

   列信息:

    selectdistinct table_name

    fromuser_tab_columns

    wherecolumn_name=''''SO_TYPE_ID'''';

  5、索引: 

   select *from dba_indexes;//索引,包括主键索引

   select *from dba_ind_columns;//索引列

   selecti.index_name,i.uniqueness,c.column_name

    fromuser_indexes i,user_ind_columns c

     wherei.index_name=c.index_name

     andi.table_name =''''ACC_NBR'''';//联接使用

  6、序列:

   select *from dba_sequences;

  7、视图:

   select *from dba_views;

   select *from all_views;

  text 可用于查询视图生成的脚本

  8、聚簇:

   select *from dba_clusters;

  9、快照:

   select *from dba_snapshots;

  快照、分区应存在相应的表空间。

  10、同义词:

   select *from dba_synonyms

    wheretable_owner=''''SPGROUP'''';

    //if owneris PUBLIC,then the synonyms is a public synonym.

     if owneris one of users,then the synonyms is a private synonym.

  11、数据库链:

   select *from dba_db_links;

  在spbase下建数据库链

   createdatabase link dbl_spnew

   connect tospnew identified by spnew using ''''jhhx'''';

   insert intoacc_nbr@dbl_spnew

   select *from acc_nbr where nxx_nbr=''''237'''' andline_nbr=''''8888'''';

  12、触发器:

   select *from dba_trigers;

  存储过程,函数从dba_objects查找。

  其文本:selecttext from user_source where name=''''BOOK_SP_EXAMPLE'''';

  建立出错:select* from user_errors;

  oracle总是将存储过程,函数等软件放在SYSTEM表空间。

  13、约束:

  (1)约束是和表关联的,可在createtable或alter tabletable_nameadd/drop/modify来建立、修改、删除约束。

  可以临时禁止约束,如:

   alter tablebook_example

   disableconstraint book_example_1;

   alter tablebook_example

   enableconstraint book_example_1;

  (2)主键和外键被称为表约束,而notnull和unique之类的约束被称为列约束。通常将主键和外键作为单独的命名约束放在字段列表下面,而列约束可放在列定义的同一行,这样更具有可读性。

  (3)列约束可从表定义看出,即describe;表约束即主键和外键,可从dba_constraints和dba_cons_columns 查。

   select *from user_constraints

   wheretable_name=''''BOOK_EXAMPLE'''';

   selectowner,CONSTRAINT_NAME,TABLE_NAME

    fromuser_constraints

    whereconstraint_type=''''R''''

    order bytable_name;

  (4)定义约束可以无名(系统自动生成约束名)和自己定义约束名(特别是主键、外键)

  如:createtable book_example

    (identifiernumber not null);

    createtable book_example

    (identifiernumber constranit book_example_1 not null);

  14、回滚段:

  在所有的修改结果存入磁盘前,回滚段中保持恢复该事务所需的全部信息,必须以数据库发生的事务来相应确定其大小(DML语句才可回滚,create,drop,truncate等DDL不能回滚)。

  回滚段数量=并发事务/4,但不能超过50;使每个回滚段大小足够处理一个完整的事务;

   createrollback segment r05

   tablespacerbs;

   createrollback segment rbs_cvt

   tablespacerbs

   storage(initial1M next 500k);

  使回滚段在线

   alterrollback segment r04 online;

  用dba_extents,v$rollback_segs监测回滚段的大小和动态增长。

  回滚段的区间信息

   select *from dba_extents

   wheresegment_type=''''ROLLBACK'''' and segment_name=''''RB1'''';

  回滚段的段信息,其中bytes显示目前回滚段的字节数

   select *from dba_segments

    wheresegment_type=''''ROLLBACK'''' and segment_name=''''RB1'''';

  为事物指定回归段

   settransaction use rollback segment rbs_cvt

  针对bytes可以使用回滚段回缩。

   alterrollback segment rbs_cvt shrink;

   selectbytes,extents,max_extents from dba_segments

    wheresegment_type=''''ROLLBACK'''' and segment_name=''''RBS_CVT'''';

  回滚段的当前状态信息:

   select *from dba_rollback_segs

    wheresegment_name=''''RB1'''';

  比多回滚段状态status,回滚段所属实例instance_num

  查优化值optimal

   selectn.name,s.optsize

    fromv$rollname n,v$rollstat s

     wheren.usn=s.usn;

  回滚段中的数据

   settransaction use rollback segment rb1;/*回滚段名*/

   selectn.name,s.writes

    fromv$rollname n,v$rollstat s

     wheren.usn=s.usn;

  当事务处理完毕,再次查询$rollstat,比较writes(回滚段条目字节数)差值,可确定事务的大小。

  查询回滚段中的事务

   column rrheading ''''RB Segment'''' format a18

   column usheading ''''Username'''' format a15

   column osheading ''''Os User'''' format a10

   column teheading ''''Terminal'''' format a10

   selectr.name rr,nvl(s.username,''''no transaction'''') us,s.osuseros,s.terminal te

    fromv$lock l,v$session s,v$rollname r

     wherel.sid=s.sid(+)

     andtrunc(l.id1/65536)=R.USN

     andl.type=''''TX''''

     andl.lmode=6

   order byr.name;

  15、作业

  查询作业信息

   selectjob,broken,next_date,interval,what from user_jobs;

   selectjob,broken,next_date,interval,what from dba_jobs;

  查询正在运行的作业

   select *from dba_jobs_running;

  使用包execdbms_job.submit(:v_num,''''a;'''',sysdate,''''sysdate +(10/(24*60*60))'''')加入作业。间隔10秒钟

execdbms_job.submit(:v_num,''''a;'''',sysdate,''''sysdate + (11/(24*60))'''')加入作业。间隔11分钟使用包exec dbms_job.remove(21)删除21号作业。

 

表连接

 

1. 内连接(自然连接)

 

2. 外连接

 

(1)左外连接 (左边的表不加限制)

 

(2)右外连接(右边的表不加限制)

 

(3)全外连接(左右两表都不加限制)

 

3. 自连接(同一张表内的连接)

 

inner join 表示内连接;

left join表示左外连接;

right join表示右外连接;

full join表示完全外连接;

on子句 用于指定连接条件。

 

注意:

 

如果使用from子句指定内、外连接,则必须要使用on子句指定连接条件;

 

如果使用(+)操作符指定外连接,则必须使用where子句指定连接条件。

 

一. 内连接(Inner Join/Join)

 

1.1  Inner Join

 

Inner join逻辑运算符返回满足第一个(顶端)输入与第二个(底端)输入联接的每一行。这个和用select查询多表是一样的效果,所以内连接用的很少。

还有一点要说明的就是Join 默认就是inner join。所以我们在写内连接的时候可以省略inner 这个关键字。

 

1.3 自然连接(Natural join)

 

自然连接是在两张表中寻找那些数据类型和列名都相同的字段,然后自动地将他们连接起来,并返回所有符合条件按的结果。

 

二. 外连接(Outer Join)

 

outer join则会返回每个满足第一个(顶端)输入与第二个(底端)输入的联接的行。它还返回任何在第二个输入中没有匹配行的第一个输入中的行。外连接分为三种:左外连接,右外连接,全外连接。 对应SQL:LEFT/RIGHT/FULLOUTERJOIN。 通常我们省略outer 这个关键字。 写成:LEFT/RIGHT/FULL JOIN。

 

在左外连接和右外连接时都会以一张表为基表,该表的内容会全部显示,然后加上两张表匹配的内容。如果基表的数据在另一张表没有记录。那么在相关联的结果集行中列显示为空值(NULL)。

 

对于外连接, 也可以使用“(+) ”来表示。 关于使用(+)的一些注意事项:

 

1.(+)操作符只能出现在where子句中,并且不能与outerjoin语法同时使用。

 

2. 当使用(+)操作符执行外连接时,如果在where子句中包含有多个条件,则必须在所有条件中都包含(+)操作符

 

3.(+)操作符只适用于列,而不能用在表达式上。

 

4.(+)操作符不能与or和in操作符一起使用。

 

5.(+)操作符只能用于实现左外连接和右外连接,而不能用于实现完全外连接。

 

2.1 左外连接(Left outer join/ left join)

 

left join是以左表的记录为基础的,示例中Dave可以看成左表,BL可以看成右表,它的结果集是Dave表中的数据,在加上Dave表和BL表匹配的数据。换句话说,左表(Dave)的记录将会全部表示出来,而右表(BL)只会显示符合搜索条件的记录。BL表记录不足的地方均为NULL.

 

2.2 右外连接(right outer join/ right join)

 

和leftjoin的结果刚好相反,是以右表(BL)为基础的, 显示BL表的所以记录,在加上Dave和BL 匹配的结果。 Dave表不足的地方用NULL填充.

 

2.3 全外连接(full outer join/ full join)

 

左表和右表都不做限制,所有的记录都显示,两表不足的地方用null 填充。 全外连接不支持(+)这种写法。

 

三. 自连接

 

自连接(self join)是SQL语句中经常要用的连接方式,使用自连接可以将自身表的一个镜像当作另一个表来对待,从而能够得到一些特殊的数据。

 

 

 

游标

 

游标(CURSOR)也叫光标,在关系数据库中经常使用,在PL/SQL程序中可以用CURSOR与SELECT一起对表或者视图中的数据进行查询并逐行读取。

 

Oracle游标分为显示游标和隐式游标。

显示游标(Explicit Cursor):在PL/SQL程序中定义的、用于查询的游标称作显示游标。

隐式游标(Implicit Cursor):是指非PL/SQL程序中定义的、而且是在PL/SQL中使用UPDATE/DELETE语句时,Oracle系统自动分配的游标。

一.显示游标

1.使用步骤

(1)定义 (2)打开 (3)使用 (4)关闭

2.使用演示

首先创建测试用表STUDENT,脚本如下:

 

复制代码 代码如下:

 

 

CREATE TABLE"STUDENT" (

"STUNAME"VARCHAR2(10 BYTE),

"STUNO"VARCHAR2(4 BYTE),

"AGE"NUMBER,

"GENDER"VARCHAR2(2 CHAR)

)

 

 

(1).使用WHILE循环处理游标

create orreplace PROCEDURE PROC_STU1 AS

BEGIN

--显示游标使用,使用while循环

declare

--1.定义游标,名称为cur_stu

cursor cur_stuis

selectstuno,stuname from student order by stuno;

--定义变量,存放游标取出的数据

v_stunovarchar(4);

v_stunamevarchar(20);

begin

--2.打开游标cur_stu

open cur_stu;

--3.将游标的当前行取出存放到变量中

fetch cur_stuinto v_stuno,v_stuname;

whilecur_stu%found --游标所指还有数据行,则继续循环

loop

--打印结果

dbms_output.PUT_LINE(v_stuno||'->'||v_stuname);

--继续将游标所指的当前行取出放到变量中

fetch cur_stuinto v_stuno,v_stuname;

end loop;

close cur_stu;--4.关闭游标

end;

END PROC_STU1;

(2).使用IF..ELSE代替WHILE循环处理游标

create orreplace PROCEDURE PROC_STU2 AS

BEGIN

--显示游标使用,使用if判断

declare

--1.定义游标,名称为cur_stu

cursor cur_stuis

selectstuno,stuname from student order by stuno;

--定义变量,存放游标取出的数据

v_stunovarchar(4);

v_stunamevarchar(20);

begin

--2.打开游标cur_stu

open cur_stu;

--3.将游标的当前行取出存放到变量中

fetch cur_stuinto v_stuno,v_stuname;

loop

if cur_stu%foundthen --如果游标cur_stu所指还有数据行

--打印结果

dbms_output.PUT_LINE(v_stuno||'->'||v_stuname);

--继续将游标所指的当前行取出放到变量中

fetch cur_stuinto v_stuno,v_stuname;

else

exit;

end if;

end loop;

close cur_stu;--4.关闭游标

end;

END PROC_STU2;

(3).使用FOR循环处理游标

create orreplace PROCEDURE PROC_STU3 AS

BEGIN

--显示游标使用,使用for循环

declare

--定义游标,名称为cur_stu

cursor cur_stuis

selectstuno,stuname from student order by stuno;

begin

for stu incur_stu

loop

dbms_output.PUT_LINE(stu.stuno||'->'||stu.stuname);

--循环做隐含检查 %notfound

end loop;

--自动关闭游标

end;

END PROC_STU3;

(4).常用的使用EXIT WHEN处理游标

create orreplace

PROCEDUREPROC_STU1_1 AS

BEGIN

--显示游标使用,使用exit when循环

declare

--1.定义游标,名称为cur_stu

cursor cur_stuis

selectstuno,stuname from student order by stuno;

--定义变量,存放游标取出的数据

v_stunovarchar(4);

v_stunamevarchar(20);

begin

--2.打开游标cur_stu

open cur_stu;

loop

--3.将游标的当前行取出存放到变量中

fetch cur_stuinto v_stuno,v_stuname;

exit whencur_stu%notfound; --游标所指还有数据行,则继续循环

--打印结果

dbms_output.PUT_LINE(v_stuno||'->'||v_stuname);

end loop;

close cur_stu;--4.关闭游标

end;

END PROC_STU1_1;

二.隐式游标

1.使用演示

create orreplace PROCEDURE PROC_STU4 AS

BEGIN

--隐式游标使用

update studentset stuname='张燕广' wherestuno='1104';

--如果更新没有匹配则插入一条新记录

if SQL%NOTFOUNDthen

insert intostudent(STUNO,STUNAME,AGE,GENDER)

values('1104','张燕广',18,'男');

end if;

END PROC_STU4;

2.说明

所有的SQL语句在上下文区内部都是可执行的,因为都有一个游标指向上下文区,此游标就是

SQL游标,与现实游标不同的是,SQL游标在PL/SQL中不需要打开和关闭,而是在执行UPDATE、

DELETE是自动打开和关闭。

上面例子中就是通过SQL%NOTFOUND游标属性判断UPDATE语句的执行结果决定是否需要插入新记录。

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 创作都市 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值