1

嗨,大师,我收到错误 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';

我试图优化第二个查询,因为第二个查询使用两个选择,我试图用一个查询替换它。有人可以帮我吗?

4

2 回答 2

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';
于 2013-05-29T18:37:48.550 回答
0

更新:使用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

更新

ROWNUMinON子句适用于更新的表,而不是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

于 2013-05-29T18:16:33.900 回答