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

Oracle - Why must constraint_name be unique if owned by a different schema?

在 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 声明中定义的相同模式( 或至少在您登录的模式中 -我的帐户没有验证权限)。这可以通过拉起 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 错误。

我对约束的理解是,它们只是数据库中的另一个对象,我假设它们受制于我所熟悉的相同所有权规则。但是根据上面的行为,很明显它们的行为不像数据库中的大多数对象。

问题


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

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

好吧...所以我是个傻瓜。请注意,如果环境干净,上述情况不能重复。在尝试重现问题之后,我现在意识到发生了什么。

我目前正在清理一些 DDL 语句,为产品发布做准备。我不是这种环境中唯一的开发人员,我的离岸团队一直在处理这些相同的表。我一直在编辑一些预先存在的 DDL 脚本,为产品发布做准备,并向一些 CREATE TABLE 语句添加了一些需要的约束。

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

感谢所有给我点亮评论的人!

您的问题中缺少的是您 运行 脚本所在的用户。但这里有一个小实验。 作为用户系统连接到数据库。我有可供实验使用的模式 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

约束是在与 table 相同的架构中创建的。如您所见,它们不需要在数据库中是全局唯一的。