Oracle的外键用来限制子表中参考的字段的值,必须在主表中存在。而且在主表的记录发生变化导致外键参考唯一约束值发生了变化时,定义了一系列的动作。7 {, m! s0 r9 u) V% N( C
前面几篇文章介绍了Oracle所支持的3种约束行为NO ACTION、DELETE SET NULL和DELETE CASCADE.至于SQL标准中定义的其他操作,Oracle只能通过触发器来实现,这里给出一个简单的RESTRICT操作的例子。
# x; \; F# X! G- H( l, g SQL> DROP TABLE T_C;& |# H; l# F Z, |" P# b, h2 x
表已删除。
# C' n* y$ {5 W4 R2 t SQL> DROP TABLE T_P;) n; c/ [& A" M' F! u( H
表已删除。' f- h, t1 n! P8 T
SQL> CREATE TABLE T_P (ID NUMBER, NAME VARCHAR2(30));% T; r; v/ M/ b5 u/ V6 W$ k5 N7 c
表已创建。
1 Q) ]4 l6 @9 @4 D5 e' E, Y SQL> ALTER TABLE T_P ADD PRIMARY KEY (ID);
; R5 |' w% l2 I9 J 表已更改。& P% t3 O& Q! }5 R$ B4 L
SQL> CREATE TABLE T_C (ID NUMBER, FID NUMBER, NAME VARCHAR2(30));6 r7 a8 h' x7 W8 d
表已创建。
, V9 P0 w8 g8 a2 C! ^; l SQL> ALTER TABLE T_C ADD CONSTRAINT FK_T_C
) C. [, n7 b6 M; Y' m7 X! ?3 s 2 FOREIGN KEY (FID)$ f, n% K- S X5 Z
3 REFERENCES T_P (ID);
2 w5 @# Z( v- m6 D( y. Y1 h0 e 表已更改。. R b8 e7 B( z# [0 B8 \ t
SQL> INSERT INTO T_P VALUES (1, ’A’);
( H1 m# P) j2 w* _; X$ R* v 已创建 1 行。
. a! |0 L1 ~4 J# v- S' P SQL> INSERT INTO T_P VALUES (2, ’B’);
, d Z8 l9 `3 \+ S$ i 已创建 1 行。( U2 g( x/ K+ A, D
SQL> INSERT INTO T_C VALUES (1, 1, ’A’);$ p6 H1 Q$ y3 N* ?" Q$ j7 D( ?
已创建 1 行。
2 u6 N; C* p- p$ p) k SQL> COMMIT;
4 p' E2 c) F% A# e7 ^* J! c 提交完成。/ z# m; I& {$ u& L( b4 S6 L
SQL标准定义的RESTRICT操作其实和NO ACTION操作十分类似。不同之处在于,RESTRICT的检查在语句执行之前,一旦发现主键被引用,就会报错,阻止更新或删除操作的执行。! r9 @) Y) U& M$ H, g
SQL> SELECT * FROM T_P;
' z5 `* b6 K" Q% I* B ID NAME# r M) o I) Z" v3 q! y7 U
---------- ------------------------------) }' u/ q6 r( ?& h% Z2 R# ~* h% N
1 A
5 S0 h9 ~, Q. p( \ j: ^' q 2 B
' s9 ?9 N) C4 U8 T V$ i. B6 Q SQL> SELECT * FROM T_C;
/ R3 A5 D) D% z6 n8 p3 C4 z ID FID NAME$ C5 D) S( _, n
---------- ---------- ------------------------------
; f2 ]! ^" e- G9 u( ^2 M 1 1 A
+ m: {; o( ^4 i3 E: W- c9 _ SQL> UPDATE T_P SET ID = 3 WHERE ID = 1;1 s; a/ @$ r2 d5 q
UPDATE T_P SET ID = 3 WHERE ID = 1
. @; a9 Z, ?6 j, T *第 1 行出现错误:' z8 L4 N6 c: C0 c1 A( t
ORA-02292: 违反完整约束条件 (YANGTK.FK_T_C) - 已找到子记录日志
& K& Y( D, o* ?% K# z 对于上面这种情况,无论是NO ACTION还是RESTRICT,效果没有什么差别,而对于下面的情况就不一样了:( p5 a* E- Y( |, X
SQL> UPDATE T_P SET ID = ID - 1;! n3 X( I: A# k# n) Z+ L
已更新2行。8 `, ^ e/ l% g' W. [
SQL> SELECT * FROM T_P;
6 L; n# }# S) y% c. y ID NAME
7 [: v$ j1 c5 ?1 ]4 i ---------- ------------------------------! _8 U7 o- J' m% L* H- m7 i
0 A
. {0 Y$ \1 I( L6 ^- B4 X 1 B& x) p7 I4 p5 p/ X, {2 B8 `3 @
SQL> UPDATE T_P SET ID = ID + 1;
' [4 T! g% c* R' u; H 已更新2行。) u; J& q' r) Y# U, p
SQL> SELECT * FROM T_P;
8 C5 W5 @# k1 {% D( ~+ O ID NAME
2 C6 ]/ k* { E* r ---------- ------------------------------+ G) o3 S) I) B9 g% S" z: \! @% K
1 A E$ W5 Q" Z" w" R- m
2 B |