如果存在则更新Oracle或在单个表上使用合并双插入

oxf4rvwz  于 2023-06-22  发布在  Oracle
关注(0)|答案(1)|浏览(106)

下面是 table 学生:
|姓名|姓氏|年龄|通过|
| - -----|- -----|- -----|- -----|
| 约翰|威克|二十个|不适用|
| 爱丽丝|仙境|二十一|Y轴|
我想更新,如果学生存在的基础上的年龄,姓名,姓氏表或插入作为一个新的行。
下面是sql query

merge into student t
using (
    select
        ? AS NAME,
        ? AS SURNAME,
        ? AS AGE,
        ? AS PASSED
    from
        dual
) s on (
    t.NAME=s.NAME
    and t.SURNAME=s.SURNAME
    and t.AGE=s.AGE
    and t.PASSED=s.PASSED
)
when matched then 
    update set t.PASSED = s.PASSED 
when not matched then 
    insert (NAME, SURNAME, AGE, PASSED) values (s.NAME, s.SURNAME, s.AGE, s.PASSED);

下面是jdbcTemplate batchUpdate方法impl:

jdbcTemplate.batchUpdate(query, new BatchPreparedStatementSetter(){

   @Override
   public void setValues(PreparedStatment ps, int i){
     Student s = studentList.get(i);

       ps.setString(1, s.getName());
       ps.setString(2, s.getSurname());
       ps.setInt(3, s.getAge());
       ps.setString(4, s.getPassed());

     }

    @Override
       public int getBatchSize(){
       return studentList.size()
    }

});

ORA-38104:无法更新ON子句中引用的列
先谢谢你。

xpcnnkqh

xpcnnkqh1#

不要在ON子句中包含要更新的列。

merge into student t
using (
    select
        ? AS NAME,
        ? AS SURNAME,
        ? AS AGE,
        ? AS PASSED
    from
        dual
) s on (
    t.NAME=s.NAME
    and t.SURNAME=s.SURNAME
    and t.AGE=s.AGE
    -- and t.PASSED=s.PASSED                      -- Remove this filter.
)
when matched then 
    update set t.PASSED = s.PASSED 
when not matched then 
    insert (NAME, SURNAME, AGE, PASSED)
    values (s.NAME, s.SURNAME, s.AGE, s.PASSED);

此外,您还应考虑:

  • 为表使用主键(例如IDENTITY列),然后您可以基于主键而不是复合键进行更新(因为可能有两个不同的学生具有相同的姓名和年龄,并且您需要能够区分他们);
  • 存储出生日期,而不是年龄(因为年龄随着每个人的生日而变化,而出生日期是恒定的,可以用来计算年龄)。

相关问题