以下主要是吉林大学软件工程数据库应用db2课程的复习资料,希望能够帮到找到这里的学弟学妹们。
不过需要注意的是:
然后整篇博客,我是按照“复习总结报告涉及的知识点——真题演练”的脉络进行的。本门课程的考核实验报告占一半,笔试占一半,而笔试其实也就是考察对相关语句的记忆和理解(主要还是背,背了才会用)。
考完了我靠记忆复原一下我们考的内容(我是2019级,今天是2021/12/31):
表给的是员工表(姓名、年龄、性别、工资、简历、照片)
emmmmmm一整个大无语的状态,抱佛脚的内容从来记不住,记住的从来也从来不是临时抱佛脚背下来的,别指望两天速成,还是平时花时间多用吧
Class.forName("COM.ibm.db2.jdbc.app.DB2Driver");
String url = "jdbc:db2:sample";//欲连接的数据库路径
String userid=”db2admin”;//用户名
String passwd=”db2admin”;//密码
Connection sample=DriverManager.getConnection(url,userid,passwd);
用到的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对象才行。
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
操作完成以后要把所有使用的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() ;
}
}
涉及到一点交互,就是先不指定sql的判定语句中的值,通过弹出一个窗口,获得用户输入再赋值查询。
String inputValue = JOptionPane.showInputDialog("Please input a value");//输入的东西保存在inputValue
JOptionPane.showMessageDialog(null, "\nNumber of rows updated: " + updateCount);//弹出一个输出框显示更新行数
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=?";
//用于读取结果集下一行的语句判断是否为空
rs.next();
while(rs.next()){
......
}
rs.wasNull();
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();//将结果集落实到数据库
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();
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()后一条
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();
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”。Blob类型的赋值,用setBinaryStream(int n, java.io.InputStream x, int length)
语句:
①n指示参数编号的 int
②InputStream 对象
③length指示字节数的 int。
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();
}
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();
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长度的字段
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();
String SQL="SELECT NAME,JOB,SALARY FROM STAFF WHERE ID = 10";
Resultset rs = st.executeQuery(SQL);
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();
}
String sql = "SELECT name FROM Temp WHERE id=?" ;
pstmt = conn.prepareStatement(sql) ;
pstmt.setString(1,id) ; // 这里用于设置了第一个?的值
实质就是等用户去手动“setString”以控制查找条件。设置完成后,sql才构造好。
总结:
①
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);
rs.close()
stmt.close()
con.close()
从最开始的两道题里面也能看出,是先建立连接,然后获取当前状态下的数据,再进行相应操作获得结果集;那么关闭过程应该溯源,所以关闭结果集——>关闭状态对象——>关闭连接。
//将图片插入到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;