programing

ORA-01779: 키가 보존되지 않은 테이블에 매핑되는 열을 수정할 수 없습니다.

telecom 2023. 7. 14. 23:40
반응형

ORA-01779: 키가 보존되지 않은 테이블에 매핑되는 열을 수정할 수 없습니다.

다음 절차가 있습니다.

create or replace procedure changePermissionsToRead(
datasource  in varchar2
) 
IS

begin

update 
(
select * from 
WEB_USERROLE ur ,
WEB_USERDATASOURCE ds 
where 
    ur.username = ds.username 
    and 
    ds.datasource = datasource
    and 
    ur.READ_ONLY <> 'Y'  
)
r set r.role = replace(r.role, 'FULL', 'READ');
end;

다음과 같은 오류가 발생합니다.

 ORA-01779

하지만 업데이트를 꺼내면 다음과 같이 쓸 수 있습니다.

  update 
(
select * from 
WEB_USERROLE ur ,
WEB_USERDATASOURCE ds 
where 
    ur.username = ds.username 
    and 
    ds.datasource = 'PIPPO'
    and 
    ur.READ_ONLY <> 'Y'  
)
r set r.role = replace(r.role, 'FULL', 'READ');

그러면 잘 작동합니다.무슨 일이 일어나고 있는지 말씀해 주시겠습니까?

DML 테이블 식 절은 둘 이상의 테이블에서 열이 필요한 경우에만 유용합니다.당신의 경우, 당신은 정기적인 업데이트를 사용할 수 있습니다.EXISTS:

update web_userrole
set role = replace(role, 'FULL', 'READ')
where read_only <> 'Y'
    and exists
    (
        select 1/0
        from web_userdatasource
        where datasource = p_datasource
            and username = web_userrole.username
    );

두 테이블 모두에서 열을 사용해야 하는 경우 세 가지 옵션이 있습니다.

  1. 조인을 반복합니다.SET그리고WHERE이것은 구축하기 쉽지만 최적은 아닙니다.
  2. DML 테이블 식입니다.인덱스가 정확한 경우 이 작업이 수행됩니다.
  3. MERGE아래는 예입니다.

    merge into web_userrole
    using
    (
        select distinct username
        from web_userdatasource
        where datasource = p_datasource
    ) web_userdatasource on
    (
        web_userrole.username = web_userdatasource.username
        and web_userrole.read_only <> 'Y'
    )
    when matched then update
    set role = replace(role, 'FULL', 'READ');
    

이렇게 하면 질문에 직접 대답하지 않고 몇 가지 해결 방법을 제공할 수 있습니다.저는 당신이 받고 있는 오류를 재현할 수 없습니다.더 자세히 조사하려면 완전한 테스트 케이스가 필요합니다.

업데이트 가능한 보기에 대한 일반적인 조언

업데이트 가능한 보기의 주요 문제 중 하나는 포함할 수 있는 쿼리에 대한 제한이 많다는 것입니다.쿼리 또는 보기에 DISTINCT, GROUP BY, 특정 식 등과 같은 많은 기능이 포함되어 있으면 안 됩니다.이러한 기능이 있는 쿼리는 "ORA-01732: 데이터 조작 작업이 이 보기에서 합법적이지 않음" 예외를 발생시킬 수 있습니다.

업데이트 가능한 보기 쿼리는 수정된 테이블의 각 행을 한 번만 명확하게 반환해야 합니다.쿼리는 "키 보존"되어야 합니다. 즉, Oracle은 기본 키 또는 고유 제약 조건을 사용하여 각 행을 한 번만 수정할 수 있어야 합니다.

키 보존이 중요한 이유를 설명하기 위해 아래 코드는 모호한 업데이트 문을 만듭니다.두 개의 테이블을 만들고, 첫 번째 테이블에는 하나의 행이 있고, 두 번째 테이블에는 두 개의 행이 있습니다.테이블이 열에 의해 결합됩니다.A열을 업데이트합니다.B제1표에이 경우 Oracle이 업데이트를 방지하는 것이 좋습니다. 그렇지 않으면 값이 결정적이지 않습니다.값이 "1"로 설정될 수도 있고, "2"로 설정될 수도 있습니다.

--Create table to update, with one row.
create table test1 as
select 1 a, 1 b from dual;

--Create table to join two, with two rows that match the other table's one row.
create table test2 as
select 1 a, 1 b from dual union all
select 1 a, 2 b from dual;

--Simple view that joins the two tables.
create or replace view test_view as
select test1.a, test1.b b_1, test2.b b_2
from test1
join test2 on test1.a = test2.a;

--Note how there's one value of B_1, but two values for B_2.
select *
from test_view;

A  B_1  B_2
-  ---  ---
1    1    1
1    1    2

--If we try to update the view it fails with this error:
--ORA-01779: cannot modify a column which maps to a non key-preserved table
update test_view
set b_1 = b_2;

--Using a subquery also fails with the same error.
update
(
    select test1.a, test1.b b_1, test2.b b_2
    from test1
    join test2 on test1.a = test2.a
)
set b_1 = b_2;

MERGE문에 동일한 제한이 없습니다.MERGE문은 컴파일 시간 대신 실행 시간에 모호성을 탐지하려고 시도하는 것으로 보입니다.

도 불하게도행.MERGE애매함을 감지하는 것이 항상 좋은 일은 아닙니다.오라클 12.2에서는 다음 문장이 작동했다가 실패하는 경우가 있습니다.쿼리를 작게 변경하면 작동하거나 실패할 수 있지만 특정 패턴을 찾을 수 없습니다.

--The equivalent MERGE may work and changes "2" rows, even though there's only one.
--But if you re-run, or uncomment out the "order by 2 desc" it might raise:
--  ORA-30926: unable to get a stable set of rows in the source tables
merge into test1
using
(
    select test1.a, test1.b b_1, test2.b b_2
    from test1
    join test2 on test1.a = test2.a
    --order by 2 desc
) new_rows
    on (test1.a = new_rows.a)
when matched then update set test1.b = new_rows.b_2;

UPDATE이론적으로 중복이 가능한 경우 컴파일 시 실패합니다.작동해야 하는 일부 문이 실행되지 않습니다.

MERGE데이터베이스가 런타임에 불안정한 행을 탐지하면 실패합니다.작동하지 않아야 하는 일부 문은 계속 실행됩니다.

언급URL : https://stackoverflow.com/questions/17092560/ora-01779-cannot-modify-a-column-which-maps-to-a-non-key-preserved-table

반응형