Oracle 程序:从表 A 中读取,如果没有找到,则转到表 B
Posted
技术标签:
【中文标题】Oracle 程序:从表 A 中读取,如果没有找到,则转到表 B【英文标题】:Oracle Procedure: Read from Table A and if not found go to Table B 【发布时间】:2015-03-24 08:59:48 【问题描述】:我想从 Table-A 或 Table-B 中读取数据。我的数据库是 oracle,过程必须使用最少数量的查询。要求是从一个表中读取,如果数据不可用,则转到另一个表。我写了以下程序,
CREATE OR REPLACE PROCEDURE READ(myId IN VARCHAR2, aout OUT SYS_REFCURSOR, bout OUT SYS_REFCURSOR )
IS
temp_acout_type A_TABLE%ROWTYPE;
BEGIN
OPEN aout FOR SELECT * FROM A_TABLE WHERE ID = myId;
FETCH aout into temp_acout_type ;
if aout%NOTFOUND then
OPEN bout FOR SELECT * FROM B_TABLE WHERE ID = myId;
end if;
END;
我从 java 端调用这个函数。我的问题是一旦我在程序中获取游标,游标就会丢失数据。我从 Java 客户端观察到这一点,因为 ResultSet
in java 端是空的(过程中的查询将只有 1 条记录,因为它是从主键搜索的),尽管它必须包含数据。
我需要一种方法来实现上述逻辑,但不使用更多查询(例如:Table-A 中提供了第一个检查数据)。有没有办法做到这一点?
【问题讨论】:
【参考方案1】:您总是可以在 PL/SQL 存储过程中打开两个游标,然后在 Java 中,从第一个中获取数据,如果您没有从第一个中获取数据,则仅从第二个中获取数据。这将防止发生不必要的读取(打开游标不会进行任何读取;它会为您准备好获取数据的执行路径)。
或者,您可以在两个表之间进行联合并只选择第一行(其中 first 表示第一个查询中有数据)。
【讨论】:
【参考方案2】:检查表中的行数。您可以在 12c 中使用 row-limiting 子句,例如 ROWNUM
或 FETCH
。
既然您说 ID 是主键,因此它只会获取 1 行,那么只需这样做:
SELECT COUNT(*) INTO var_cnt FROM A_TABLE WHERE ID = myId;
IF var_cnt > 0
THEN
OPEN aout FOR SELECT * FROM A_TABLE WHERE ID = myId;
ELSE
OPEN bout FOR SELECT * FROM B_TABLE WHERE ID = myId;
END IF;
但是,您不能确定要获取的行是否一定会出现在游标结果集中,因为同时其他一些会话可能 DELETE OPEN FOR 之前的行strong> 正在执行语句。
为了理智,我建议在 explicit cursor 查询中使用 Analytic COUNT() OVER()。
【讨论】:
是否有可能只使用两个主要的选择查询以某种方式省略select count(*)
?
是的,使用count() over()
。然后您将计算同一查询中的行数。以上是关于Oracle 程序:从表 A 中读取,如果没有找到,则转到表 B的主要内容,如果未能解决你的问题,请参考以下文章
您能帮我在 Oracle 中编写一个程序来将数据从表中转存到 CSV 文件吗?