所有的MIS系统都存在一个同样的需求就是对于特定的数据在一次批量操作过程中如果数据已经存在则对存在的数据按照现有情况进行更新如果不存在则需要加入数据库这时我们就可以考虑采用 Oracle 的MERGE 函数其具体用法如下
MERGE INTO [your tablename] [rename your table here]
USING
(
[write your query here]
)[rename your querysql and using just like a table]
ON
([conditional expression here] AND [])
WHEN
MATHED
THEN
[here you can execute some update sql or something else ]
WHEN
NOT MATHED
THEN
[execute something else here ! ]
下面我再进行详细的说明
上述代码格式中的加粗字体表示为 Oracle 关键字[]以及其中的文字均是说明在实际使用中不应有 [ words ] 出现要注意()[圆括号]也是程序的组成部分
为了能够使问题与实际问题更加贴切不妨假设我们现在要给计算机系某个班的学生批量录入学生成绩但是录入时如果学生的成绩已经存在时老师只想对成绩进行修改而如果成绩不存在则直接添加到库中我们就老师的这些需求来构造一个执行语句
DEFINE TABLE :
SCORE : using for save the students score informations
STUDENTS : the base information of students
DEFINE COLUMNS :
STUNO : the students ID in theUniversity
STUNAME : students name
COURSENAME : course name
COURSESCORE : the studyresults of the reference course
CLASSNAME : where the students study in
STUGRADE : the students grade
TERMNAME : the term which the reference course studied
NOW BEAGIN TO WRITE DOWN THE STATEMENT HERE BLOW THIS LINE !
MERGE INTO SCORE S
USING
(
SELECT A*B*? MYSCOREFROM SCORE ASTUDENT B
WHERE
ACLASSNO=? AND AGRADE=?
AND ATERMNAME=? AND ACOURSENAME=?
ASTUNO=BSTUNO(+)
)X
ON
(SSTUNO=XSTUNO)
WHEN
MATHED
THEN
UPDATE SET COURSESCORE=XMYSCORE
WHEN
NOT MATHED
THEN
INSERT
(
STUNOSTUNAMECOURSENAMECOURSESCORE
CLASSNAMESTUGRADETERMNAME
)
VALUES
(
XSTUNOXSTUNAMEXCOURSENAMEXMYSCORE
XCLASSNAMEXSTUGRADEXTERMNAME
);
注意到 MERGE 语句在最后的(分号)这仅仅带到 MERGE 为一条完整的 SQL 语句
这时如果你需要在你的 Java 程序中使用上述方法执行相应操作则仅需要将其放入一个 for 循环中即可由于是批量更新数据因此如果你不想对中间出现异常的数据进行提交导致数据的不完整则可以考虑使用 Java 的事务回滚机制具体示例代码如下
public yourMethod(statement){
try{
Connection conn=;
PreparedStatement ps=;
Resultset rs=;
connsetAutoCommit(false);
for(int i=;i<;i++){
//add your code here !
psaddBatch();
}
psexecuteBatch();
mit();
}catch(Exception e){
try{
connrollback();
}catch(Exception el){}
}
这时你会发现在代码中直接使用 Merge 时代码会变的非常复杂首先是 SQL 的拼接变得非常复杂接下来便是程序写完后的查错因此自然而然就会想到使用存储过程接下来我们来看看如何使用存储过程实现 Merge 调用过程
Oracle 存储过程定义格式如下
CREATE OR REPLACE PROCEDURE PRO_YOUR_PROCEDURE (
ELEMENT_ IN ELEMENT_TYPE COMMENTS
ELEMENT_S OUT ELEMENT_TYPE COMMENTS
)
AS
ARGUMENT_ ARGUMENT_TYPE(ARGUMENT_RANGE);
BEGIN
MERGE INTO YOUR_TABLE_NAEM [RENAEM_YOUR_TABLE_HERE]
AND YOUR CODE HERE !
END;
EXCEPTION
WHEN
OTHERS
THEN
RAISE_APPLICATION_ERROR([YOUR EXCEPITON MESSAGE HERE !]);
END;
COMMIT;IF YOUR WANT JUST DO SO !
END PRO_YOUR_PROCEDURE;
其中[RAISE_APPLICATION_ERROR([YOUR EXCEPITON MESSAGE HERE !]);]中的是 Oracle 提供的用于用户进行错误自定义的扩充代码其值可以随便定义但是也有范围 到的负整数
接下来就是如何来在 Java 程序中调用你的存储过程Oracle为了方便开发人员调用其存储过程开发了一个 [OracleCallableStatement ] 位于 oraclejdbc 包内
核心代码如下
OracleCallableStatement cal = null;
cal=(OracleCallableStatement)conngetMetaData()getConnection()prepareCall(call PRO_);
for(………………){
…………
calsetDouble(iARGUMENTS);
…………
calexecuteUpdate();
}