《数据库系统应用程序开发》期末复习

前言

以下主要是吉林大学软件工程数据库应用db2课程的复习资料,希望能够帮到找到这里的学弟学妹们。

不过需要注意的是:

  • ①所有罗列出的代码因为不要求具体编译环境,所以可能跟实际运行会有出入,在此只是给大家一个基本的参照和思路,请不要以这个为标答。
  • ②请注意你们的考试范围,我们这届老师画的范围如下:
    • 全部来自报告内容
    • 只有五道题(每道题都是代码题)
    • 会给一个数据库表
    • 要求掌握需要导入哪些包,有哪些公共方法
    • 去年考的批处理、查询并更新、clog、blog
    • 今年不考GUI
  • ③最后鸣谢我的学长学姐们,因为我也是靠他们传下来的资料和学校奔腾的考题去抱的佛脚。

然后整篇博客,我是按照“复习总结报告涉及的知识点——真题演练”的脉络进行的。本门课程的考核实验报告占一半,笔试占一半,而笔试其实也就是考察对相关语句的记忆和理解(主要还是背,背了才会用)。


考完了我靠记忆复原一下我们考的内容(我是2019级,今天是2021/12/31):
表给的是员工表(姓名、年龄、性别、工资、简历、照片)

  1. 单行插入、多行插入、子查询插入
  2. 用for update和where current of进行修改,好像是把名字为xxx的改为yyy
  3. 将员工原有工资增加5%,并写出溢出的异常处理
  4. 用setNULL和wasNULL对员工某个属性栏进行判空处理
  5. CLOB(简历)的读取并按要求输出指定内容

emmmmmm一整个大无语的状态,抱佛脚的内容从来记不住,记住的从来也从来不是临时抱佛脚背下来的,别指望两天速成,还是平时花时间多用吧


一. 报告知识点复习

1 任务1-3(Java连接数据库基本步骤)

1.1 加载jdbc驱动程序

Class.forName("COM.ibm.db2.jdbc.app.DB2Driver");

1.2 创建数据库的连接

String url = "jdbc:db2:sample";//欲连接的数据库路径
String userid=”db2admin”;//用户名
String passwd=”db2admin”;//密码
Connection sample=DriverManager.getConnection(url,userid,passwd);

1.3 ①写sql语句并创建一个 PreparedStatement/Statement语句;②并执行存入ResultSet结果集。

1.3.1 ①写sql语句并创建一个 PreparedStatement/Statement语句;

用到的sql语句分两类:

  • 查询
  • 删除,插入,更新

因为Sql语句如果是select查询类型的,查询之后的行数列数内容就用ResultSet存储。
而Sql如果是插删改的话,返回值是插入/修改/删除的行数int型。

//执行查询数据库的SQL语句,返回一个结果集(ResultSet)对象。    
ResultSet executeQuery(String sqlString)

//用于执行INSERT、UPDATE或DELETE语句以及SQL DDL语句,如:CREATE TABLE和DROP TABLE等    
int executeUpdate(String sqlString)

//一般用于sql语句中没有?的、可以直接执行的语句
//(1)Statement:
String sql ="select NAME, JOB, SALARY from staff Where ID = 10"//sql语句
Statement stmt = sample.createStatement();//创建statement语句
ResultSet rs = stmt.executeQuery( sql);//执行,并存入结果集

//一般用于sql语句中有?需要赋值的、不可以直接执行的语句。
//(2)PreparedStatement:
String sql="insert into templ(empno,firstnme,lastname,edlevel) values (?,?,?,?)";//sql语句
PreparedStatement pstmt = sample.prepareStatement(sql);//创建 PreparedStatement语句
pstmt.setString(1,deptno);//记住,从1开始,不是从0开始set,规定。deptno是一个字符串,自己定义即可,意思是将定义好的deptno赋值给第一个问号出现的地方。
pstmt.setString(2,deptno);//同理,给第二个问号赋值
pstmt.setString(3,deptno);
pstmt.setString(4,deptno);
int rows=pstmt.executeUpdate();//返回更新过的行数。
//而这一步,我们上面提到过如果是插删改的话,rows的值可以直接传回,但是如果是查询语句的话,那么就要遍历结果集得到一个ResultSet对象才行。

1.3.2 ②并执行存入ResultSet结果集。

while(rs.next()){    
    String data1 = rs.getString(1) ; //从1开始
    String data2 = rs.getString(2) ; 
    String data3 = rs.getString(3) ; 
    String data4= rs.getString(4) ; 
     }    

结果集有很多库函数,getString最常用,指取出的那一列属性的是字符串类型,
如果那一列属性是整数类型,就用getInt

1.4 处理异常,关闭jdbc对象资源

操作完成以后要把所有使用的JDBC对象全都关闭,以释放JDBC资源,关闭顺序和声明顺序相反,正常的声明顺序是“建立连接——获取当前状态——根据操作返回结果集”,所以反过来,我们的关闭顺序为:
1、先关闭ResultSet
2、再关闭preparedStatement
3、最后关闭连接对象connection

if(rs != null){   // 关闭结果记录集    
        try{    
            rs.close() ;    
        }catch(SQLException e){    
            e.printStackTrace() ;    
        }    
   }    
if(stmt != null){   // 关闭状态声明对象    
        try{    
            stmt.close() ;    
        }catch(SQLException e){    
            e.printStackTrace() ;    
        }    
   }    
if(conn != null){  // 关闭连接对象    
         try{    
            conn.close() ;    
         }catch(SQLException e){    
            e.printStackTrace() ;    
         }    
}  

2 任务4:窗口交互

涉及到一点交互,就是先不指定sql的判定语句中的值,通过弹出一个窗口,获得用户输入再赋值查询。

String inputValue = JOptionPane.showInputDialog("Please input a value");//输入的东西保存在inputValue
JOptionPane.showMessageDialog(null, "\nNumber of rows updated: " + updateCount);//弹出一个输出框显示更新行数

3 任务5:表格的相关操作,创建表格

String[] Names = { "编号", "名字", "姓氏", "职位"};//表头
Object[][] Info = new Object[4][4];//表格内容,几行几列
JTable table = new JTable(Info, Names);//创建表格

表格主要的库函数

//1.获取单元格数据
String cellValue=(String) tableModel.getValueAt(row, column);// 取单元格数据,row是行号,column是列号
//2.给单元格数据赋值,即给二维数组赋值,一般用ResultSet结果集赋值定义的表格Info
for(int i=0;i<4;i++)
   for(int j=0;j<4;j++){
      System.out.println(j+"ci");
      info[i][j]=rs.getString(j+1);						
    }
}
//3.单行插入 
String single_insert="insert into templ(empno,firstnme,lastname,edlevel)values (?,?,?,?)";

//4.多行插入 
int count =4//用户想插入四行
String sql="insert into templ(empno,firstnme,lastname,edlevel) values (?,?,?,?)";
for(int i=0;i<3;i++){
    sql=sql+",(?,?,?,?)";
}

//5.通过子查询插入 
String find_insert="insert into templ(empno,firstnme,lastname,edlevel)"+
                    "select empno,firstnme,lastname,edlevel from employee "+
                    "where empno=? "+
                    "and firstnme=? "+
                    "and lastname=? "+
                    "and edlevel=?";

4 任务6:ResultSet的wasNull()方法

//用于读取结果集下一行的语句判断是否为空
rs.next();
while(rs.next()){
......
}
rs.wasNull();

5 任务8:实现对结果集的任意行,任意列的修改

5.1 第一种方法

String finalstr="";
String selectforupdate="select empno,firstnme,lastname,edlevel,job  from employee" +" for update";
//sql语句,不要忘记加上for update!!

int finalrow=0; 
int finalcolmn=0;
int r= table.getSelectedRow();//得到表格被选中的行数,与结果集对应 finalrow=r;
int c=table.getSelectedColumn();//得到表格被选中的列数,与结果集对应 finalcolmn=c;
stmt=sample.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE); //创建可滚动,可更新的结果集
ResultSet select_rs=stmt.executeQuery(selectforupdate);
for(int i=0;i<finalrow;i++){ 
    select_rs.next();//结果集移动到第finalrow行
}
if(select_rs.next()){ 
	select_rs.updateObject(finalcolmn,finalstr);//更新结果集的第finalcolumn列,更新为finalstr
}
select_rs.updateRow();//将结果集落实到数据库

5.2 第二种方法

String finalstr=""; 
String selectforupdate="select empno,firstnme,lastname,edlevel,job from employee"+" for update";
//sql语句,不要忘记加上for update!! 
int finalrow=0; 
int finalcolmn=0;
int r= table.getSelectedRow();//得到表格被选中的行数,与结果集对应 
finalrow=r; 
int c=table.getSelectedColumn();//得到表格被选中的列数,与结果集对应 
finalcolmn=c;
stmt=sample.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.
CONCUR_UPDATABLE); 
ResultSet select_rs=stmt.executeQuery(selectforupdate);
select_rs.absolute(finalrow+1);//直接定位到第finalrow+1行
select_rs.updateObject(finalcolmn+1,finalstr);
select_rs.updateRow();

6 任务9:

6.1 创建可滚动的结果集,使用last,previous,first函数遍历

String sql="select NAME,JOB,SALARY from staff";
PreparedStatement stmt=sample.prepareStatement(sql,rs.TYPE_SCROLL_INSENSITIVE,rs.CONCUR_READ_ONLY);  //为了创建可滚动,只读的结果集
ResultSet rs = stmt.executeQuery( );    
 rs.last();
 rs.previous();
rs.first();

知识

rs.absolute()//绝对位置,负数表示从后面数
rs.first()第一条
rs.last()最后一条
rs.previoust()前一条
rs.next()后一条

6.2 批处理操作,同时执行多条语句

Statement接口里有两个方法:

  • void addBatch(String sql)——将给定的 SQL 命令添加到此 Statement 对象的当前命令列表中。通过调用方法 executeBatch可以批量执行此列表中的命令。
  • int[] executeBatch()——将一批命令提交给数据库来执行,如果全部命令执行成功,则返回更新计数组成的数组。

返回:包含批中每个命令的一个元素的更新计数所组成的数组(数组中的每个元素为:成功处理了命令后,执行命令所影响数据库中行数的更新计数)。数组的元素根据将命令添加到批中的顺序排序。
批处理操作,即同时执行多条语句
代码:

Statement stmt=sample.createStatement();
stmt.addBatch("INSERT INTO DB2ADMIN.DEPARTMENT " +
              "VALUES ('BT6','BATCH6 NEWYORK','BBBBB1','BTT','NEW YORK CITY6')");
stmt.addBatch("INSERT INTO DB2ADMIN.DEPARTMENT " +
               "VALUES ('BT7','BATCH7 NEWYORK','BBBBB2','BT2','NEW YORK CITY7')");   
int []updateCounts=stmt.executeBatch();
sample.commit();

6.3 获取数据库结构

DatabaseMetaData dbmd=sample.getMetaData();//获取数据库的结构,存储等信息。
String []tableTypes={"TABLE","VIEW"};
ResultSet rs=dbmd.getTables(null,"UDBA","%",tableTypes);

知识:

  • dbmd.getTables(String catalog,String schema,String tableName,String[] types),这个方法带有四个参数,它们表示的含义如下:
    String catalog:要获得表所在的编目。"“”“意味着没有任何编目,Null表示所有编目。
    String schema:要获得表所在的模式。”“”"意味着没有任何模式,Null表示所有模式。
    String tableName:指出要返回表名与该参数匹配的那些表。
    String types:一个指出返回何种表的数组。可能的数组项是:“TABLE”、“VIEW”、“SYSTEM TABLE”, “GLOBAL TEMPORARY”,“LOCAL TEMPORARY”,“ALIAS”,“SYSNONYM”。
  • 通过getTables()方法返回的结果集中的每个表都有下面是10字段的描述信息,而且只有10个。通常我们用到的也就是标红的几个字段。而且在结果集中直接使用下面字段前面的序号即可获取字段值。
    1.TABLE_CAT (String) => 表所在的编目(可能为空)
    2.TABLE_SCHEM (String) => 表所在的模式(可能为空)
    3.TABLE_NAME (String) => 表的名称

7 任务10:blob类型对象的读取和插入

Blob类型的赋值,用setBinaryStream(int n, java.io.InputStream x, int length)语句:
①n指示参数编号的 int
②InputStream 对象
③length指示字节数的 int。

7.1 查询图片代码

Statement st=conn.createStatement();
ResultSet rs=st.executeQuery("select image from employee");
while(rs.next()){
    //读取Blob对象
    Blob blob= (Blob) rs.getBlob(1);
    
    //Blob对象转化为InputStream流
    java.io.InputStream inputStream =blob.getBinaryStream();
    
    //要写入的文件
    File fileOutput = new File("c:/backa.jpg");
    
    //文件的写入流的定义
    FileOutputStream fo = new FileOutputStream(fileOutput);
    int c;
    //读取流并写入到文件中
    while ((c = inputStream.read()) != -1)
        fo.write(c);
        //流的关闭:
        fo.close();
}

7.2 插入图片代码

PreparedStatement preparedStatement = conn.prepareStatement("insert into emp_photo values('000130','jpeg',?)");
//创建文件对象:
File file=new File("e:/123.jpg");//参数是本地图片的路径名
// 创建流对象: 
BufferedInputStream imageInput = new BufferedInputStream(new  FileInputStream(file));
//参数赋值:
preparedStatement.setBinaryStream(1, imageInput,(int)file.length());
//第二个参数InputStream 对象,第三个参数字节数int
//执行语句
preparedStatement.executeUpdate();

8 任务11:clob类型的读取

Clob resumelob = null;//定义clob类型
resumelob = rs3.getClob(3);//将结果集中第三个位置的clob取出
String detailinfo = resumelob.getSubString((long)1,(int)resumelob.length());
//将clob类型转化为字符串类型,参数固定,基本上就这么写

还用到的sql函数

POSSTR(RESUME,'Personal')//查看Personal这个单词在RESUME中的位置
SUBSTR(RESUME,1,length)//取resume中1-length长度的字段


二. 真题演练(2016-2017年考题)

1. 建立数据库连接的语句,对象自定义

static{
     try{
        class.forName("COM.ibm.db2.jdbc.app.DB2Driver");
        }catch(Exception e){
            System.println("\n Error loading DB2 Driver...\n");
            System.println(e);
            System.exit(1);
          }
}
String url = "jdbc:db2:sample";
Connection con = DriverManager.getConnection(url,userid;passwd);
Statement st = con.creatStatement();

2. 定义一个结果集对象,该对象将执行的查询语句是“查询表staff,获取员工编号为10的员工名字(name)工作(job)和工资(salary)”,写出具体执行代码

String SQL="SELECT NAME,JOB,SALARY FROM STAFF WHERE ID = 10";
Resultset rs = st.executeQuery(SQL);

3. 写出结果集中下一行的方法,假设对象为rs,写出具体执行代码。

boolean more = rs.next();
while(more){
     String outline;
     name = rs.getString(1);
     job = rs.getString(2);
     salary = rs.getString(3);
     outline = ( name + blanks.substring(0,10-name.length()) ) +
               ( job + blanks.substring(0,10-job.length()) ) +
               ( salary + blanks.substring(0,12-salary.length()) )
     more=rs.next();
     }

4. Sql=“SELECT name FROM Temp WHERE id=? ”执行这种sql语句时,该创建什么对象?若对象名为pstmt,写出具体的程序片段。

String sql = "SELECT name FROM Temp WHERE id=?" ;
pstmt = conn.prepareStatement(sql) ;
pstmt.setString(1,id) ; // 这里用于设置了第一个?的值

实质就是等用户去手动“setString”以控制查找条件。设置完成后,sql才构造好。

总结:

  • 问号就是我们所谓的一个变量,没有确定值,我们可以通过setString()方法对其赋值,这对于我们sql的灵活性有很好的意义。

5. ①已知sql更新语句“UPDATE temp SET salary=salary*5”,写出具体执行代码;②count为executeUpdate()的执行结果,count=3,但查询原表并未改变,这是为什么?

sqlstmt = "UPDATE TEMP SET SALARY = SALARY * 5 WHERE DEPT = ?";
PreparedStatement pstmt = con.prepareStatement( sqlstmt );


原因是因为程序被设置为了不自动提交SQL语句con.setAutoCommit(fALSE)
所以刚刚进行修改后立即返回的结果,是程序为了提高性能从设置中的缓存里读取的,而不是从数据库读取的。

总过程:

Connection sample = DriverManager.getConnection("jdbc:db2:sample",userid,passwd);
String deptno  = "";
String s = " ";
int mydeptno = 0;
int updateCount=0;

String sqlstmt = "UPDATE TEMP SET SALARY = SALARY * 5 WHERE DEPT = ?";

BufferedReader in = new BufferedReader( new InputStreamReader (System.in));
System.out.println("input deparement no._");
s = in.readLine();

While(s!=null){
   deptno = s.substring(0,2);//从输入流中获取指定的dep的值,结果返回字符串
   mydeptno = Integer.parseInt(deptno);//转换为int
   PreparedStatement pstmt = sample.prepareStatement( sqlstmt );//准备执行sql语句
   pstmt.setInt(1, mydeptno);//给sql中第一个?处赋值
   updateCount += pstmt.executeUpdate();//每次更新都要计数
   System.out.println("input deparement no");
   s = in.readline();
}
System.out.println("\n Number of rows updated: " + updateCount);

6. 假设Connection,Statement,ResultSet类的对象分别是con,stmt,rs,在程序结束之前,应该按什么顺序关闭这三个对象,请以此写出具体语句。

rs.close()
stmt.close()
con.close()

从最开始的两道题里面也能看出,是先建立连接,然后获取当前状态下的数据,再进行相应操作获得结果集;那么关闭过程应该溯源,所以关闭结果集——>关闭状态对象——>关闭连接。

7. 将一个图片“e:\photo\a.jpg”插入到表student的photo列(BOLB属性)中,写出主要的操作语句,对象自定义。

//将图片插入到BLOB类型的字段中
//建立一个表:
create table a(blob a);
//建立一个目录:
create directory tmp as 'e:\';
//建立一个PL/SQL块:
declare
     bfile b_file;
     blob b_lob;
begin
     insert into a(a) values(empty_blob()) 
     return a into b_lob;
     //为了使PL/SQL编译成功,必须先为该列插入一个empty_blob() 值
     //return a into b_lob是将该列与一个blog类型的变量绑定在一起,以后只要为b_lob赋值,即等于将该值插入了表中。
     
     b_file:=bfilename('tmp','filename.jpg');
     //tmp是建立的文件所在的目录,filename.jpg是文件名;将文件转换为bfile类型
     
     dbms_lob.open(b_file,dbms_lob.file_readonly);
     //将b_file 以只读的方式打开
     
     dbms_lob.loadfromfile(b_lob,b_file,dbms_lob.getlength(b_file));
     //将b_file中的内容转换到b_lob中
     
     dbms_lob.close(b_file);
     commit;
end;

你可能感兴趣的:(课程笔记,数据库,java,database)