Oracle的外键用来限制子表中参考的字段的值,必须在主表中存在。而且在主表的记录发生变化导致外键参考唯一约束值发生了变化时,定义了一系列的动作。
: @5 i# s& N7 f" {- Z1 V 这篇简单描述一下SET TO NULL操作。
/ F" B% P, [5 A+ P 上一篇描述了Oracle外键处理默认操作:No Action,这里简单介绍一下SET TO NULL操作。还是利用前面例子的表,不过约束需要重建。' V+ e! l4 Z1 N. F8 a: M3 `
SQL> DROP TABLE T_C;
" M1 n |0 w* o f% P 表已删除。
, E. [- w& ?2 o5 R, T/ i1 K( j$ p$ y/ m SQL> DROP TABLE T_P;
7 l9 w3 G! @5 k5 `0 _7 D6 f 表已删除。" S5 O0 O0 m. c# Q
SQL> CREATE TABLE T_P (ID NUMBER, NAME VARCHAR2(30));
: N* m) ?5 k9 D- O% ~ 表已创建。
+ f) r; M7 V, l9 r SQL> ALTER TABLE T_P ADD PRIMARY KEY (ID);; y3 A4 J" M9 m" \9 U! t
表已更改。 l# H% k4 A: n9 }/ M
SQL> CREATE TABLE T_C (ID NUMBER, FID NUMBER, NAME VARCHAR2(30));
: p7 G. m- R$ d8 S# @4 e 表已创建。
+ \! w1 U& A" J, l" L+ U SQL> ALTER TABLE T_C ADD CONSTRAINT FK_T_C
- h. }" S& j: }/ y# J 2 FOREIGN KEY (FID)
0 X" j6 ]5 ^- j: U' g$ \& d 3 REFERENCES T_P (ID)
% d5 a# ?8 _0 [/ g" W+ y 4 ON DELETE SET NULL;6 Y. [# g& ?% _! C/ u
表已更改。
$ q* J+ O2 S7 J4 |' |# F SQL> INSERT INTO T_P VALUES (1, ’A’);% G, `( w6 I2 T6 I
已创建 1 行。" \, ?# I( a" Q
SQL> INSERT INTO T_P VALUES (2, ’B’);
0 }- h- J/ V: c 已创建 1 行。
# S' j3 y; ?1 I9 D SQL> INSERT INTO T_C VALUES (1, 1, ’A’);1 ]* B! U4 f* t8 m3 S3 v, e# S* a
已创建 1 行。
! r9 Y# s7 L2 [4 C SQL> INSERT INTO T_C VALUES (2, 2, ’B’);! G q |) H; }4 I Z
已创建 1 行。6 ~: H! L' s5 t9 p. i# E
SQL> INSERT INTO T_C VALUES (3, 1, ’C’);% v8 f3 ~3 }3 E) s" f5 }1 d
已创建 1 行。# i% G+ t5 D( O4 a+ P
SQL> COMMIT;
0 ] U* r. G5 U) p( F 提交完成。. e3 r5 S: b2 Y! N& ?% ?' G
下面检查一下DELETE SET NULL是如何工作的:* v& W* E+ u3 H
SQL> SELECT * FROM T_P;" E. X: Y) m6 `# U2 o! l& K
ID NAME
[% U j) I2 R) i$ D8 l& l; x( L/ | ---------- ------------------------------# p }; b" _* d
1 A1 }4 ~( ]" V6 a4 b( z* B
2 B
( v+ m7 ^8 R: h L, G4 c SQL> SELECT * FROM T_C;5 J3 d# R( x' f* B5 Z; `- {6 p. g
ID FID NAME2 W: Q" K& Q" N: p9 F8 e: k$ L
---------- ---------- ------------------------------* I; ?6 c% e% e1 Q9 I6 ?
1 1 A. f. Z9 S9 p/ l$ ~ } L2 V
2 2 B$ ~5 ], J% z$ G0 J4 X
3 1 C: | v. X" V9 p6 @$ W& Q) \
SQL> DELETE T_P WHERE ID = 2;
5 `2 f: A6 h5 G& \6 A 已删除 1 行。
) K9 V, l6 Q, p2 | [" s+ G* Q SQL> SELECT * FROM T_C;
; x) O) _# D, v. s/ ~1 c ID FID NAME5 N, H1 ` F# {5 `$ Y; B; h
---------- ---------- ------------------------------7 C; h3 Y0 l, J$ r, B- l
1 1 A" ` N& ]2 z1 |' V2 X ^8 w6 H
2 B% v3 I6 \2 U* @3 o+ p3 x2 v
3 1 C. }1 C- W6 \1 X0 K
SQL> UPDATE T_P SET ID = 3;9 a! y* i& l( D g0 y- d G
UPDATE T_P SET ID = 3
+ W" w& d+ B; t *第 1 行出现错误:/ c7 S a5 J/ M# P, [( l
ORA-02292: 违反完整约束条件 (YANGTK.FK_T_C) - 已找到子记录日志
6 ?3 A Q" A# [* y1 X0 ~ 可以看到这个Set no null的操作和语法中的名称一样,只对DELETE操作有效,而对于UPDATE操作无效。
6 i* ~/ r; t4 j% q- R# I 这个约束操作还有一个前提,就是要求子表的外键列允许为空,否则对主表的DELETE操作会报错:; B+ T3 v- J/ w' m! E+ y3 r
SQL> SELECT * FROM T_C;+ q) w1 V% m$ n# @
ID FID NAME3 s& X6 z; n- e. C
---------- ---------- ------------------------------4 V. Z% D6 `! Q2 t
1 1 A
/ F" o9 h- a1 o' F3 x0 b% [ 2 B
2 v( T# a# T+ Z; ?# z$ q 3 1 C$ e# s" W0 Z5 a
SQL> DELETE T_C WHERE ID = 2;
8 w0 H: E- h" i' X 已删除 1 行。3 z* `- f! M* |: z
SQL> ALTER TABLE T_C MODIFY FID NOT NULL;
9 Y* A" V5 B4 b- d( M* A: b 表已更改。( |& a0 O: A' V+ n& ?
SQL> DELETE T_P;
) B! S0 Z0 v& S2 g: U DELETE T_P1 t) ~% d+ R) V1 o. T1 P0 s
*第 1 行出现错误:
/ k1 H8 G' j) N9 J3 L ORA-01407: 无法更新 ("YANGTK"."T_C"."FID") 为 NULL
5 {) p/ t3 d% u* F3 o2 U9 i 从这里也可以看到,虽然Oracle支持Set to null,但是只是实现了DELETE语句,而没有实现UPDATE语句,这和SQL标准的定义还是有区别的。 |