添加 FK 或 PK 约束是否会使某些内容无效?

Can adding FK or PK constraints invalidate something?

我有几个具有主-外键关系的表,但这些约束实际上并不存在。现在我想用 alter table 语句添加它们。

这些命令会导致任何依赖于表的对象变得无效吗?

谢谢。

这是个好问题。我们戳一下数据库看看。这是设置:

SQL> create table p23 (id number not null, col1 varchar2(10));

Table created.

SQL> create table c23 (id number not null, p_id number not null, col1 varchar2(10));

Table created.

SQL> create or replace procedure tst23
  2  is
  3  begin
  4    insert into p23 values (1, 'ABC');
  5    insert into c23 values (11, 1, 'DEF');
  6  end;
  7  /

Procedure created.

SQL> select status from user_objects where object_name = 'TST23';

STATUS
-------
VALID

SQL> 

一切都是copacetic。现在我们将添加一些约束。

SQL> alter table p23 add constraint p23_pk primary key (id);

Table altered.

SQL> select status from user_objects where object_name = 'TST23';

STATUS
-------
VALID

SQL> alter table c23 add constraint c23_p23_fk 
  2      foreign key (p_id) references p23;

Table altered.

SQL> select status from user_objects where object_name = 'TST23';

STATUS
-------
VALID

SQL>

一切都还很酷。但是当我们改变 table 的结构时,就会发生这种情况......

SQL> alter table p23 add col2 date;

Table altered.

SQL> select status from user_objects where object_name = 'TST23';

STATUS
-------
INVALID

SQL> 

...这正是我们想要的。

请注意,我 运行 这些测试是在 11gR2 上进行的。 Oracle 在 11g 中引入了细粒度的依赖关系跟踪,当我们 运行 DDL 对其依赖关系时,它使编程对象更加健壮。 Find out more。所以在早期版本中结果可能会有所不同。测试是值得的。


" what is the reason for the procedure to become invalid?"

添加、修改或删除列等结构更改可能会对引用对象产生影响。该过程具有未指定目标列的插入语句。所以添加一列引入了一个 ORA-00947: not enough values 错误。

但是假设我们采用了良好做法并指定了列?

SQL> create or replace procedure tst23
  2  is
  3  begin
  4      insert into p23 (id, col1) values (1, 'ABC');
  5  end;
  6  /

Procedure created.

SQL> select status from user_objects where object_name = 'TST23';

STATUS
-------
VALID

SQL> alter table p23 add col4 number;

Table altered.

SQL> select status from user_objects where object_name = 'TST23';

STATUS
-------
VALID

SQL> 

现在我们受到细粒度依赖项跟踪的保护。好吧,有点。我们不应该用依赖跟踪代替影响分析:

SQL> alter table p23 add col5 date not null;

Table altered.

SQL> select status from user_objects where object_name = 'TST23';

STATUS
-------
VALID

SQL> 

该过程具有 VALID 状态,但当我们 运行 它时它仍然会失败,因为它不会填充新的强制列。