【发布时间】:2017-05-05 23:06:32
【问题描述】:
我很难弄清楚这一点。我知道必须有办法做到这一点,而且我可能非常接近(或者可能不是)。我想从表中删除一组记录并返回在一个语句中删除的记录。该表是一个队列,我需要从中弹出一些记录。
这可以通过 2 个语句完成工作:
select id, add_date from my_queue where rownum <= 10;
-- save for processing
delete from my_queue where rownum <= 10;
如何将这些组合成 1 条语句,然后在 Java 中读取结果?
我查看了this SO question,并尝试在问题中实现这两种方法,但是,在我的情况下,我有 2 列要输出,我需要使用 bulk collect into 子句,因此输出将成为一张桌子。这样做,我无法弄清楚我需要做什么才能正确定义和注册输出以执行匿名 PL/SQL 语句。
这是我最接近的尝试:
StringBuilder sql = new StringBuilder();
sql.append("BEGIN ");
sql.append(" delete from my_queue where rownum <= 10 ");
sql.append(" returning _id into ?; ");
sql.append("END; ");
CallableStatement cstmt = con.prepareCall(sql.toString());
cstmt.registerOutParameter(1, OracleTypes.CURSOR);
//cstmt.registerOutParameter(1, OracleTypes.NUMBER);
//cstmt.registerOutParameter(1, OracleTypes.ARRAY);
cstmt.execute(); // throws error, see comments below
以下是根据注册的输出类型执行时的各种错误:
使用光标:
ORA-00932: inconsistent datatypes: expected CURSER got NUMBER使用号码:
ORA-01422: exact fetch returns more than requested number of rows使用数组:
ORA-03115: unsupported network datatype or representation
【问题讨论】:
-
为什么不在开始/结束块中的删除语句之前运行选择语句?
-
@Sebas - 这会阻止同一张表上的其他操作吗?即如果选择运行,其他一些操作插入,然后删除运行......其他操作会在插入之前等待 PL/SQL 块完成吗?
-
Select 语句不锁定。有关 DML 操作是否包含锁定的更多信息,请参见此处:docs.oracle.com/cloud/latest/db112/SQLRF/…
-
好的,所以真正的问题不是“我怎样才能在一个语句中完成所有操作”。相反,它是“我如何删除十行并在 SELECT 查询中显示它们 - 并确保它是相同的行,即使表上还有其他事务。”您不能在一个声明中完成所有操作; SQL 中没有组合的 SELECT/DELETE 语句。确切的要求是什么也不清楚。如果您确定了 10 行,但在您要删除时,有 3 行已经被另一个用户删除了怎么办?删除其他七个可以吗?
-
一旦您打开事务,任何东西都无法改变您对表中内容的看法。你安全了。这是它的全部意义。这也意味着如果您的删除语句(或从另一个请求完成的)将阻止您的事务,直到它完成。这不一定是问题,只需确保查询已优化即可。
标签: java sql oracle plsql oracle11g