2011-04-13 2 views
2

확인을 클릭하면 문제가 무엇인지 명확히 알 수 있습니다. 데이터베이스가 5 개 있습니다. A와 B, V_1, V_2 및 V_3이라고합시다. A와 B는 할 일 목록을 나타냅니다. 이러한 작업은 V_i 테이블에 설명되어 있습니다. 이제 A는 특정 유형의 항목으로 완료해야하는 항목의 템플리트의 종류를 나타냅니다. 한편, B는 A가 기술 한 추상 항목 인 경우 구체적인 인스턴스로 수행해야 할 작업 (또는 수행 된 작업)을 설명합니다. 따라서 OOP 용어에서 A는 클래스를 나타내고 B는 A의 인스턴스를 나타낼 수 있습니다. 테이블 B에 무언가가 삽입 될 때마다 테이블 A의 관련 데이터가 복사되므로 A에 영향을 미치지 않고 해당 특정 항목에 대해 수정할 수 있습니다.여러 테이블 중 하나와 정확히 1 : 1의 관계

그래, 실제 문제는 여기에 있습니다. 어떻게 이것을 모델링합니까? 정확히? 내 주요 관심사는 V_i의 각 레코드가 A와 B 모두에 연결되어서는 안된다는 것입니다. A 또는 B 중 하나와 1 대 1 관계 여야합니다. 또한 V_i와 V_j는 A 또는 B의 동일한 레코드에 연결되어서는 안됩니다. B. 나는 이것을 올바르게하는 방법을 모른다. 현재 구조는 다음과 같습니다.

A와 B에는 ID라는 PK가 있습니다. 각 V_i에는 ID라고하는 PK와 A 또는 B를 참조하는 두 개의 FK도 있습니다. A_ID 및 B_ID라고 부릅니다. 이제 현재 구현에서는 A_ID 또는 B_ID가 NULL이지만 둘 다가 아닌지 확인합니다. 그러나 이것을 수행하는 더 좋은 방법이 있는지 궁금합니다. 또한 여러 V_i가 A 또는 B의 동일한 항목을 참조 할 수있는 문제가 있습니다.

그래서 문제가 해결되기를 바랍니다. 제약 조건을 적용하기 위해 외부 코드에 의존하지 않고 관계형 데이터베이스를 적절하게 모델링 할 수있는 방법이 있습니까? 사전에 귀하의 의견을 보내 주셔서 감사합니다.

안부 데이비드

+0

나는 당신이 룩업 테이블을 필요로 할 것이라고 생각한다. 나는 이것에 대한 최선의 구현을 확신하지는 않지만, Quassnoi, OMG_Ponies, gbn, martin, Joe Stefanelli 또는 SQLMenace와 같은 현명한 누군가가 파이프를 넣을 것입니다! – JNK

답변

1

우선 : 데이터베이스를 설계 할 때, 당신은 기록하지 테이블 간의 관계를 표현한다. OO의 관점에서 문제를 표현하고 있습니다. 이 패러다임은 테이블을 디자인하는 데 사용할 수 없습니다 (SQL은 선언적 언어 임).

그렇지 않으면 조건을 테이블에 추가하여 조건자를 확인할 수 있습니다.

아마도 오라클은 다른 가능성을 제공합니다.

+0

추가 정보 www. asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1545206281987 –

+0

일반적으로 문제를 다르게 표현하면 다른 해결책이 생깁니다. 관계를 검토하십시오. V-i 테이블을 정확하게 설명해 주시겠습니까? –

2

관계형 이론에서 일대일 관계는 일반적으로 물리적 모델에서 단일 테이블로 변환됩니다. 이 단일 테이블에는 두 테이블의 행이 포함되며 행의 유형을 판별하기 위해 점검 제한 조건을 사용합니다. 이것은 신뢰할 수있는 1 : 1 관계를 얻는 가장 간단한 방법입니다. -

0

클래스 모델링하는 가장 일반적인 방법 RDB에있는 인스턴스 관계는 클래스 = 테이블 인스턴스 = 행 생각해

입니다 : 당신은 각각의 새로운 인스턴스에 대한 새로운 행을 삽입; 데이터를 삽입하지 않으면 기본값이 삽입되어 클래스 데이터를 제공합니다. 트리거는 클래스 수준의 동작을 제공합니다.

또는 A와 B에 동일한 기본 키를주고 B의 PK를 A의 PK로 FK로 설정합니다. B가 행에 포함되면 DBMS는 "상위"행이 존재하는지 확인합니다 A. 아마

+--------+ +--------+ 
|Table A | |Table B | 
+--------+ +--------+ 
|id (PK) |<--|id* (PK)| 
|col1 | |colB1 | 
| ... | | ... | 
+--------+ +--------+ 
0

서문을 그리기 필요가 : 다른 사람이 언급 한대로이 나쁜 디자인입니다.

가정 :

create table a (a_id number primary key); 

create table b (b_id number primary key); 

create table v1 
(v1_id number primary key, a_id number references a, b_id number references b); 

create table v2 
(v2_id number primary key, a_id number references a, b_id number references b); 

create table v3 
(v3_id number primary key, a_id number references a, b_id number references b); 

정확히에서 ID 중 하나 또는 B가 필요한 V_i 모든 테이블에 (하지만 둘 다) 아주 쉽다는 것을 의무화.

alter table V1 
    add constraint v1_check check 
    ( (a_id is null and b_id is not null) 
    or (a_id is not null and b_id is null) 
); 

당신은 A 또는 B에서 ID의 정확히 하나가 있고 그 값이 하나 존재하고 하나의 행하도록하는 제약 조건을 확장 할 경우 어려운 부분이

create unique index v1_check_unique on v1 (coalesce (a_id, b_id)); 

을하고있다 A와 B의 ID가 V_i 테이블 중 하나에 존재하는지 확인하십시오. 이는 DML 시간에는 수행 할 수 없지만 커밋 시간에 적용 할 수 있습니다.

create materialized view log on v1 with rowid; 
create materialized view log on v2 with rowid; 
create materialized view log on v3 with rowid; 
CREATE MATERIALIZED VIEW CROSS_TABLE 
REFRESH FAST ON COMMIT 
AS 
    SELECT V1_ID AS V_ID, 'V1' AS TABLE_NAME, ROWID AS ROW_ID, 
     COALESCE (A_ID, B_ID) AS OTHER_ID FROM V1 
    UNION ALL 
    SELECT V2_ID AS V_ID, 'V2' AS TABLE_NAME, ROWID AS ROW_ID, 
     COALESCE (A_ID, B_ID) AS OTHER_ID FROM V2 
    UNION ALL 
    SELECT V3_ID AS V_ID, 'V3' AS TABLE_NAME, ROWID AS ROW_ID, 
     COALESCE (A_ID, B_ID) AS OTHER_ID FROM V3 
/

ALTER TABLE CROSS_TABLE ADD CONSTRAINT CROSS_TABLE_UNIQUE UNIQUE (OTHER_ID); 

이것은 효과가있는 것처럼 보입니다. 그러나 당신이 바라는만큼 좋지는 않습니다. 세션 A가 다른 세션의 변경 사항을 고려하지 않기 때문에 오라클은 시간에 테이블간에 고유성을 적용 할 수 없습니다. 유일성이 에 커밋 시간에만 적용될 수 있습니다.

다음 테스트 사례는 빈 테이블에 대해 실행될 때 실패하고 실패를 유발 한 원인을 추론 할 수 없으므로 전체 트랜잭션을 롤백합니다. 경고.

INSERT INTO A VALUES (1); 
INSERT INTO B VALUES (1); 
INSERT INTO V1 (V1_ID, A_ID, B_ID) VALUES (1, 1, NULL); 
INSERT INTO V2 (V2_ID, A_ID, B_ID) VALUES (1, 1, NULL); 
COMMIT;