5

我正在对我继承的 Rails 站点进行维护工作;它由 Oracle 数据库驱动,我可以访问该站点的开发和生产安装(每个都有自己的 Oracle DB)。尝试在生产站点而不是开发站点上插入数据时,我遇到了 Oracle 错误:

ActiveRecord::StatementInvalid (OCIError: ORA-00001: unique constraint (DATABASE_NAME.PK_REGISTRATION_OWNERSHIP) violated: INSERT INTO registration_ownerships (updated_at, company_ownership_id, created_by, updated_by, registration_id, created_at) VALUES ('2006-05-04 16:30:47', 3, NULL, NULL, 2920, '2006-05-04 16:30:47')):
/usr/local/lib/ruby/gems/1.8/gems/activerecord-oracle-adapter-1.0.0.9250/lib/active_record/connection_adapters/oracle_adapter.rb:221:in `execute'
app/controllers/vendors_controller.rb:94:in `create'

据我所知(我使用 Navicat 作为 Oracle 客户端),开发站点的数据库架构与实时站点的数据库架构相同。我不是甲骨文专家;谁能阐明为什么我会在一个安装中而不是另一个安装中出现错误?

顺便说一句,开发和生产的registration_ownerships 表都填充了大量数据,包括country_ownership_id 的重复条目(由索引PK_REGISTRATION_OWNERSHIP 驱动)。如果您需要更多信息来解决问题,请告诉我。很抱歉我还没有提供更多信息,但我只是不确定哪些细节会有所帮助。

更新:我尝试在生产服务器上删除约束,但没有效果;我也不想删除索引,因为我不确定后果可能是什么,而且我不想让生产变得比现在更不稳定。

奇怪的是,我尝试手动执行引发错误的 SQL,并且 Oracle 接受了插入语句(尽管我不得不用字符串文字将日期包装在 to_date() 调用中以绕过“ORA-01861:文字不匹配格式字符串”错误)。这里可能发生了什么?

4

4 回答 4

3

根据约束的名称PK_REGISTRATION_OWNERSHIP,您有一个主键违规。registration_ownerships如果这些数据库没有以同步方式维护这些数据,则某些/某人已经在您的生产数据库的表中插入了一条记录,其中company_ownership_id=2 和registration_id=2920。(我根据名字猜测细节)

如果生产数据库中需要存在这组特定的值,

1)检查已经存在的内容是否不是您要插入的内容。如果是,你就完成了。

2)如果您需要按原样插入示例数据,则需要修改现有数据并重新插入(以及所有依赖/引用记录),然后您可以插入您的值。

于 2010-04-12T19:45:23.337 回答
1

如果您查询该表并没有找到匹配的行,则可能是以下原因之一:

  1. 会话试图插入该行两次。
  2. 另一个会话已插入该行,但尚未提交。

此外,检查 dev 和 prod 之间唯一约束的状态是否相同。也许 dev 上的那个被标记为未验证 - 检查索引是否存在于 dev 上并且是唯一索引(注意:在 Oracle 中,可能有一个由非唯一索引验证的唯一约束)。

于 2010-04-13T03:37:32.087 回答
0

碰巧的是,目录周围有一份“注册”模型的备用副本;即使它有不同的名称(“registrations_2349871.rb”或类似名称)Rails 运行所有模型功能(保存、验证等)两次,因此违反了键约束!我以前从未见过这样的行为。删除流氓文件解决了这个问题。

于 2010-04-20T13:23:05.417 回答
0

仔细查看约束的底层唯一索引。删除约束不会改变任何内容的原因是索引仍然存在,并且它是唯一索引。以下内容告诉您有关这两种环境中的索引的哪些信息?两个索引都有效吗?两者定义相同吗?它们实际上都是独一无二的吗?

SELECT ai.table_name, ai.index_name, ai.uniqueness, aic.column_name, ai.status
  FROM all_constraints ac JOIN all_indexes ai ON (ac.index_name = ai.index_name)
                          JOIN all_ind_columns aic ON (ai.index_name = aic.index_name)
 WHERE ac.owner = 'YOUR_USER'
   AND ac.constraint_name = 'PK_REGISTRATION_OWNERSHIP'
 ORDER BY ai.index_name, column_position;
于 2010-04-13T23:15:39.583 回答