IBATIS的缓存证明还是比较简单的,思路如下:

首先,第一次查询时,从数据库中查询,得到结果.其次,在第二次查询之前,将数据库里的数据改变,再次进行查询.看结果如何.

结果一:查询结果跟第一次一直,缓存设置成功.

结果二:查询结果为更新后结果,缓存设置失败.

好了,话不多说直接上代码.至于jar包导入之类的就不再废话.

一、首先是建立一个简单的javabean,代码如下

package cn.itcast.beans;

import java.io.Serializable;
import java.sql.Date;

public class Student implements Serializable
{
    private int sid;
    private String sname;
    private String major;
    private Date birth;
    
    public int getSid()
    {
        return sid;
    }
    public void setSid(int sid)
    {
        this.sid = sid;
    }
    public String getSname()
    {
        return sname;
    }
    public void setSname(String sname)
    {
        this.sname = sname;
    }
    public String getMajor()
    {
        return major;
    }
    public void setMajor(String major)
    {
        this.major = major;
    }
    public Date getBirth()
    {
        return birth;
    }
    public void setBirth(Date birth)
    {
        this.birth = birth;
    }
    
    @Override
    public String toString()
    {
        String content = "sid="+sid+"\tsname="+sname+"\tmajor="+major+"\tbirth="+birth;
        // TODO Auto-generated method stub
        return content;
    }
    
}

二、然后是javabean对应的student.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE sqlMap 
        PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" 
        "http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="Student">

    <!--模块配置-->
    <!--typeAlias节点: -->
    <!--
        定义了本映射文件中的别名,以避免过长变量值的反复书写,此例中通过
        typeAlias节点为类"cn.itcast.beans.Student"定义了一个别名"Student",
        这样在本配置文件的其他部分,需要引用"cn.itcast.beans.Student"类时,
         只需以其别名替代即可。
    -->
    <typeAlias alias="Student" type="cn.itcast.beans.Student"></typeAlias>
    <cacheModel id="userCache" type="LRU">
         <flushInterval hours="24"/> 
         <flushOnExecute statement="upateStudent"/> 
         <property name="size" value="1000" /> 
    </cacheModel>
    <!--Statement配置-->
    <select id="queryAllStudent" resultClass="Student" cacheModel="userCache">
        <![CDATA[ 
        select sid,sname,major,birth from student
        ]]>
    </select>
    <select id="selectStudentById" parameterClass="int" resultClass="Student" cacheModel="userCache">
    <![CDATA[ 
        select sid,sname,major,birth from student where sid=#sid#
        ]]>
    </select>
    <insert id="addStudent" parameterClass="Student">
    <![CDATA[ 
        insert into student(
        sname,
        major,
        birth
        )
        values(#sname#,#sname#,#birth#)
        ]]>
    </insert>
    <delete id="deleteStudent" parameterClass="int">
    <![CDATA[ 
        delete from student where sid=#sid#
        ]]>
    </delete>
    <update id="upateStudent" parameterClass="Student">
    <![CDATA[ 
        update Student
        set sname=#sname#,
            major=#major#,
            birth=#birth#
        where sid=#sid#
        ]]>
    </update>
    <select id="queryStudentByName" parameterClass="String"
        resultClass="Student">
    <![CDATA[ 
        select sid,sname,major,birth
          from student
         where sname like '%$sname$%'
         ]]>
    </select>
</sqlMap>

注意粗体部分是cacheModel相应的配置

三、SqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config2.0//EN" 
        "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
    <properties resource="sqlMap.properties" />

    <!--cacheModelsEnabled  是否启用SqlMapClient上的缓存机制。建议设为"true" -->
    <!--
        enhancementEnabled 是否针对POJO启用字节码增强机制以提升getter/setter的调用效能,
        避免使用JavaReflect所带来的性能开销。同时,这也为Lazy Loading带来了极大的性能提升。建议设为"true"
    -->
    <!--errorTracingEnabled 是否启用错误日志,在开发期间建议设为"true"以方便调试 -->
    <!--lazyLoadingEnabled  是否启用延迟加载机制,建议设为"true" -->
    <!--maxRequests          最大并发请求数(Statement并发数) -->
    <!--maxTransactions      最大并发事务数 -->
    <!--
        maxSessions 最大Session数。即当前最大允许的并发SqlMapClient数。
        maxSessions设定必须介于maxTransactions和maxRequests之间,
        即maxTransactions<maxSessions=<maxRequests
    -->
    <!--
        useStatementNamespaces
        是否使用Statement命名空间。这里的命名空间指的是映射文件中,sqlMap节点的namespace属性,
        如在本例中针对student表的映射文件sqlMap节点: <sqlMap namespace="Student">
        这里,指定了此sqlMap节点下定义的操作均从属于"才tudent"命名空间。
        在useStatementNamespaces="true"的情况下,Statement调用需追加命名空间,
        如:sqlMapClient.update("Student.upateStudent", student);
        否则直接通过Statement名称调用即可,如:sqlMapClient.update("upateStudent", student);
        但请注意此时需要保证所有映射文件中,Statement定义无重名。
    -->
    <settings cacheModelsEnabled="true" enhancementEnabled="true"
        lazyLoadingEnabled="true" errorTracingEnabled="true" maxRequests="32"
        maxSessions="10" maxTransactions="5" useStatementNamespaces="false" />
    <!--transactionManager节点 -->
    <!--transactionManager节点定义了ibatis的事务管理器,目前提供了以下几种选择:
        Ø  JDBC     通过传统JDBC Connection.commit/rollback实现事务支持。
        Ø  JTA         使用容器提供的JTA服务实现全局事务管理。
        Ø EXTERNAL 外部事务管理,如在EJB中使用ibatis,通过EJB的部署配置即可实现自动的事务管理机制。
        此时ibatis将把所有事务委托给外部容器进行管理。此外,通过Spring等轻量级容器实现
        事务的配置化管理也是一个不错的选择。关于结合容器实现事务管理,参见“高级特性”中的描述。
    -->
    <transactionManager type="JDBC">
        <!--dataSource节点 -->
        <!--
            dataSource从属于transactionManager节点,用于设定ibatis运行期使用的DataSource属性。
            type属性: dataSource节点的type属性指定了dataSource的实现类型。
            可选项目:
            Ø SIMPLE:
            SIMPLE是ibatis内置的dataSource实现,其中实现了一个简单的 数据库连接池机制,对应 ibatis 实现类为
            com.ibatis.sqlmap.engine.datasource.SimpleDataSourceFactory。
            Ø DBCP:
            基于Apache DBCP连接池组件实现的DataSource封装,当无容器提 供DataSource
            服务时,建议使用该选项,对应ibatis 实现类为
            com.ibatis.sqlmap.engine.datasource.DbcpDataSourceFactory。
            Ø JNDI:
            使用J2EE容器提供的DataSource实现,DataSource将通过指定 的 JNDI Name 从容器中获取。对应 ibatis实现类为 
            com.ibatis.sqlmap.engine.datasource.JndiDataSourceFactory。
        -->
        <dataSource type="SIMPLE">
            <property value="${driver}" name="JDBC.Driver" />
            <property value="${url}" name="JDBC.ConnectionURL" />
            <property value="${username}" name="JDBC.Username" />
            <property value="${password}" name="JDBC.Password" />
        </dataSource>
    </transactionManager>
    <sqlMap resource="cn/itcast/beans/Student.xml" />
</sqlMapConfig>

四、sqlMap.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///ibatis
username=root
password=root

五、接口

package cn.itcast.dao;



import java.util.List;

import cn.itcast.beans.Student;

public interface IstudentDao
{
    public void addStudent(Student student);
    public void deleteStudent(int id);
    public void upateStudent(Student student);
    public List<Student> queryAllStudent();
    public List<Student> queryStudentByName(String name);
    public Student queryStudentById(int id);
    
}

六、接口实现类

package cn.itcast.dao.impl;

import java.io.IOException;
import java.io.Reader;
import java.sql.Date;
import java.sql.SQLException;
import java.util.List;

import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;
import com.ibatis.sqlmap.engine.mapping.sql.Sql;

import cn.itcast.beans.Student;
import cn.itcast.dao.IstudentDao;

public class IstudentDaoIbatisImpl implements IstudentDao
{
    private static SqlMapClient sqlMapClient;
    /**
     * 这部分内容应该说是最重要的主要作用是读取配置文件
     * 通过配置文件中的信息进行一系列的操作得到sqlMapClient对象
     * 最后要关闭字符输入流
     */
    static
    {
        try
        {
            //读取SqlMapConfig.xml文件
            Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");
            sqlMapClient = SqlMapClientBuilder.buildSqlMapClient(reader);
            reader.close();
        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    public void addStudent(Student student)
    {
        try
        {
            /**
             * 当Student.xml中<sqlMap namespace="Student">,且SqlMapConfig.xml中setting节点设置了useStatementNamespaces="true"时,
             */
            //sqlMapClient.insert("Student.addStudent", student);
            sqlMapClient.insert("addStudent", student);
        }
        catch (SQLException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    public void deleteStudent(int id)
    {
        
        try
        {
            int i = sqlMapClient.delete("deleteStudent", id);
            System.out.println(i);
        }
        catch (SQLException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }

    public List<Student> queryAllStudent() 
    {
        List<Student> students = null;
        try
        {
            students = sqlMapClient.queryForList("queryAllStudent");
        }
        catch (SQLException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return students;
    }

    public Student queryStudentById(int id)
    {
        Student student = null;
        try
        {
            student = (Student) sqlMapClient.queryForObject("selectStudentById", id);
        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }
        return student;
    }

    public void upateStudent(Student student)
    {
        try
        {
            int i = sqlMapClient.update("upateStudent", student);
            System.out.println(i);
        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }
    }
    
    public List<Student> queryStudentByName(String name)
    {
        List<Student> students = null;
        try
        {
            students = sqlMapClient.queryForList("queryStudentByName", name);
        }
        catch (SQLException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return  students;
    }
    
    public static void main(String[] args)
    {
        IstudentDao dao = new IstudentDaoIbatisImpl();
/**        queryAllStudent
         List<Student> students =dao.queryAllStudent();
         for(Student student: students)
         {
             System.out.println(student);
         }
     System.out.println(students);
 */    
        
/**        queryStudentById
         Student student = dao.queryStudentById(2);
         System.out.println(student);
 */    
        
/**        addStudent
        Student student = new Student();
        student.setSname("houjinxin");
        student.setMajor("电信");
        student.setBirth(Date.valueOf("2012-01-14"));
        dao.addStudent(student);
        System.out.println("插入成功");
*/        
        
/**        deleteStudent
          dao.deleteStudent(2);
        System.out.println("删除成功!");
 */
/**        updateStudent
        Student student = new Student();
        student.setSid(3);
        student.setSname("houjinxin");
        student.setMajor("电信08");
        student.setBirth(Date.valueOf("2012-01-14"));
        dao.upateStudent(student);
 */
        
        
      Student student = null;
student = dao.queryStudentById(2); System.out.println(student); student = dao.queryStudentById(2
); System.out.println(student); } }

注意红色代码部分即为测试代码,终于把他沾出来了。

我的方法是这样,在第二个student前打个断点,然后用debug模式启动,执行到断点处打印一次查询的结果,结果如下

sid=2    sname=woshiou    major=houjinxin    birth=2012-01-14

然后后到数据库中改变所查的记录,如图所示:

继续执行刚才的代码直至结束.结果如下

sid=2    sname=woshiou    major=houjinxin    birth=2012-01-14
sid=2    sname=woshiou    major=houjinxin    birth=2012-01-14

 可以看到,虽然数据库改变了但是查询到的结果,仍然没有改变,所以缓存设置成功。

还要注意一点,验证缓存是否成功的关键是一定要在同一个连接未关闭前验证 ,如果上例改成

    Student student = null;
    student = dao.queryStudentById(2);
     System.out.println(student);

只有一次查询,让他执行两次,那么数据库中是什么,查到的就是什么.就无法检验出缓存是否配置成功。

posted @ 2012-05-11 15:34 houjinxin 阅读(20) 评论(0) 编辑

废了一天的功夫,终于把我的留言功能实现了.有时候一个纠结的问题,会耽误自己很长时间,如何提高开发效率,是个很大的问题!

总结一下今天的内容:

我要实现的功能是,在一篇文章的最后,添加一个留言板块,在留言之后能够直接显示在页面上

第一步:在struts2基本jar包的基础上添加struts2-jsonplugin

第二步:在stuts.xml文件中将extends由默认的struts-default改为json-default

<package name="tutorial" extends="json-default">

第三步:在jsp中引入jquery

<script type="text/javascript" src="js/jquery-1.7.2.js"></script>

第四步:画页面

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://"
            + request.getServerName() + ":" + request.getServerPort()
            + path + "/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
    <head>
        <title>新闻公告</title>

        <link href="css/register.css" rel="stylesheet" type="text/css" />
        <script type="text/javascript" src="js/jquery-1.7.2.js"></script>
        <script type="text/javascript">
        jQuery(document).ready(function()
       {
                $("#mes_button").bind("click",function(event){
                
                var m_name = $("#m_name").val();
                var m_content = $("#m_content").val();
                var b_id = $("#b_id").val();
                $.ajax({
                    type: "POST",
                    url: "addMessage.action",
                    data:{"m_name":m_name,"m_content":m_content,"b_id":b_id} ,
                    success: function (data) {
                               $("#message_list").append("<div class='message_box' id=''><div class='message_text'><strong>" 
                    + data.m_name + "</strong><p>" + data.m_content +"</p></div></div>"); } }); }); }); </script> </head> <body> <div id="main"> <div id="head"> <div class="head_bg"> <div class="head_menu"> <ul> <div class="head_left"> <a href="http://www.cnblogs.com/index.jsp">首页</a> </div> <div class="head_right"> <a href="jsp/news/news.jsp">新闻公告</a> </div> <div class="head_right"> <a href="jsp/news/news.jsp">专业动态</a> </div> <div class="head_right"> <a href="">文章列表</a> </div> <div class="head_right"> <a href="jsp/news/news.jsp">成果展示</a> </div> <div class="head_right"> <a href="">下载中心</a> </div> <div class="head_right"> <a href="">管理员入口</a> </div> </ul> </div> </div> </div> <div class="underhead"> <span class="l"> 正文 </span> </div> <div align="left" style="width: 100%"> <div class="news"> <div class="newscontent"> <h1> <a id="tit" class="tit" href="" target="_blank" mon="a=7">${ins.b_title }</a> </h1> <div class="overcontent"> 时间:${ins.b_date } </div> <div id="content"> ${ins.b_content} </div> <div id="undercontent"> <input id="b_id" type="hidden" name="b_id" value="8"> </div> </div> </div> <div id="message_list"> </div> <div class="message"> <div class="message_title"> 发表评论 </div> <div class="message_user"> 用户名: <input disabled="disabled" id="m_name" type="text" value="houjinxin" name="m_name"/> </div> <form action=""> <div class="message_content"> <textarea id="m_content" rows="5" cols="80" name="m_content"></textarea> </div> <div class="message_button"> <input id="mes_button" type="button" value="提交评论" /> </div> </form> </div> </div> </div> <div> <br/> </div> <div id="foot"> &nbsp;&nbsp; Copyright (c) 2012 Inc All rights reserved 版权所有 by 黑龙江科技学院 <select> <option value="" selected> ----------友情链接---------- </option> <option value=http://www.moe.edu.cn /> 国家教育部 </option> <option value=http://www.pgzx.edu.cn /> 教育教学评估中心 </option> <option value=http://www.hlje.net /> 省教育厅 </option> <option value=http://www.chinasafety.gov.cn/index.htm> 国家安全生产监督管理总局 </option> <option value=http://www.hljmj.gov.cn /> 省煤矿安全监察局 </option> <option value=http://www.chinacoal.org.cn /> 中国煤炭工业网 </option> <option value=http://www.triz.gov.cn /> 技术创新方法 </option> <option value=http://www.cumt.edu.cn /> 中国矿业大学 </option> <option value=http://www.triz.gov.cn /> 中国矿业大学北京校区 </option> </select> </div> <br /> <br /> </body> </html>

第四步:写业务代码

public void addMessage(int b_id,String m_content,String m_name)
    {
        PreparedStatement ps = null;
        try
        {
            String sql = "insert into message(b_id,m_name,m_content,m_date,m_status) values(?,?,?,?,?)"; 
            ps = DBUtils.getConnection().prepareStatement(sql);
            ps.setInt(1,b_id);
            ps.setString(2,m_content);
            ps.setString(3,m_name );
            ps.setDate(4, new Date(new java.util.Date().getTime()));
            ps.setString(5, "1");
            ps.executeUpdate();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            DBUtils.close(ps);
            DBUtils.close();
        }
        
    }

第五步:在action调用该方法:目的是将留言录入数据库

package com.ele.web.action.message;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.sql.Date;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;

import com.ele.services.MessageServices;
import com.ele.services.NewsServices;
import com.ele.vo.Ele_messageVO;
import com.ele.vo.Ele_newsVO;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class AddMessageAction extends ActionSupport
{
    private String m_name;
    
    private String m_content;
    
    private int b_id;
    
    public int getB_id()
    {
        return b_id;
    }

    public void setB_id(int bId)
    {
        b_id = bId;
    }

    public String getM_name()
    {
        return m_name;
    }

    public void setM_name(String mName)
    {
        m_name = mName;
    }

    public String getM_content()
    {
        return m_content;
    }

    public void setM_content(String mContent)
    {
        m_content = mContent;
    }
    
    @Override
    public String execute()
    {

        MessageServices msgServices = new MessageServices();
        msgServices.addMessage(b_id, m_content, m_name);
                return SUCCESS;
    }
    
}

到目前为止,在点击提交按钮后,数据会被显示到页面上,但是刷新之后就没有了.这也是我将要完成的部分.

我设想的解决方法是在查询文章的时候,将留言一并查出,不知道还会遇到什么问题.

在今天的工作过程中,最让我纠结的问题就是,利用ajax异步传值和响应数据处理这部分

试了无数种方法都无果.最后还是在别人的帮助下完成的.留下此文,记录学习过程.

posted @ 2012-05-07 19:56 houjinxin 阅读(304) 评论(2) 编辑

一、oracle的分页

oracle的分页一共有三中方式(这里只有一种)

1.rownum 分页

select * from (select a.*,rownum rn from    (select * from emp) a   where rownum<=15 ) where rn>10;

这条语句是用来将11-15条记录提取出来,拆分这条语句

1.将所有想要的结果查询出来

select * from emp;

2.将上一步的结果作为一个视图,给每一条记录加上一个rn编号并将前15条记录查询出来.其中rownum为oracle的关键字,

且在第一次在查询字段中使用rownum时,如果有条件限制在where子句中也要用rownum,不可以用rn

select a.*,rownum rn from (select * from emp) a where rownum<=15;

3.将前15条数据作为一个视图,提取出11-15条

select * from (select a.*,rownum rn from (select * from emp) a where rownum<=15) where rn>10;

在java程序中只需要替换15和10这两个数字就可以实现分页了

二、用查询结果创建新表

这个命令是一种快捷的建表方法

create table mytable(id,name,sal,job,deptno) as select empno,ename,sal,job,deptno from emp;

三、合并查询

为了合并多个select语句的结果,可以使用集合操作符号,union,union all,intersect(交集),minus(差集)

(1)union

该操作符,用于取得两个结果集的并集,使用时自动去掉相同部分结果集

select ename,sal,job from emp where job='MANAGER' union select ename,sal,job from emp where sal>2500;

(2)union all

与union相似,但是不取消重复行,而且不排序

(3)intersect

取交集

(4)minus

取差集 只会显示存在第一个集合中,而不存在在第二个集合中的数据

集合操作要比and,or效率高很多

四、操作数据

使用特定的格式插入日期值

(1)使用to_date函数

?如何插入带有日期的表,并按照年月日格式插入

insert into emp values(9994,'hou','PRESIDENT',null,to_date('1990-10-10','YYYY-MM-DD'),800,1000,10);

使用to_date函数可以插入任意形式的日期

(2)使用子查询插入数据 一条insert语句可以插入大量的数据,当处理行迁移或者装载外部表的数据到数据库时, 可以使用子查询插入数据

insert into mytable(id,name,deptno) select empno,ename,deptno from emp where deptno=10;

(3)使用子查询更新数据 ?希望员工scott的岗位、工资、补助与SMITH一样

update emp set (job,sal,comm)= (select job,sal,comm from emp where ename='SMITH' ) where ename='SCOTT'; ename的值要用大写,oracle对值的大小写是敏感的

posted @ 2012-04-12 14:30 houjinxin 阅读(49) 评论(0) 编辑

Oracle的复杂查询

在实际应用中经常需要执行复杂的数据统计,经常需要现实多张表的数据

所以经常要用到数据分组函数如 max(), min(),avg(),sum(),count()等

一、分组函数

?如何显示所有员工中最高工资和最低工资

select max(sal),min(sal) from emp;

?如何查询最高,最低工资的人是谁

select ename,sal from emp where sal= (select max(sal) from emp); select ename,sal from emp where sal= (select min(sal) from emp);

这里利用了子查询

?请显示工资最高的员工的名字,工作岗位

select ename,job from emp where sal= (select max(sal) from emp);

?请显示工资高于平均工资的员工信息

select * from emp where sal> (select avg(sal) from emp) select avg(sal) from emp ;

如果这里不是*号而是ename,sal等字段与分组函数那么在语句的最后要加上 group by ename,sal..(与select后的字段一致)

二、group by 和having 子句

group by 用于对查询结果分组统计

having子句用于限制分组显示结果

?如何显示每个部门的平均工资和最高工资

select avg(sal),max(sal),deptno from emp group by deptno;

分组字段依据必须出现在查询结果中,否则结果可读性太差

?如何显示每个部门的每种岗位的平均工资和最低工资

select avg(sal),min(sal),job,deptno from emp group by job,deptno;

? 显示平均工资低于2000的部门和它的平均工资

select avg(sal),max(sal),deptno from emp group by deptno having avg(sal)>2000;

三、对分组函数的总结

1.分组函数只能出现在选择列表,having,group by,order by子句中

2.如果在select语句中同时包含有group by,having, order by,那么顺序为group by,having,order by

3.在选择列中如果有列,表达式,和分组函数,那么这些列表达式必须有一个出现在group by 子句中,否则出错 如:select deptno,avg(sal),max(sal),max(sal) from emp group by deptno having avg(sal)>2000; 这里的deptno就一定要出现在group by中

四、多表查询

基于两个或两个以上的表或是视图的查询

查单表满足不了要求如部门和员工的关系

?显示雇员名,雇员工资及所在部门的名称

select a.ename,a.sal,b.dname from emp a,dept b where a.deptno=b.deptno;

如果不加where子句,就会产生笛卡尔集

所谓笛卡尔集,就是不加筛选,将所有的都查询出来

两张表关联,至少需要一个条件排除笛卡尔集

三张表关联,至少需要二个条件排除笛卡尔集

以此类推:多表查询中,判断条件至少是表的个数-1

?如何显示部门号为10的部门名,员工名和工资

select b.dname,a.ename,a.sal from emp a,dept b where a.deptno=b.deptno    and b.deptno=10;

?显示各个员工的姓名,工资及工资的级别

select a.ename,a.sal,b.grade from emp a,salgrade b where a.sal between losal and hisal;

这里用到了between ... and 子句. 表示在losal和hisal之间(很好理解)

?显示雇员名,雇员工资及所在部门的名字,并部门排序

select a.ename,a.sal,b.dname,b.deptno   

from emp a,dept b  

where a.deptno=b.deptno  

order by b.deptno;

五、自连接

自连接:指在同一张表内的连接查询

?显示某个员工的上级领导的姓名

select worker.ename,boss.ename

  from emp worker,emp boss

where worker.mgr=boss.empno   

and worker.ename='FORD';

根据FORD的名字找到ford的mgr编号再根据这个编号找到boss的empno,最后显示出来

六、子查询

子查询:指嵌入在其他sql语句中的select语句,也叫做嵌套查询

(1)单行子查询:是指只返回一行数据的子查询语句

?如何显示与SMITH同一部门的所有员工 分两步:

1.查出SMITH所在部门

2.根据部门查出所有员工

1.select deptno from emp where ename='SMITH';

2.select ename from emp where deptno=(select deptno from emp where ename='SMITH');

(2)多行子查询:返回多行数据的子查询

?如何查询和部门10的工作相同的雇员的名字,岗位,工资,部门号

1.首先查出部门10的工作种类

select job from emp where deptno=10;

发现有重复结果.所以在job前加上distinct

select distinct job from emp where deptno=10;

2.根据工作的种类查询

select ename,job,sal,deptno   

from emp where job in  

(select distinct job from emp where deptno=10);

注意这里job之后用的是"in"而非"=".

(3)all操作符

?如何显示工资比部门30的所有员工的工资高的员工的姓名,工资和部门号

select ename,sal,deptno from emp where sal>all (select sal from emp where deptno=30);

可以使用max方法

select ename,sal,deptno from emp where sal> (select max(sal) from emp where deptno=30);

max方法的效率较高,原因是使用all操作符时,要和子查询所得结果逐一比较 而使用max只需和sal中的最大值比较,减少了比较的次数,缩短了时间. 数据量较大是会比较明显,数据量较小基本看不出来

(4)any操作符

?如何显示工资比部门30的任意一个员工的工资高的员工的姓名,工资和部门号

select ename,sal,deptno from emp where sal>any (select sal from emp where deptno=30);

可以使用min方法

select ename,sal,deptno from emp where sal> (select min(sal) from emp where deptno=30);

原理同上

(5)多列子查询

多列子查询:指子查询返回多列数据 ?如何查询与SMITH部门和岗位完全相同的所有雇员

1.查询出SMITH的部门号,岗位

select deptno,job from emp where ename='SMITH';

2.显示结果

select * from emp where (deptno,job)=  

(select deptno,job     

from emp    

where ename='SMITH'  

);

(6)在from子句中使用子查询

?如何显示高于自己部门的平均工资员工信息

1.查询各个部门的平均工资和部门号

select avg(sal) avgsal,deptno from emp group by deptno;

这里group by deptno是必须要有的.用来对分组结果进行统计

2.把上面的查询看作是一张子表

select a.ename,a.sal,a.deptno,b.avgsal  

from emp a,   (select avg(sal) avgsal,deptno from emp group by deptno) b

where a.deptno=b.deptno and a.sal>b.avgsal;

这个比较难想到,将这两个表做关联查询 当在from子句中使用子查询时,该子查询会被作为一个视图来对待,因此叫做内嵌视图 挡在from子句中使用子查询时,必须为子查询指定别名

posted @ 2012-04-09 16:24 houjinxin 阅读(39) 评论(0) 编辑

Oracle的基本查询

首先,介绍PL/SQL软件中两个命令

1.清屏命令

  clear

2.关闭/打开显示操作时间命令

    set timing off/on

其次,是两个sql技巧

1.快速向数据库中插入大量数据

insert into users(userid,username,userpass)

       select * from user;

使用这个语句的前提是表中至少要有一条数据

2.查询所有记录数

select count(*) from user;

需要注意的是在写SQL 语句时,要注意大小写问题

Orace的字段不区分大小写,实体却区分大小写

一、使用算数表达式

? 显示每个雇员的年工资

可以使用列的别名

select ename "姓名",sal*12 as "年收入" from emp;

这里的中文最好用引号引上,尽量不要用中文

?如果计算表达式中有一个null值那么计算结果就为null,如何处理null值?

使用nvl函数处理

select sal*13+nvl(comm,0) "年工资" ,ename from emp;

nvl(comm,0)的意思是如果comm为null,那么按0计算,不是0按本身计算

?如何连接字符串

用"||"

select ename || ' is a ' || job from emp;

二、使用where子句

?如何显示工资高于3000的员工

select ename,sal from emp where sal >3000;

?如何查找1982.1.1后入职的员工

select ename from emp where hiredate>'1-1月-1982';

?查找工资在2000-2500之间的员工

select ename from emp where sal>=2000 and sal <=2500;

三、如何使用like操作符

%: 表示0到多个字符

_:表示任意单个字符

?如何显示首字母为s的员工

select ename from emp where ename like ‘s%’;

?如何显示第三个字母为大写O的所有员工的姓名和工资

select ename, sal from emp where ename like '__O%';

四、在where条件中使用in

?如何显示empno为123,456,234的雇员情况

select * from emp where empno in(123,234,456);

这种查询效率很高

五、使用is null操作符

? 如何显示没有上级的雇员情况

select * from emp where mgr is null;

六、使用逻辑操作符号

?查询工资高于500或是岗位为MANAGER的雇员,同时还要满足他们的姓名首写字母为大写的T

select * from emp where (sal>500 or job='MANAGER') and ename like 'T%';

这里的括号不可以忘记,否则条件就变了,因为and的优先级高于or

七、使用order by 子句

?如何按照工资从高到低的顺序显示雇员

select ename from emp order by sal desc;

desc 为逆序 asc为顺序(默认)

?按照部门号升序而雇员工资降序排列

select * from emp order by deptno asc,sal desc;

八、使用列的别名排序

select ename ,sal*12 "年薪" from emp order by "年薪" asc;

posted @ 2012-04-09 16:20 houjinxin 阅读(26) 评论(0) 编辑

表的管理 

一、表名和列的命名规范

1.必须以字母开头

2.长度不能超过30个字符

3.不能使用oracle的保留字

4.只能使用如下字符串,A-->Z,a-->z,0-->9,$,#等

二、oracle支持的数据类型

1、字符型

char 定长,最长2000字符

例如:char(10) 存储内容为“小韩”时,前4个字符放‘小韩’,后六位由空格补齐

优点是:效率高,查询速率快。如身份证的字段可以设置成char(18)。

varchar2 变长 最大4000字符(oracle推荐使用)

varchar2(10) 存储内容为“小韩”时 oracle分配4个字符

clob(character large object) 字符型大对象

最大4G

2、数字类型

number范围-10的38次方到10的38次方

可以是整数,也可以是小数

number(5,2)表示一个小数有5位有效数字,2位是小数

例如:定义一个范围在-999.99-999.99的数字可以用number(5,2)

定义一个范围在-99999-99999可以用number(5)

3、日期类型

date 包含年月日和时分秒

timestamp oracle对date类型的扩展

4、图片类型

blob 二进制数据,可以存放图片,音频,视频最大4G

这个类型允许我们将大文件存储进数据库,但是一般在数据库里,存放的应该是这些文件的路径,如果对安全性有要求,可以将文件放入数据库

三、建表语句

1)建表

sql>create table student(--表名

Idnumber(4), --学号

Namevarchar(20), --姓名

Sex char(2),--性别

birthday date);--出生日期

上面的语句足以建立一个简单的学生表

2)向已经建立的表中添加字段

sql>alter table student add(ClassId number(2));

3)修改字段的长度

sql>alter table studentmodify(Name varchar2(50) );

4)修改字段的类型/或名字(不能有数据)

sql>alter table student modify(Name char(20));

sql>alter table student rename Name to Sname;

5)删除一个字段(慎重使用)

alter table student drop column Sex

6)修改表的名字

sql>rename student to stu

7)删除表

drop table student

8)查看表结构

desc student;

四、操作表

1、添加数据,所有字段必须都插入

insert into student values(1,'张三','男','01-5月-05');

不要以为这里写错了,oracle中默认的日期格式‘DD-MON-YY’ (日-月-年)

想要修改日期的默认格式可以这样做

sql>alter session set nls_date_format='YYYY-MM-DD';

修改以后就可以用我们熟悉的格式来添加类型

insert into student values(1,'张三','男','2000-08-31');

但是这里的修改只是临时成立的,要想永久改变日期输入格式是需要改注册表的,还有一个方法是使用函数,暂且略过

2、插入部分字段,前提是未插入的字段允许为null

insert into student(Id,Name) values(1,'张三');

3、插入空值

insert into student(Id,Name,Sex) values('1',null,null);

4、查询Name为空的一条记录

按照正常的逻辑,许多人会这样做

select * from studentwhere Name=null;

但是这样的结果是什么都查不到,正确的方法如下

select * from student where Name is null;

查询所有非空的就在is后面加上not

5、修改一个字段

update student set sex=‘女’ where Id=‘1’

6、修改多个字段

update student set sex=‘男’,Name='赵四' whereId=‘1’

7、修改含有null值的字段

update student set Name=‘张三’ where Name is null

8、删除数据(三中方式)

1)删除一条记录

delete from student where Id=‘1’

2)删除所有记录,表结构还在,会记录日志,这种删除是可以恢复的,速度会稍慢

delete from student

3)删除表的结构和数据

drop table student ;

4)删除所有记录,表结构还在,不记录日记,所有这种删除无法找回数据,但是速度很快

truncate table student;

9、恢复数据

用delete from student 时数据可恢

1)首先要设置一个保存点

savepoint sp;--sp是保存点名称,可以随意起名,作用是将数据保存在日志中

2)删除数据

delete from student ;

3)查询验证数据是否被删掉

select * from student

结果是肯定的,没有数据

4)回滚数据

rollback to sp;

5)在查询验证数据回滚是否成功

select * from student

结果还是肯定的数据回来了!

当然可以设置多个保存点,但是如果不做处理,新的保存点会默认覆盖前一个保存点

10、取消重复行

select distinct deptno,job from emp;

在查询时select后面加上distinct即可将重复数据略去

posted @ 2012-04-09 16:16 houjinxin 阅读(71) 评论(0) 编辑

使用profile 管理用户口令  

profile是口令限制,资源限制的命令集合。当建立数据库时,oracle会自动建立名称为default的profile。当建立用户没有制定profile选项,那oracle就会将default分配给用户。  

(1)帐号锁定  

指定登录时最多可以输入密码的次数,也可以指定用户锁定的时间,以天为单位。一般用dba的身份去执行命令例如:指定stu最多只能尝试三次登录,锁定时间为2天

sql>create profile lock_account limit failed_login_attempts 3 password_lock_time 2;

sql>alter user stu profile lock_account;  

(2)给账户解锁  

sql>alter user stu account unlock;

(3)终止口令  

为了让用户定期修改密码,可以使用终止口令的指令完成,同样这个命令也要dba身份来操作  给stu创建一个profile文件,要求该用户每隔10天要修改登录密码,宽限期2天

 sql>create profile stu limit password_life_time 10 password_grace_time 2;

 sql>alter user stu profile stu;

 解锁方式同上

 (4)口令历史  

如果希望用户在修改密码时,不能使用以前用过的密码,可以使用口令历史,这样oracle就会将口令修改的信息存放在数据字典中,这样当用户修改密码时,oracle就会对新密码与就得进行对比,如果一样提示用户重新输入。

  例如:

 sql>create profile password_history limit password_life_time 10 password_grace_time 2 password_reuse_time 10  

sql>alter user stu profile password_history;

password_reuse_time 10 表示10天后口令可重复使用

 (5)删除profile  

 drop profile password_history [cascade]

 cascade表示如果已经将profile分配给某个用户时,仍要删除profile,就要加上cascade

posted @ 2012-02-10 23:13 houjinxin 阅读(191) 评论(0) 编辑

一、Oracle用户管理

创建用户,需要DBA权限

命令:create user 【用户名】identified by 【密码】

修改密码

命令:password 【用户名】 ( 在用户已经连接的情况下 )

注意:在给其他用户修改密码时  需要具有DBA的权限或拥有alter user的系统权限

命令:alter user 【用户名】 identified by 【新密码】

删除用户

一般以DBA身份去删除用户

如果要删除的用户,已经创建了表,要在删除时加上一个参数 cascade

命令:drop user 【用户名】 [cascade]

二、权限和角色

刚刚创建完的新用户是没有任何权限的,甚至连登录数据库的权限都没有。这是时候使用conn 【用户名】/【密码】会提示没有权限

在新建一个用户之后还要对这个用户进行授权操作。当然了,要使用有能力授权的用户,如sys、system

权限包含系统权限对象权限

系统权限:用户对数据库的相关权限

对象权限:用户对其他用户的数据对象操作的权限

角色

角色是指由系统权限集合。通常给某个用户授予权限时如果没有角色存在的话,那么需要一条一条的操作,角色的存在

就是使得授权变得很方便。通常一个角色由多个系统权限组成。常用的角色有三个connect(7种权限)、dba、resource(在任何表空间建表)。

这里只是简单的提一下,在以后会作为一个专题进行研究。

使用grant命令给用户分配权限

grant 【权限名】 to 【用户名】

分配角色

grant 【角色名】 to 【用户名】

收回权限

revoke 【权限名】 from 【用户名】

举个例子来说明:

1、创建用户

create user stu identified by stu;

2、使stu能够被连接

grant create session to stu;

3、让stu能够在任何表空间下建表

grant resource to stu

3、创建一个简单的表

create table users(name varchar2(10),age number(2));

4、插入几条数据

insert into users values('houjinxin',22);

5、登录到scott给stu授权让stu可以查看scott下的emp表

grant select on emp to stu;

6、登录到stu下查看emp表

select * from scott.emp;

如果这时想要更新scott.emp中的数据

update scott.emp set ename='ok2' where ename='ok';

会提示ORA-01031: 权限不足 。因为scott只给了stu查看的权利,如果仍然想更新,要到scott下进行授权

7、登录到system下收回resource角色

revoke resource from stu;

8、登录scott下收回select 权限

revoke select on emp from stu;

这是stu就不能再查询scott.emp的数据了

权限的传递

当希望stu用户可以去查询scott的emp表时,还希望stu能够把这个权限继续传给其他用户时

如果要传递的是对象权限,就加入with grant option

grant select on emp to stu with grant option

如果是系统权限:就加上with admin option

grant connect to stu with admin option

当system给stu授权时,会给stu给其他用户授权的能力

做个实验来验证下

1、登录到system用户下,重新建立两个用户

create user hou identified by hou;

create user jin identified by jin;

并为hou分配connect角色

grant connect to hou with admin option;

2、登录到scott下个hou授权

grant select on emp to hou with grant option;

3、登录到hou下开始对jin授权

grant select on scott.emp to jin;

grant connect to jin;

4、登录到jin下查询scott.emp

select * from scott.emp;

到目前位置都正常,问题来了!

如果system收回分配给hou的权限,那么jin的权限会不会也被一起收回,继续实验。

5、登录到scott下收回hou的权限

revoke select on emp from hou;

revoke connect from hou;

6、登录到jin下看现象

发现仍然能够登录到jin上这说明connect角色并未被收回

而当查询scott.emp时却提示ORA-00942: 表或视图不存在

这说明系统权限和对象权限是不同的。对于系统权限,hou分配给jin之后不再收回,对象权限却随着hou的权限被收回也被同时收回了

posted @ 2012-02-10 01:21 houjinxin 阅读(158) 评论(0) 编辑

一、以下是sqlplus常用命令

(1)conn[ect]

用法:conn 用户名/密码@网络服务名[as sysbda/sysoper]

当用户是特权用户时必须带上as sysbda/sysoper

例如:conn system/manager

(2)disc[onnect]

断开连接

(3)passw[ord]

修改密码,当想要修改其他用户密码用sys或system登录

(4)show user

显示当前用户

(5)exit

断开连接,并退出sqlplus

二、文件操作命令

(1)start、@

说明:运行sql脚本

如:在d:\ 下有a.sql这个文件,运行下面的命令即可执行a.sql中的内容

sql>@ d:\a.sql 或者

sql>start d:\a.sql

(2)edit

编辑指定的sql脚本

sql>edit d:\a.sql

(3)spool

该命令可以将sqlplus屏幕上的内容输出到制定的文件中去

sql>spool d:\b.sql

sql>select * from emp;

spl>spool off

说明:spool命令将select * from emp;的查询结果输出到指定位置的文件中 然后spool off类似于IO的开启/关闭

三、交互式命令

(1)&

可以替代变量,而该变量在执行时需要用户输入

sql>select * from emp where job='&job';

oracle会提示用户输入值

四、显示和设置环境变量

可以用来控制输出的各种格式,如果希望永久的保存相关设置,可以修改glogin.sql脚本

(1)linesize

设置显示行的宽,默认是80个自己字符

sql>show linesize

sql>set linesize 120

(2)pagesize

设置每页显示的行数默认是14,用法同linesize

其他环境参数的使用也是大同小异

posted @ 2012-02-10 01:17 houjinxin 阅读(161) 评论(0) 编辑

一、oracle安装过程略

二、sys用户和system用户

(1)sys用户是超级用户,具有最高权限,具有sysdba角色,有create database的权限

默认密码是manager

(2)system用户是管理操作员,权限也很大,具有sysoper角色,但没有create database的权限,默认密码为change_oninstall

(3)一般对数据库的维护,使用system用户登录就足够了

三、oracle的启动

所谓的启动是指启动oracle的实例,即OracleServiceORCL,在使用java连接数据库时必须要启动监听器,否则就不能够使用JDBC。

四、oracle的数据对象

在oracle中表、视图、存储过程、触发器在oracle中被称为数据对象

五、oracle管理工具

sqlplus是oracle自带的工具软件,主要用来执行sql语句

     

posted @ 2012-02-10 01:14 houjinxin 阅读(217) 评论(2) 编辑