出现错误 ORA-01732:此视图上的数据操作操作不合法
Posted
技术标签:
【中文标题】出现错误 ORA-01732:此视图上的数据操作操作不合法【英文标题】:Gettin error ORA-01732: data manipulation operation not legal on this view 【发布时间】:2013-05-29 15:30:38 【问题描述】:您好大师,我收到错误 ORA-01732:此视图上的数据操作操作不合法
执行以下查询时
UPDATE (SELECT CR.AMOUNT AS AMOUNT,
CASE
WHEN MRG.AMOUNT_USD=0
THEN CR.AMOUNT
ELSE MRG.AMOUNT_USD
END AS AMOUNT_BILAT,
CR.ISUPDATED
FROM CRS_TT_BILAT_EXCL_MERGE1 MRG,CRS_T_CURRENT_RATES1 CR
WHERE SUBSTR(CR.DNIS_CD,1,3)=MRG.DNIS_CD
AND CR.PRODUCT_CUST_ID = MRG.PRODUCT_CUST_ID
AND CR.ISUPDATED <> 'Y'
AND ROWNUM = 1)
SET AMOUNT = AMOUNT_BILAT;
CR.ISUPDATED = 'Y';
我已经从下面的查询中简化了上面的代码
UPDATE CRS_T_CURRENT_RATES1 CR
SET CR.AMOUNT =
(SELECT
CASE
WHEN MRG.AMOUNT_USD=0
THEN CR.AMOUNT
ELSE MRG.AMOUNT_USD
END
FROM CRS_TT_BILAT_EXCL_MERGE1 MRG
WHERE SUBSTR(CR.DNIS_CD,1,3)=MRG.DNIS_CD
AND CR.PRODUCT_CUST_ID = MRG.PRODUCT_CUST_ID
AND ROWNUM = 1),
CR.ISUPDATED = 'Y'
WHERE EXISTS
(SELECT 1 FROM CRS_TT_BILAT_EXCL_MERGE1 MRG WHERE MRG.DNIS_CD = SUBSTR(CR.DNIS_CD, 1,3) AND CR.PRODUCT_CUST_ID = MRG.PRODUCT_CUST_ID )
AND
CR.ISUPDATED <> 'Y';
我试图优化第二个查询,因为第二个查询使用两个选择,我试图用单个查询替换它。有人可以帮我解决这个问题吗?
【问题讨论】:
【参考方案1】:MERGE
语句为每个(AMOUNT_USD、DNIS_CD、PRODUCT_CUST_ID)选择第一行 - 查询中的ROWNUM=1
条件:
MERGE INTO CRS_T_CURRENT_RATES1 CR
USING (SELECT * FROM (
SELECT AMOUNT_USD,
DNIS_CD,
PRODUCT_CUST_ID
ROW_NUMBER() OVER (PARTITION BY AMOUNT_USD, DNIS_CD, PRODUCT_CUST_ID ORDER BY 1) AS ORD_NO
FROM CRS_TT_BILAT_EXCL_MERGE1
) WHERE ORD_NO = 1
) MGR
ON CR.PRODUCT_CUST_ID = MRG.PRODUCT_CUST_ID AND
SUBSTR(CR.DNIS_CD,1,3)=MRG.DNIS_CD
WHEN MATCHED THEN
UPDATE SET CR.AMOUNT = (CASE
WHEN MRG.AMOUNT_USD=0 THEN CR.AMOUNT
ELSE MRG.AMOUNT_USD
END),
ISUPDATED = 'Y'
WHERE ISUPDATED <> 'Y';
【讨论】:
感谢您的回答 Chorel 我对 ROW_NUMBER() 函数有疑问,该函数是在满足 ON 条件后应用还是先应用到内部查询。 条件ORD_NO=1
将应用于获取数据集,然后使用MERGE
的ON
部分中的条件匹配CRS_T_CURRENT_RATES1。看看MERGE
是如何工作的 - 文档链接由 jonearles 提供。
你能告诉我你为什么选择ORD_NO = 1
条件吗?除此之外,如果我们删除 ROW_NUMBER()
和 ORD_NO=1
,查询会有多大不同?
如果保证(AMOUNT_USD, DNIS_CD, PRODUCT_CUST_ID)
的集合是唯一的,那么您可以删除ORD_NO
和ROW_NUMBER()
,否则MERGE
将返回错误。分析函数中的PARTIRION BY
意味着该函数将独立返回PARTITION BY
字段的每个子集的值,在您的示例中,每个(AMOUNT_USD, DNIS_CD, PRODUCT_CUST_ID)
ORD_NO 将从1 开始,如果还有其他具有相同值的行,它们将得到2 ,3 等条件ORD_NO=1
确保仅使用上述字段的唯一子集来匹配目标表。
非常感谢 Chorel,你真的是一位大师【参考方案2】:
更新:使用 MERGE
和 ROWNUM
将不起作用。
MERGE
可以帮你避免重复SQL:
MERGE INTO CRS_T_CURRENT_RATES1 CR
USING
(
SELECT AMOUNT_USD, DNIS_CD, PRODUCT_CUST_ID
FROM CRS_TT_BILAT_EXCL_MERGE1
) MRG
ON
(
SUBSTR(CR.DNIS_CD,1,3) = MRG.DNIS_CD
AND CR.PRODUCT_CUST_ID = MRG.PRODUCT_CUST_ID
AND ROWNUM = 1
)
WHEN MATCHED THEN UPDATE SET
CR.ISUPDATED = 'Y',
CR.AMOUNT = CASE WHEN MRG.AMOUNT_USD=0 THEN CR.AMOUNT ELSE MRG.AMOUNT_USD END
更新
ON
子句中的ROWNUM
作用于更新后的表,而不是USING
子句中的数据。下面的示例从两个相同的行开始,并且只有一个被更新:
create table test1(a number, b number);
insert into test1 values(1, 1);
insert into test1 values(1, 1);
merge into test1
using
(
select 1 a from dual
) test2
on (test1.a = test2.a and rownum = 1)
when matched then update set b = 0;
select * from test1;
A B
- -
1 0
1 1
【讨论】:
不确定它是否能与 rownum 一起正常工作。可能它只会与USING
子句的第一行合并。
@Chorel 它似乎有效,请参阅我的更新。但是您使用分析函数的想法很好,它可以帮助使查询更具可读性。
抱歉 - 我是对的,它无法正常工作:(sqlfiddle.com/#!4/7f35f/1/1)。请注意,仅更新了一行。
@Chorel 你是对的。感谢您花时间纠正我。
不客气 :) - 我只是知道,因为几周前我遇到了类似的问题。以上是关于出现错误 ORA-01732:此视图上的数据操作操作不合法的主要内容,如果未能解决你的问题,请参考以下文章
PostgreSQL:十进制/数字数据类型上的数字字段溢出 - 为啥会出现此错误
VS 2013 给出 操作无法完成。 Razor 视图上的指针无效