我在oracle中执行一个插入条件,当基于作业和子作业的记录不存在时,它将以其他方式插入,如果它存在则应该更新剩余的值。
这是我的程序,
CREATE OR REPLACE PROCEDURE WELTESADMIN.SP_JOB_INS
(
JOB_V VARCHAR2,
SUBJOB_V VARCHAR2,
STARTDATE_V DATE,
ENDDATE_V DATE,
JOBWEIGHT_V NUMBER
)
AS BEGIN INSERT INTO PROJECT_SPAN (JOB, SUBJOB, STARTDATE, ENDDATE, WEIGHT) VALUES (JOB_V, SUBJOB_V, STARTDATE_V, ENDDATE_V, JOBWEIGHT_V);
EXCEPTION WHEN DUP_VAL_ON_INDEX THEN
UPDATE PROJECT_SPAN SET STARTDATE = STARTDATE_V, ENDDATE = ENDDATE_V, WEIGHT = JOBWEIGHT_V WHERE JOB = JOB_V AND SUBJOB = SUBJOB_V;
END;
/
这是来自PHP Call,
$insertJobSpanSql = "BEGIN SP_JOB_INS(:JOB, :SUBJOB, :SDATE, :EDATE, :WT); END;";
$insertJobSpanParse = oci_parse($conn, $insertJobSpanSql);
oci_bind_by_name($insertJobSpanParse, ":JOB", $jobValue);
oci_bind_by_name($insertJobSpanParse, ":SUBJOB", $subJobValue);
oci_bind_by_name($insertJobSpanParse, ":SDATE", $startDateValue);
oci_bind_by_name($insertJobSpanParse, ":EDATE", $endDateValue);
oci_bind_by_name($insertJobSpanParse, ":WT", $jobWeightValue);
$insertJobSpanRes = oci_execute($insertJobSpanParse);
if ($insertJobSpanRes){
oci_commit($conn);
} else {
oci_rollback($conn);
}
问题是它不断插入具有相同作业和子作业值的新行。它应该是对新值的更新。
答案 0 :(得分:2)
首先,我建议在这种情况下使用MERGE:
CREATE OR REPLACE PROCEDURE WELTESADMIN.SP_JOB_INS
(
JOB_V VARCHAR2,
SUBJOB_V VARCHAR2,
STARTDATE_V DATE,
ENDDATE_V DATE,
JOBWEIGHT_V NUMBER
) AS
BEGIN
merge into PROJECT_SPAN ps
using (select JOB_V, SUBJOB_V, STARTDATE_V, ENDDATE_V, JOBWEIGHT_V
from dual) new_val
on (ps.SUBJOB = new_val.SUBJOB_V and ps.JOB = new_val.JOB_V)
when matched then update
set STARTDATE = new_val.STARTDATE_V,
ENDDATE = new_val.ENDDATE_V,
WEIGHT = new_val.JOBWEIGHT_V
when not matched then insert (JOB, SUBJOB, STARTDATE, ENDDATE, WEIGHT)
values (new_val.JOB_V, new_val.SUBJOB_V, new_val.STARTDATE_V,
new_val.ENDDATE_V, new_val.JOBWEIGHT_V );
END;
/
如果仍未更新值,请使用包DBMS_OUTPUT
或登录表格以确保新旧JOB
和SUBJOB
真的相同。
答案 1 :(得分:1)
当DDL语句违反主键或唯一键约束时,Oracle会引发DUP_VAL_ON_INDEX。因此,要使代码工作,您需要在(job, subjob)
上定义主键,或者在该对上构建唯一索引。
Oracle以MERGE语句的形式提供了一种更简单的实现upsert的方法:
CREATE OR REPLACE PROCEDURE WELTESADMIN.SP_JOB_INS
(
JOB_V VARCHAR2,
SUBJOB_V VARCHAR2,
STARTDATE_V DATE,
ENDDATE_V DATE,
JOBWEIGHT_V NUMBER
)
AS BEGIN
merge into project_span ps
using ( select job_v, subjob_v, startdate_v, enddate_v, jobweight_v from dual ) q
on (ps.job = q.job_v
and ps.subjob = q.subjob_v)
when not matched then
insert (job, subjob, startdate, enddate, weight)
values (q.job_v, q.subjob_v, q.startdate_v, q.enddate_v, q.jobweight_v);
when matched then
update
set startdate = q.startdate_v
, enddate = q.enddate_v
, weight = q.jobweight_v
;
END;
MERGE声明在文档中。 Find out more