可以使用dblink选择,不能使用dblink

时间:2016-04-27 15:44:01

标签: sql oracle oracle11g dblink

我继承了一个代码,可以帮助我从外部系统获取数据。它有点搞砸了,但我必须按原样使用它。

   SELECT NVL (
                (
                  SELECT TRIM (alias.SERV_CD)
                   FROM schema.CX_SER@db_link alias
                  WHERE     row_id =
                                          (
                                           SELECT mix.par_row_id
                                              FROM schema.CX_SER_MI_XM@db_link mix
                                             WHERE     mix.bill = SA.BILL_AC
                                          AND ROWNUM < 2
                                          )
                        AND ROWNUM < 2
                        ),
                (
                    SELECT TRIM (ba.SERV_CD)
                     FROM schema.s_some_table@db_link ba
                     WHERE ba.row_id = sa.BILL_AC AND ROWNUM < 2
                )
            ) REQUIRED_CODE,                   --NVL ends here
             COUNT (*) order_count,
             TRUNC (ia.CREATED_DATE) CREATED_DATE_date,
             TRUNC (ia.CREATED_DATE + 1) inserted_date
        FROM schema.s_some_table@db_link sa, schema.action_table@db_link ia, schema.s_order@db_link ord
       WHERE     ia.CREATED_DATE >= TRUNC (SYSDATE - 1)
             AND ia.CREATED_DATE < TRUNC (SYSDATE)
             AND ord.status = 'Done'
    GROUP BY SA.BILL_AC, TRUNC (ia.CREATED_DATE), TRUNC (IA.CREATED_DATE + 1); 

当我按原样运行select时,所述代码返回结果。 但是当我尝试在我的模式中插入这些记录时(使用简单的insert into(columns) <this select statement>),我收到以下错误消息:

  1. 错误:ORA-00904:&#34; SA&#34;。&#34; BILL_ACC&#34; :不合法的识别符。 ORA - 02063:db_link的前一行。
  2. 选择语句,如:

      with c as(
          SELECT NVL (
                        (
                          SELECT TRIM (alias.SERV_CD)
                           FROM schema.CX_SER@db_link alias
                          WHERE     row_id =
                                                  (
                                                   SELECT mix.par_row_id
                                                      FROM schema.CX_SER_MI_XM@db_link mix
                                                     WHERE     mix.bill = SA.BILL_AC
                                                  AND ROWNUM < 2
                                                  )
                                AND ROWNUM < 2
                                ),
                        (
                            SELECT TRIM (ba.SERV_CD)
                             FROM schema.s_some_table@db_link ba
                             WHERE ba.row_id = sa.BILL_AC AND ROWNUM < 2
                        )
                    ) REQUIRED_CODE,                   --NVL ends here
                     COUNT (*) order_count,
                     TRUNC (ia.CREATED_DATE) CREATED_DATE_date,
                     TRUNC (ia.CREATED_DATE + 1) inserted_date
                FROM schema.s_some_table@db_link sa, schema.action_table@db_link ia, schema.s_order@db_link ord
               WHERE     ia.CREATED_DATE >= TRUNC (SYSDATE - 1)
                     AND ia.CREATED_DATE < TRUNC (SYSDATE)
                     AND ord.status = 'Done'
            GROUP BY SA.BILL_AC, TRUNC (ia.CREATED_DATE), TRUNC (IA.CREATED_DATE + 1)) 
        select * from c where REQUIRED_CODE IS NOT NULL; 
    

    也会因同样的错误而失败。但是,当我使用上面with子句中的其他一些列查询结果时,我能够获得结果,例如where order_count>2 给出结果。所以问题出在REQUIRED_CODE部分,也许是在分组中。

    请指导行动方针。我需要插入流入我的架构的记录。

    注意:所有列都是varchar2或日期

1 个答案:

答案 0 :(得分:1)

如果我尝试复制问题最终接近你的问题,你可以通过添加a driving_site hint来避免CTE错误:

with c as (
   SELECT /*+ DRIVING_SITE (sa) */ NVL (
...

这可以防止以混淆优化器的方式编写和分发查询;我认为它在子查询中对SA的嵌套引用进行了绊倒,并且它结束了太多级别而无法识别。

该提示虽然对插入没有任何影响。

正如评论中所提到的,我已快速重写查询以避免子查询。它有点粗糙,我不确定我是否理解你当前所做的一切,部分原因是因为表名更改等等。但是你想看到它,它可能会给你一些工作从...

   INSERT INTO t42
  SELECT NVL (TRIM(MIN(t.SERV_CD) KEEP (DENSE_RANK FIRST ORDER BY NULL)),
           TRIM(MIN(ba.SERV_CD) KEEP (DENSE_RANK FIRST ORDER BY NULL))
         ) REQUIRED_CODE,  --NVL ends here
         COUNT (*) order_count,
         TRUNC (ia.CREATED_DATE) CREATED_DATE_date,
         TRUNC (ia.CREATED_DATE + 1) inserted_date
    FROM schema.s_some_table@db_link sa
    LEFT JOIN (
      SELECT mix.bill, alias.SERV_CD
        FROM schema.CX_SER_MI_XM@db_link mix
        JOIN schema.CX_SER@db_link alias
          ON alias.row_id = mix.par_row_id
      ) t
      ON t.bill = SA.BILL_ACC
    LEFT JOIN schema.s_some_table@db_link ba
      ON ba.row_id = sa.BILL_ACC
    CROSS JOIN schema.action_table@db_link ia
    CROSS JOIN schema.s_order@db_link ord
   WHERE     ia.CREATED_DATE >= TRUNC (SYSDATE - 1)
         AND ia.CREATED_DATE < TRUNC (SYSDATE)
         AND ord.status = 'Done'
GROUP BY SA.BILL_ACC, TRUNC (ia.CREATED_DATE), TRUNC (IA.CREATED_DATE + 1);

如果你不能使它工作,那么你可以在PL / SQL块中使用原始查询,作为游标并逐行插入,或者最好(特别是如果它会返回很多)数据)使用带有bulk collectforall插入的集合。

如果您在ORA-02063和ORA-00904上搜索My Oracle Support,您会看到一些错误,其中一些似乎适用于11g但应该由我的版本11.2.0.4修复;我无法通过快速浏览看到任何匹配的内容,但是您可能会遇到其中一个,或者实际上没有报告过。可能值得提出一个SR来调查您的具体情况。