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
);
두 테이블 모두에서 열을 사용해야 하는 경우 세 가지 옵션이 있습니다.
- 조인을 반복합니다.
SET그리고WHERE절이것은 구축하기 쉽지만 최적은 아닙니다. - DML 테이블 식입니다.인덱스가 정확한 경우 이 작업이 수행됩니다.
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
'programing' 카테고리의 다른 글
| .NET 응용 프로그램에서는 SQL 쿼리가 느리지만 SQL Server Management Studio에서는 즉시 실행됨 (0) | 2023.07.14 |
|---|---|
| Oracle / SQL - 단일 열에 있는 값의 발생 횟수 (0) | 2023.07.14 |
| 읽기 전용 맵 유형 사용 (0) | 2023.07.14 |
| 구글 앱 엔진 vs 파이어베이스 (0) | 2023.07.14 |
| 전체 MySQL 데이터베이스 복제?아이디어? 사람들은 무엇을 합니까? (0) | 2023.07.14 |