可以添加FK或PK约束无效吗?

时间:2017-04-18 05:35:18

标签: oracle constraints alter-table

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

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

感谢。

1 个答案:

答案 0 :(得分:2)

这是一个很好的问题。让我们捅数据库然后看看。这是设置:

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>

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

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。因此,早期版本的结果可能会有所不同。测试是值得的。

  

"该程序失效的原因是什么?"

添加,修改或删除列等结构更改可能会对引用对象产生影响。该过程具有插入语句,该语句没有指定目标列。因此,添加列会引入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状态,但在运行它时仍然会失败,因为它没有填充新的强制列。