|
我在SQL Server 2008数据库中具有以下表:5 [( Y8 w( p4 j& a- F, }
4 f- h" |: v# p* C. otblItem ,它具有一个 ItemID 字段;/ Y) V, m7 T6 G; `' T4 A- V
, L9 | y( g, \# K8 k* h' G4 d: t
tblGoodItem ,它也有一个ItemID字段,并且有一个指向tblItem的外键;
: i8 m! V/ E {! B0 f
( l. N/ s0 X$ utblBadItem ,它也具有ItemID字段,并且还具有指向tblItem的外键。2 `" S8 I# k/ E ]. y
! ^+ x" T" A' t4 F+ H) d5 p5 t- f1 M( e
一个项目不能同时是好项目和坏项目。它必须是一个或另一个。但是,无论该项目是好是坏,它都必须是一个项目。" G3 f# b, R8 \/ l$ g) D7 }
我的问题是: 如何在tblGoodItem和tblBadItem的ItemID字段中添加约束,以便两个表中都不存在ItemID值 ?/ ^5 l0 a4 M8 g9 S* K
我已经阅读了Stack Overflow关于类似问题的一些答复,并且正在考虑以下解决方案:
: O! x: ?4 L2 V4 J: g, D0 B) {6 [8 ~$ I8 f! m
创建一个视图 vwItem ,该视图在ItemID上的tblBadItem上连接tblGoodItem。, U/ a, @8 k' B5 | o
$ x* |3 a' U, G
编写一个UDF fnItem ,它对vwItem进行查询,以查看视图中存在多少记录。5 n" K* P& ?! ~7 C
4 X. D& \4 p- @4 e4 S4 o% f: R
具有一个约束,该约束调用fnItem并验证返回的值为0。
) f/ X( _! ]( k7 N9 z4 i. ^6 I2 d# K
" k* z& Z! a" K2 h2 [8 I* S1 _! \5 g
这是最好的主意吗?有谁有更好的主意吗?" C. |2 |) R/ [- {1 v# x1 [
; e4 p& A; V4 x) c- n- N% z4 f
解决方案:
8 E) u0 O/ o9 b% r0 h" q
) S& Y" g: B% H4 a. e* q2 H+ z
( Q/ o* x& ], E1 n" `) j
3 j+ U% l1 ^/ _1 z( _1 F: p0 k 添加一列tblItem.ItemType列。此列在任何给定的行上只能有一个值(显然)。在ItemID,ItemType上添加唯一约束。
- `; X9 l) e8 e3 d; _0 L# S4 R现在的诀窍是:很少有人记住这一点,但是外键可以引用唯一约束的列。
9 w- A: |! W8 x/ ECREATE TABLE tblItem (
1 X# k- Y( j# _% g" e* m ItemID INT PRIMARY KEY,
) F+ t5 X3 K. G& N ItemType CHAR(1),
& i3 Z! C8 @* t! T UNIQUE KEY (ItemID, ItemType), `3 o1 L. R1 C- u8 ]0 q
);7 g. u- |8 C) ?2 B3 ~1 x* @( i' @
CREATE TABLE tblGoodItem (
: u' F2 d% T. I ItemID INT PRIMARY KEY, e+ @- i6 z7 Y1 p" [( _* N
ItemType CHAR(1),
6 m* P1 d+ d& [" O# G9 P% o CHECK (ItemType='G')2 r7 ?6 O7 y: {0 W9 L
FOREIGN KEY (ItemID, ItemType) REFERENCES tblItem(ItemID, ItemType)
1 Y& z9 `. s2 Y7 e1 a$ X4 D4 W! w0 J);' b" P5 ?" \, L: X& k6 E/ I
CREATE TABLE tblBadItem (5 b8 u9 v9 B1 p8 f" v
ItemID INT PRIMARY KEY% j) v% I5 Z( O: F; ]4 V2 F
ItemType CHAR(1),
4 E \/ @8 p" n" F' E$ K! F CHECK (ItemType='B')
6 O. k* m2 L" p0 D FOREIGN KEY (ItemID, ItemType) REFERENCES tblItem(ItemID, ItemType) * p3 u% j( H" e
);
" e4 s) p" o+ W. N如果将每个子表中的ItemType约束为固定值,则tblItem中的给定行只能由一个子表引用。/ H% a, U" {+ J+ J
但是,将项目从好更改为坏的过程分为三个步骤:
! B; E9 Y" o0 ^# w0 t: X( S9 L* q[ol]从tblGoodItem删除行' h; E: ~+ r2 Z/ C2 G! \2 W! O
在tblItem中更新行的ItemType 0 k8 X4 P4 j( Q, a. L5 D
在tblBadItem中插入行5 P. U; G: t& ~0 f+ P
[/ol] |
|