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

标签 oracle constraints schema ownership

在 Oracle 中,如果您尝试在 CREATE TABLE 语句中显式定义约束架构,将会导致 ORA-00904: : invalididentifier 错误:

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:名称已被现有对象使用错误。

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

问题

  • 要求其名称在所有架构中保持唯一(与数据库中的其他对象不同)的约束是什么?
  • 有人知道此命名要求的技术原因吗?
<小时/>

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

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

好吧...所以我是个傻瓜。请注意,在干净的环境下,上述场景无法重复。在尝试重现该问题后,我现在意识到发生了什么。

我目前正在清理一些 DDL 语句,为生产版本做准备。我不是这个环境中唯一的开发人员,我的离岸团队一直在这些相同的 table 上工作。我一直在编辑一些预先存在的 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

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

关于Oracle - 如果由不同的模式拥有,为什么constraint_name必须是唯一的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35893811/

相关文章:

java - 如何在不使用任何工具的情况下导出 SYBASE IQ/SYBASE ASE 中所有对象(如表、索引等)的 ddl?

sql - 在针对 Oracle 编写良好的 SQL 时,您会给您的开发人员什么简单的指导方针?

sql - 获取ORACLE中的总行数然后只得到4个结果

来自 wsdl 的 Java.xml.validation.Schema

sql-server - SQL字段约束

Symfony 条件表单验证

ruby-on-rails - rake db :schema:dump recreate schema. rb 是来自迁移还是数据库本身?

java - SQL 条件语句

xml - 您如何在 Oracle PL/SQL 中解析一个简单的 XML 片段并将其加载到全局临时表中?

ios - 如何以编程方式设置 View 的约束关系,而不是 subview ?