目前尚不清楚對我,爲什麼你需要確定任務表的FRUIT_TYPE。表面上看,這只是一個糟糕的(非標準化)數據模型。根據我的經驗,對這類數據進行建模的最佳方式是使用超類型的通用事物(例如FRUIT)和細節類型(APPLE,GRAPE,BANANA)的子類型。這允許我們在記錄每個實例的特定屬性的同時將常見屬性存儲在一個地方。
這裏是超類型的表:
create table fruits
(fruit_id number not null
, fruit_type varchar2(10) not null
, constraint fruit_pk primary key (fruit_id)
, constraint fruit_uk unique (fruit_id, fruit_type)
, constraint fruit_ck check (fruit_type in ('GRAPE', 'APPLE', 'BANANA'))
)
/
水果具有主鍵和化合物唯一密鑰。我們需要在外鍵約束中使用主鍵,因爲複合鍵是一個痛苦的脖子。除非它們不是這些子類型表的情況。這裏我們使用的唯一密鑰作爲參考,因爲通過限制在子類型FRUIT_TYPE的價值,我們可以保證的是,在GRAPES表映射記錄類型「葡萄」的水果記錄等
create table grapes
(fruit_id number not null
, fruit_type varchar2(10) not null default 'GRAPE'
, seedless_yn not null char(1) default 'Y'
, colour varchar2(5) not null
, constraint grape_pk primary key (fruit_id)
, constraint grape_ck check (fruit_type = 'GRAPE')
, constraint grape_fruit_fk foreign key (fruit_id, fruit_type)
references fruit (fruit_id, fruit_type)
, constraint grape_flg_ck check (seedless_yn in ('Y', 'N'))
)
/
create table apples
(fruit_id number not null
, fruit_type varchar2(10) not null
, apple_type varchar2(10) not null default 'APPLE'
, constraint apple_pk primary key (fruit_id)
, constraint apple_ck check (fruit_type = 'APPLE')
, constraint apple_fruit_fk foreign key (fruit_id, fruit_type)
references fruit (fruit_id, fruit_type)
, constraint apple_type_ck check (apple_type in ('EATING', 'COOKING', 'CIDER'))
)
/
create table bananas
(fruit_id number not null
, fruit_type varchar2(10) not null default 'BANANA'
, constraint banana_pk primary key (fruit_id)
, constraint banana_ck check (fruit_type = 'BANANA')
, constraint banana_fruit_fk foreign key (fruit_id, fruit_type)
references fruit (fruit_id, fruit_type)
)
/
在11g中,我們可以使FRUIT_TYPE成爲子類型的虛擬列,並取消檢查約束。所以,現在我們需要一個任務類型表('Peel','Refrigerate','Eat'等)。
create table task_types
(task_code varchar2(4) not null
, task_descr varchar2(40) not null
, constraint task_type_pk primary key (task_code)
)
/
而實際的TASKS表是FRUITS和TASK_TYPES之間的簡單交集。
create table tasks
(task_code varchar2(4) not null
, fruit_id number not null
, constraint task_pk primary key (task_code, fruit_id)
, constraint task_task_fk ask foreign key (task_code)
references task_types (task_code)
, constraint task_fruit_fk foreign key (fruit_id)
references fruit (fruit_id)
/
如果不能滿足您的需求,請編輯您的問題,包括更多的信息。
「......如果你想爲不同的水果不同的任務......」
是的,我不知道這是否是OP公司發佈的設計背後的動機。但通常情況下,工作流程比這要困難得多:有些任務將適用於所有水果,有些僅適用於(例如)成串的水果,其他的只適用於香蕉。
「在我們實際的邏輯,‘水果’與 很少共性完全不同的表。想想客戶,員工,會議室, 建築,資產標籤等步驟的列表應該是 自由形式,並允許用戶指定這些事情的任何行爲。「
所以你有一堆現有的表。您希望能夠將這些表中的記錄以自由滑動的方式分配給任務,但能夠保證擁有該任務的特定記錄的識別。
我認爲你仍然需要一個通用表來保存任務中的actor的ID,但是你需要以某種方式將它鏈接到其他表。下面是我可能接近它:
SOEM樣品現有的表:
create table customers
(cust_id number not null
, cname varchar2(100) not null
, constraint cust_pk primary key (fruit_id)
)
/
create table employees
(emp_no number not null
, ename varchar2(30) not null
, constraint emp_pk primary key (fruit_id)
)
/
一個普通的表來保存演員:
create table actors
(actor_id number not null
, constraint actor_pk primary key (actor_id)
)
/
現在,你需要交集表將現有的表有關聯新的:
create table cust_actors
(cust_id number not null
, actor_id number not null
, constraint cust_actor_pk primary key (cust_id, actor_id)
, constraint cust_actor_cust_fk foreign key (cust_id)
references customers (cust_id)
, constraint cust_actor_actor_fk foreign key (actor_id)
references actors (actor_id)
)
/
create table emp_actors
(emp_no number not null
, actor_id number not null
, constraint emp_actor_pk primary key (emp_no, actor_id)
, constraint emp_actor_emp_fk foreign key (emp_no)
references eployees (emp_no)
, constraint cust_actor_actor_fk foreign key (actor_id)
references actors (actor_id)
)
/
TASKS表是相當不奇怪,給出什麼是去NE前:
create table tasks
(task_code varchar2(4) not null
, actor_id number not null
, constraint task_pk primary key (task_code, actor_id)
, constraint task_task_fk ask foreign key (task_code)
references task_types (task_code)
, constraint task_actor_fk foreign key (actor_id)
references actors (actor_id)
/
我同意所有這些路口表看起來像一個很大的開銷,但沒有任何其他的方式來強制執行外鍵約束。每當您在CUSTOMERS中創建記錄時,額外的障礙就是創建ACTORS和CUSTOMER_ACTORS記錄。同上刪除。唯一的好消息是你可以生成你需要的所有代碼。
此解決方案是否比具有一百個可選外鍵的表更好?也許不是:這是一個品味問題。但我喜歡它比沒有外鍵更好。如果在數據庫實踐中存在關於euniversal的真理,那麼它是這樣的:依靠應用程序代碼來強制執行關係完整性的數據庫是充斥着引用錯誤父項或根本不引用父項的子項的數據庫。
所以意圖是有一個「食譜」表與一組食譜行動?如「剁碎的奶奶 - 蘋果」,「切片c ban香蕉」,「把奶奶蘋果放在碗裏」,「把草莓香蕉放在碗裏」等等。據推測,這些作品只能在蘋果上切割,而切片只能用在香蕉上,但是也可以放在碗裏,而一些機器人會使用這個配方表來了解如何製作水果沙拉? (抱歉評論,因爲某些原因無法編輯原件) – Brian 2012-01-11 19:58:45
@Brian:您可以編輯評論長達5分鐘。但是你仍然可以刪除第一條評論。 – 2012-01-11 21:48:09
@Brian:這是一個很好的方式來描述我問的問題。實際上,一個機器人會檢查香蕉是否被切成薄片,蘋果是否被切碎,葡萄放在碗裏。一旦它認識到所有這些事情都已經發生,它就會正確地確定我們有完成的水果沙拉。 – StilesCrisis 2012-01-11 23:52:37