执行Active Storage迁移时遭遇ORA-00955错误:对象名称已被占用
问题诊断
你碰到的这个ActiveRecord::StatementInvalid: OCIError: ORA-00955错误其实很直白——Oracle数据库里已经存在ACTIVE_STORAGE_BLOBS表了,迁移脚本执行CREATE TABLE时自然就冲突报错了。
解决方案
根据你的实际情况,你可以选下面几种处理方式:
1. 先确认表的真实状态
先登录Oracle数据库,执行这两句查询,确认两张表是不是真的存在:
-- 检查active_storage_blobs表 SELECT table_name FROM user_tables WHERE table_name = 'ACTIVE_STORAGE_BLOBS'; -- 检查active_storage_attachments表 SELECT table_name FROM user_tables WHERE table_name = 'ACTIVE_STORAGE_ATTACHMENTS';
2. 场景一:表无业务数据,直接清理后重跑迁移
如果查询结果显示表存在,而且里面没有任何需要保留的数据,直接删表再执行迁移就好:
-- 先删依赖的attachments表(因为有外键关联,不能先删blobs表) DROP TABLE ACTIVE_STORAGE_ATTACHMENTS; -- 再删blobs表 DROP TABLE ACTIVE_STORAGE_BLOBS;
回到Rails项目里,执行迁移命令:
rails db:migrate
3. 场景二:表已有数据,不能删除
如果表里面已经存了业务数据,绝对不能删,那你得修改迁移文件,添加if_not_exists: true参数,让迁移只在表不存在的时候才创建:
修改你的CreateActiveStorageTables迁移文件:
# This migration comes from active_storage (originally 20170806125915) class CreateActiveStorageTables < ActiveRecord::Migration[5.2] def change create_table :active_storage_blobs, if_not_exists: true do |t| t.string :key, null: false t.string :filename, null: false t.string :content_type t.text :metadata t.bigint :byte_size, null: false t.string :checksum, null: false t.datetime :created_at, null: false t.index [ :key ], unique: true end create_table :active_storage_attachments, if_not_exists: true do |t| t.string :name, null: false t.references :record, null: false, polymorphic: true, index: false t.references :blob, null: false t.datetime :created_at, null: false t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true t.foreign_key :active_storage_blobs, column: :blob_id end end end
改完之后重新执行迁移就行。
4. 检查迁移执行状态
你也可以先看看这个迁移的状态,确认它是不是已经被标记为执行过了:
rails db:migrate:status
如果状态显示up,但表是之前手动创建的,那你完全不用再跑迁移;如果状态是down但表已经存在,可以手动把迁移标记为已执行:
rails db:migrate:up VERSION=20170806125915
(注意把VERSION换成你迁移文件名里的那个版本号)
补充的问题信息
你的环境配置:
- Rails版本:5.2.0
- activerecord-oracle_enhanced-adapter版本:5.2.0
- ruby-oci8版本:2.2.6.1
- Ruby版本:2.6.0
- Oracle数据库版本:10.2.0.1.0
你遇到的完整错误信息:
ActiveRecord::StatementInvalid: OCIError: ORA-00955: name is already used by an existing object: CREATE TABLE "ACTIVE_STORAGE_BLOBS" ("ID" NUMBER(38) NOT NULL PRIMARY KEY, "KEY" VARCHAR2(255) NOT NULL, "FILENAME" VARCHAR2(255) NOT NULL, "CONTENT_TYPE" VARCHAR2(255), "METADATA" CLOB, "BYTE_SIZE" NUMBER(19) NOT NULL, "CHECKSUM" VARCHAR2(255) NOT NULL, "CREATED_AT" TIMESTAMP NOT NULL)
你使用的迁移文件:
# This migration comes from active_storage (originally 20170806125915) class CreateActiveStorageTables < ActiveRecord::Migration[5.2] def change create_table :active_storage_blobs do |t| t.string :key, null: false t.string :filename, null: false t.string :content_type t.text :metadata t.bigint :byte_size, null: false t.string :checksum, null: false t.datetime :created_at, null: false t.index [ :key ], unique: true end create_table :active_storage_attachments do |t| t.string :name, null: false t.references :record, null: false, polymorphic: true, index: false t.references :blob, null: false t.datetime :created_at, null: false t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true t.foreign_key :active_storage_blobs, column: :blob_id end end end
内容的提问来源于stack exchange,提问作者Vishal Pandey

