Oracle 的一次 MyBatis 查询中的两个删除?

Posted

技术标签:

【中文标题】Oracle 的一次 MyBatis 查询中的两个删除?【英文标题】:Two delete in one MyBatis query for Oracle? 【发布时间】:2020-11-02 00:05:40 【问题描述】:

我想从两个表中删除两行。从每个一个行。在 XML 映射器中。MyBatis executing multiple sql statements in one go, is that possible? 触及了这个问题,但答案不是关于 XML 映射器或 - 看下面 - 不适用于 Oracle。

按照上面提到的,我需要写:

<delete id="removeReportRecord" >
    DELETE FROM S01_SESTAVA WHERE (id_s01_sestava = #idReport);
    DELETE FROM S02_DATA WHERE (id_s01_sestava = #idReport);
</delete >
...
int removeReportRecord(Long idReport);

但这不适用于 Oracle。我试过没有“;”在第三行,或者在两个删除操作上(MyBatis with Oracle 不喜欢结尾的“;”)或在界面中为参数使用注释 - 我总是有相同的消息:

org.apache.ibatis.exceptions.PersistenceException: 
### Error updating database.  Cause: java.sql.SQLSyntaxErrorException: ORA-00933: SQL command not properly ended

### The error may involve defaultParameterMap
### The error occurred while setting parameters
### Cause: java.sql.SQLSyntaxErrorException: ORA-00933: SQL command not properly ended

如果我改为使用两个后续查询:

<delete id="removeReportRecord" >
    DELETE FROM S01_SESTAVA WHERE (id_s01_sestava = #idReport)
</delete >
<delete id="removeReportData" >
    DELETE FROM S02_DATA WHERE (id_s01_sestava = #idReport)
</delete >
...
int removeReportRecord(Long idReport);
int removeReportData(Long idReport);

没问题,一切正常。我已经用@Transactional 介绍了这两个操作,它可以工作并且看起来很安全,但是如果我真的需要在一个查询中使用多个 SQL 操作符,我该如何使用这些 MyBatis XML + Oracle 呢?我是不是做错了什么?

【问题讨论】:

你看到了吗:***.com/a/8338725/910736 根据@JamesB 链接的答案,Oracle 不支持在一个命令中使用多个语句,但您可以发送包含多个 SQL 语句的单个 PL/SQL 匿名块。 CALL BEGIN DELETE FROM table1 WHERE ...; DELETE FROM table2 WHERE ...; END 我会避开这个功能。只需单独运行每个 SQL 并在晚上睡个好觉。我个人不喜欢在凌晨 2 点应用程序崩溃时随叫随到,因为 DevOps 更改了数据源 URL——迁移、升级、部署、新版本等——并删除了标志。 @JamesB 我在我的问题中提到了那个问题,这是第一行,你没注意到吗?当然,我阅读了所有我能找到的东西。提出其他技术解决方案对我来说没有任何价值——我不想在没有必要的情况下扩大使用方法的范围。 @MT0 在那个答案中并不是说 Oracle 在 XML 映射器中不支持它。只提出了另一种工作方式。谢谢你的信息,这可能是答案。 【参考方案1】:

是否支持执行多条语句取决于驱动程序。 Oracle的JDBC驱动支持方式如下(用ojdbc8 19.8.0.0测试)。

<delete id="removeReportRecord">
  BEGIN
    DELETE FROM S01_SESTAVA WHERE (id_s01_sestava = #idReport);
    DELETE FROM S02_DATA WHERE (id_s01_sestava = #idReport);
  END;
</delete >

请注意,使用这种方法,该方法返回 -1 而不是删除的行数,因为驱动程序从 PreparedStatement#getUpdateCount() 返回 -1

【讨论】:

谢谢。我在您的解决方案中看到了更多优点。如果我不使用这些开始/结束括号,我必须删除“;”从 Oracle SQL 查询让 MyBatis 接受它们。正如我所见,使用这些括号,支持标准的 Oracle 语法。因此,最好将它们用于单个查询 - 因此我们可以使用 SQL 客户端中的查询来测试 unchanged 很高兴知道它有帮助! :D

以上是关于Oracle 的一次 MyBatis 查询中的两个删除?的主要内容,如果未能解决你的问题,请参考以下文章

在Mybatis中使用连表查询的一次实际应用

java中使用mybatis和oracle 查询数据时比如我第一次点击页面查询 返回1,2

java mybatis对oracle long解决办法?

Oracle查询出最最近一次的一条记录

mybatis中的模糊查询,Oracle和MySQL中的concat

终结篇:MyBatis原理深入解析