iT邦幫忙

1

趣味SQL 外鍵限制之先有雞還是先有蛋?

  • 分享至 

  • xImage

先有雞還是先有蛋的情境,例如:
員工資料裡面有所屬部門,部門資料表裡有部門主管,部門主管同時也是員工一員.

會有這樣的設計:

create table empl (
  eid int not null primary key
, ename text not null
, dept_id int not null
);

create table dept (
  did int not null primary key
, dname text not null
, manager_id int not null
);

alter table dept
add foreign key (manager_id)
references empl(eid);

alter table empl
add foreign key (dept_id)
references dept(did);

此時要 insert 資料時,會有一些麻煩
Demo

不限制方法.

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
3
froce
iT邦大師 1 級 ‧ 2022-02-25 13:17:45

我不會把主管設計在dept這表裡,員工的身分放在員工的表就好啦。

create table empl (
  eid int not null primary key
, ename text not null
, dept_id int not null
, position int not null  #數字,越大職位越高
, tmpposition int  #臨時身分
);

create table dept (
  did int not null primary key
, dname text not null
);

如果還是要放dept,因為實際上會有臨時代理及暫時沒有主管的狀況,至少 manager_id 我不會設為not null

這也是一種方法.設計上有許多方式,並沒有說一定要怎樣設計.
有沒有另外的方式? 可以再多想一下,這樣會更精彩!

2
純真的人
iT邦大師 1 級 ‧ 2022-02-25 13:18:31

Oracle可以同時新增不同資料表~
所以沒有外鍵問題~

create table empl (
  eid number(10,0) PRIMARY KEY not null 
, ename varchar2(50) not null
, dept_id number(10,0) not null
);
create table dept (
  did number(10,0) primary key not null 
, dname varchar2(50) not null
, manager_id number(10,0) not null
);
create table tmp (
  id number(10,0) primary key not null 
, name varchar2(50) not null
, reid number(10,0) not null
);
ALTER TABLE dept
  ADD CONSTRAINT X1
    FOREIGN KEY (manager_id) REFERENCES empl (eid) 
    INITIALLY DEFERRED DEFERRABLE;
ALTER TABLE empl
  ADD CONSTRAINT X2
    FOREIGN KEY (dept_id) REFERENCES dept(did) 
    INITIALLY DEFERRED DEFERRABLE;
insert all
into empl(eid,ename,dept_id) values(id,name,reid)
into dept(did,dname,manager_id) values(id,name,reid)
select * from tmp 

select * from empl

select * from dept

https://dbfiddle.uk/?rdbms=oracle_21&fiddle=605154fcf34fb38f45a7af2c19fc604e

原來如此~考慮到會被外鍵鎖住的問題~

1

不限方法的話...這樣算作弊嗎...(HeidiSQL)
Create完直接先insert,在將欄位的default都設為0

SET FOREIGN_KEY_CHECKS=0;

INSERT INTO dept VALUES ('0','待確認','0');
INSERT INTO empl VALUES ('0','待確認','0');

SET FOREIGN_KEY_CHECKS=1;

抱歉,小的才疏學淺 一直誤以為HeidiSQL是從MySQL延伸出來的
讓大大見笑了

2
海綿寶寶
iT邦大神 1 級 ‧ 2022-02-25 16:26:19

小孩才做選擇
雞蛋同時有
把酒問青天
/images/emoticon/emoticon73.gif

with new_dept as (
  insert into dept (did, dname, manager_id) values (1,'IT',101)
  returning manager_id
)
insert into empl (eid,ename,dept_id)
values 
( (select manager_id from new_dept),'Tom',1);

這裡抄來改的

我要發表回答

立即登入回答