可以 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>
,我收到以下错误消息:
- 错误:ORA-00904:"SA"."BILL_ACC":标识符无效。
ORA - 02063:来自 db_link.
的前一行
一个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 collect
和 forall
插入的集合。
如果您在 My Oracle Support 中搜索 ORA-02063 和 ORA-00904,您会看到很多错误,其中一些似乎适用于 11g,但应该已在我的 11.2.0.4 版本中修复;我无法通过快速浏览看到任何完全匹配的内容,但您可能正在点击其中之一,或者确实是尚未报告的内容。可能值得提出 SR 来调查您的具体情况。
我继承了一个代码,可以帮助我从外部系统获取数据。有点乱,但我必须按原样使用它。
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>
,我收到以下错误消息:
- 错误:ORA-00904:"SA"."BILL_ACC":标识符无效。 ORA - 02063:来自 db_link. 的前一行
一个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:
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 collect
和 forall
插入的集合。
如果您在 My Oracle Support 中搜索 ORA-02063 和 ORA-00904,您会看到很多错误,其中一些似乎适用于 11g,但应该已在我的 11.2.0.4 版本中修复;我无法通过快速浏览看到任何完全匹配的内容,但您可能正在点击其中之一,或者确实是尚未报告的内容。可能值得提出 SR 来调查您的具体情况。