【问题标题】:How to access columns on a cursor which is a join on all elements of two tables in Oracle PL/SQL如何访问游标上的列,该游标是 Oracle PL/SQL 中两个表的所有元素的连接
【发布时间】:2013-07-21 19:04:10
【问题描述】:

我试图在两个表的完全连接上运行游标,但在访问游标中的列时遇到问题。

CREATE  TABLE APPLE(
    MY_ID           VARCHAR(2) NOT NULL,
    A_TIMESTAMP     TIMESTAMP,
    A_NAME          VARCHAR(10)
);

CREATE  TABLE BANANA(
    MY_ID           VARCHAR(2) NOT NULL,
    B_TIMESTAMP     TIMESTAMP,
    B_NAME          VARCHAR(10)
);

我编写了一个完全连接来返回表 A 和 B 中的所有相关行,其中两个时间戳中的任何一个都在未来。 即,如果表 APPLE 中的一行将来有时间戳,则从 APPLE 中获取行,并在 MY_ID 上与 BANANA 中的行连接 类似地,如果表 BANANA 中的行在将来具有时间戳,则从 BANANA 中获取行,并在 MY_ID 上加入来自 APPLE 的行 这个完全加入对我有用。

select * from APPLE a full join BANANA b on  a.MY_ID = b.MY_ID where 
    (
      a.A_TIMESTAMP > current_timestamp
      or b.B_TIMESTAMP > current_timestamp 
    );

现在我想遍历每个加入的记录并进行一些处理。我能够访问仅存在于一个表中的列,但在尝试访问两个表中相同的列名时出现错误。例如。本例中的 ID。

create or replace 
PROCEDURE testProc(someDate IN DATE)
AS
CURSOR c1 IS
    select * from APPLE a full join BANANA b on  a.MY_ID = b.MY_ID where 
    (
      a.A_TIMESTAMP > current_timestamp
      or b.B_TIMESTAMP > current_timestamp 
    );

BEGIN
    FOR rec IN c1
    LOOP    
        DBMS_OUTPUT.PUT_LINE(rec.A_NAME);
        DBMS_OUTPUT.PUT_LINE(rec.A_TIMESTAMP);
        DBMS_OUTPUT.PUT_LINE(rec.MY_ID);
    END LOOP;
END testProc;

我在编译上面的过程时遇到这个错误:

错误(16,28):PLS-00302:必须声明组件“MY_ID”

我不确定如何访问 MY_ID 元素。我相信它会很漂亮 直截了当,但我是数据库编程的新手,一直在尝试但找不到正确的方法。 任何帮助表示赞赏。 谢谢

【问题讨论】:

    标签: sql oracle join plsql cursor


    【解决方案1】:

    在这种情况下,您可以做的另一件事是使用USING 子句而不是使用ON 连接表,如下所示:

    select *
      from APPLE a
      full join BANANA b
        USING (MY_ID)
    where a.A_TIMESTAMP > current_timestamp or
          b.B_TIMESTAMP > current_timestamp
    

    USING 如果两个表上的列具有相同的名称,则可以使用,并且使用相等 ('=') 运算符进行键值的比较。在结果集中,将有一个名为 MY_ID 的列以及两个表中的其他列(A_TIMESTAMP、B_TIMESTAMP 等)。

    分享和享受。

    【讨论】:

      【解决方案2】:

      我认为问题是MY_ID 在两个表中都定义了,所以* 得到了它们。尝试使用此查询定义光标:

      select coalesce(A.MY_ID, B.MY_ID) as MY_ID,
             A_TIMESTAMP, A_NAME, B_TIMESTAMP, B_NAME
      from APPLE a full join
           BANANA b
           on a.MY_ID = b.MY_ID
      where a.A_TIMESTAMP > current_timestamp or b.B_TIMESTAMP > current_timestamp;
      

      编辑:

      您有两个关于列冲突的问题。如果这只是一个内部连接,你可以这样做:

      select A.*, B_TIMESTAMP, B_NAME
      

      也就是说,您可以使用* 从一个表中选择列,其余的则单独选择。但是,这是一个full outer join,所以有一组列要使用coalesce()

      因此,最好的答案是您应该列出所有列。无论如何,这是一种很好的编码习惯,并且有助于防止在表中添加或删除列时代码不会出现意外错误。

      【讨论】:

      • 感谢您的快速回复。我试过这样做并且它有效,但我试图避免它,因为我的表中有大量列。所以基本上我必须明确使用 AS 来定义冲突的列而不是其他方式?附带说明一下,关于上面相同的查询和表的问题,但与冲突的列名问题无关:我必须查询这些完全连接的记录并将它们写入另一个表,但在此之前,我必须进行映射/转换一些列,游标是实现它的正确方法吗?还是我应该看看其他选择?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-07
      相关资源
      最近更新 更多