我实际上想要在Oracle的ERD中实现两个表之间的强制一对一关系。这两个表是州长和州。州长只能管理一个州,一个州必须只有一个州长。我想在Oracle中实现它。我写了如下查询
create table gov
(gid number(3) ,name varchar2(100),
constraint gov_pk primary key (gid)
);
create table state
(
sid number(3) ,
name varchar2(100),
gid number(3),
constraint state_pk primary key (sid),
constraint gov_state_fk foreign key (gid) references gov(gid),
constraint state_uk unique(gid,name)
);
但这似乎不起作用。我找不到任何其他方式。请帮我解决一下这个。我会感激你的。请让我知道为什么没有建立一对一的关系。
答案 0 :(得分:2)
您已经非常接近成功实施您的要求。
"一个州必须有一个且只有一个统治者"
所以在STATE表上强制使用GID。
"治理者只能管理一个州"
因此,仅在GID上强制使用唯一键。
create table state
(
sid number(3) ,
name varchar2(100),
gid number(3) not null,
constraint state_pk primary key (sid),
constraint gov_state_fk foreign key (gid) references gov(gid),
constraint state_uk unique(gid)
);
"我可以成功地将数据添加到gov表而不添加状态表中的任何行。"
强制父母必须有儿童关系非常困难。
这是一个触发器:
create or replace trigger enforce_gov_state
before insert or update on gov
for each row
is
l_sid state.sid%type;
begin
select s.sid into l_sid
from state s
where s.gid = :new.gid;
exception
when no_data_found then
raise_application_error(-20000, 'Governor must have a state');
end;
/
那么那就好了。只有一点皱纹:我们如何在任何一个表中插入行???? 我们不能插入GOV直到状态存在;我们不能插入STATE,直到调控器存在。
有一种解决方法:将外键延迟到STATE,以便在提交整个事务之前不强制执行。这允许创建STATE记录,然后是GOV记录。当然,在创建GOV记录之前,我们需要知道STATE.GID的值。
此外,改变GOV - STATE关系也有类似的障碍。除了可以通过更新所有GOV属性(GID除外)以适应新的州长来解决它。这有点粗略,但你去了。
为什么这么难?通常,表之间的一对一关系是双方都必须的,这表明有缺陷的数据模型。
因此,更真实的实现会将STATE_GOV作为STATE和GOV之间的交集表。维护这样一个表格要简单得多,这是一个好兆头。
答案 1 :(得分:1)
向STATE添加唯一约束:
create table state
(
sid number(3) ,
name varchar2(100),
gid number(3),
constraint state_pk primary key (sid),
constraint gov_state_fk foreign key (gid) references gov(gid),
constraint state_uk unique(gid,name)
constraint gov_state_uk unique (gid)
);
答案 2 :(得分:1)
从州表中删除FK。拥有它并使其独特意味着你不能在不知道州长的情况下进入一个州。使用每个FK上的唯一约束在State和Gov之间创建一个交集表:
create table StateGov(
StateID number( 3 ) not null references State( sid ),
GovID number( 3 ) not null references Gov( gid ),
constraint UQ_StateGov_State unique StateID,
constraint UQ_StateGov_Gov unique GovID
);
任何州都不会出现多次,州长不会出现多次。在知道州长之前,没有循环引用,没有断言,插入状态记录没有问题。