可以 select 使用 dblink,不能使用 dblink 插入

Can select using dblink, cannot insert using 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 时,上述代码 returns 结果。 但是当我尝试将这些记录插入到我的架构中时(使用简单的 insert into(columns) <this select statement>,我收到以下错误消息:

  1. 错误:ORA-00904:"SA"."BILL_ACC":标识符无效。 ORA - 02063:来自 db_link.
  2. 的前一行

一个select语句,如:

  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 部分,也许在 group by.

请指导操作过程。我需要将流向我的模式的记录插入。

注意 :所有列都是 varchar2 或 date

如果我尝试重现的问题与你的问题很接近,你可以通过添加 a driving_site hint:

来避免 CTE 的错误
with c as (
   SELECT /*+ DRIVING_SITE (sa) */ NVL (
...

这可以防止以混淆优化器的方式编写和分发查询;我认为它被子查询中对 SA 的嵌套引用绊倒了,它最终会下降太多级别而无法识别。

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

如评论中所述,我快速重写了查询以避免子查询。这有点粗糙,我不确定我是否理解你目前所做的一切,部分原因是 table 名称更改等。但你想看它,它可能会给你一些工作的机会...... .

   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 块中使用你的原始查询,作为游标并进行逐行插入,或者最好(特别是如果它将 return 大量数据)使用带有 bulk collectforall 插入的集合。

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