Oracle - 如果由不同的模式拥有,为什么constraint_name必须是唯一的?

时间:2016-03-09 14:05:33

标签: oracle constraints schema ownership

在Oracle中,如果您尝试在CREATE TABLE语句中明确定义约束的架构,则会导致ORA-00904: : invalid identifier错误:

CREATE TABLE SCHEMA1.MY_TABLE
(
  TABLE_ID NUMBER(5)
, FLAG VARCHAR2(1) DEFAULT 'F'
, CONSTRAINT SCHEMA1.MY_TABLE_PK PRIMARY KEY (TABLE_ID)  -- Parser doesn't like 'SCHEMA1'
, CONSTRAINT SCHEMA1.MY_TABLE_FLAG_CK CHECK (FLAG IN ('T', 'F')) --Same issue
);

这没什么大不了的,因为约束OWNER默认为CREATE TABLE声明中定义的相同模式(或至少在您登录的模式中 - 我的帐户不在&# 39; t有权验证)。这可以通过提取ALL_CONSTRAINTSDBA_CONSTRAINTS中的约束并查看OWNER值(对于上述两个约束读取SCHEMA1)来确认。

但是,如果您在另一个模式下使用第二个重复语句跟进此语句:

CREATE TABLE SCHEMA2.MY_TABLE
(
  TABLE_ID NUMBER(5)
, FLAG VARCHAR2(1) DEFAULT 'F'
, CONSTRAINT MY_TABLE_PK PRIMARY KEY (TABLE_ID)          --This constraint already exists
, CONSTRAINT MY_TABLE_FLAG_CK CHECK (FLAG IN ('T', 'F')) --This one too
);

导致ORA-00955: name is already used by an existing object错误。

我对约束的理解是它们只是数据库中的另一个对象,我认为这些对象遵循我熟悉的相同所有权规则。但基于上面的行为,很明显它们的行为与数据库中的大多数对象不同。

问题

  • 什么是约束要求它们的名称在所有模式中都是唯一的(与数据库中的其他对象不同)?
  • 有没有人知道这个命名要求的技术原因?

对于上下文,我遇到了一个工作场景,我想在不同的模式下存储重复的名称(不要问......这是继承的重复和我只是想保持一致,直到我有资金重构)。现在,我意识到我可以非常简单地将模式添加到名称中并快速绕过这个问题,但这会以错误的方式磨损我的强迫症,所以我想更好地理解为什么我不能做我所做的事情&# 39;我试图做。

-----------------------------更新-------------- -------------

好的......所以我是个傻瓜。请注意,鉴于环境干净,上述方案无法重复。在尝试重现这个问题之后,我现在意识到发生了什么。

我目前正在努力清理一些DDL语句,为生产版本做准备。我不是这个环境中唯一的开发人员,我的离岸团队一直在研究这些相同的表。我一直在编辑一些预先存在的DDL脚本以准备生产版本,并为一些CREATE TABLE语句添加了一些必需的约束。

DROP中运行第二个语句之前,我似乎无法运行SCHEMA2脚本。我的困惑是因为我认为我收到了ORA-00955错误,因为我实际上添加的新约束是因为SCHEMA2.MY_TABLE已经存在于此环境中。我改变了我的约束名称,然后成功地重新运行了所有脚本(因为我必须在重新测试之前在所有模式中运行DROP语句),这种误解更加复杂。结果我认为当我真的没有时,我观察到了无法预料的行为。

感谢所有评论过我的人!

1 个答案:

答案 0 :(得分:2)

您的问题中缺少的是您运行脚本的用户。但这是一个小实验。 作为用户系统连接到数据库。我有可用于实验的模式NGM42和NGM41。

CREATE TABLE NGM41.MY_TABLE
(
  TABLE_ID NUMBER(5)
, FLAG VARCHAR2(1) DEFAULT 'F'
, CONSTRAINT MY_TABLE_PK PRIMARY KEY (TABLE_ID)  -- Parser doesn't like 'SCHEMA1'
, CONSTRAINT MY_TABLE_FLAG_CK CHECK (FLAG IN ('T', 'F')) --Same issue
);

CREATE TABLE NGM42.MY_TABLE
(
  TABLE_ID NUMBER(5)
, FLAG VARCHAR2(1) DEFAULT 'F'
, CONSTRAINT MY_TABLE_PK PRIMARY KEY (TABLE_ID)  
, CONSTRAINT MY_TABLE_FLAG_CK CHECK (FLAG IN ('T', 'F')) 
);

这两个陈述都是成功的。那么约束发生了什么?

select owner,constraint_name from all_constraints
where constraint_name in ('MY_TABLE_PK','MY_TABLE_FLAG_CK')

NGM42   MY_TABLE_PK
NGM41   MY_TABLE_PK
NGM41   MY_TABLE_FLAG_CK
NGM42   MY_TABLE_FLAG_CK

约束是在与表相同的模式中创建的。如您所见,它们不需要在数据库中具有全局唯一性。