Rails:为什么添加唯一约束会删除结构.sql文件和数据库中的索引

Rails: Why does adding unique constraint removes the index in structure.sql file and db

提问人:svelandiag 提问时间:8/5/2023 最后编辑:svelandiag 更新时间:8/5/2023 访问量:52

问:

最初,此问题被标记为重复:Postgres 唯一约束与索引

但我不问唯一约束与唯一约束的区别 索引,这就是为什么我更新了问题标题以使其更清晰。

我想知道为什么添加使用唯一索引的唯一约束只会删除索引,让我详细解释一下,我有以下迁移:

class AddUniqueIndexOnNamesForProgramsSuppliersCollections < ActiveRecord::Migration[5.2]
  disable_ddl_transaction!

  def up
    execute("CREATE UNIQUE INDEX CONCURRENTLY idx_supplier_company_id_and_name_unique ON public.suppliers USING btree (company_id, name);")
    execute("CREATE UNIQUE INDEX CONCURRENTLY idx_programs_company_id_and_name_unique ON public.programs USING btree (company_id, name);")
    execute("CREATE UNIQUE INDEX CONCURRENTLY idx_collections_supplier_id_and_name_unique ON public.collections USING btree (supplier_id, name);")
  end

  def down
    remove_index :suppliers, name: :idx_supplier_company_id_and_name_unique
    remove_index :programs, name: :idx_programs_company_id_and_name_unique
    remove_index :collections, name: :idx_collections_supplier_id_and_name_unique
  end
end

当我运行上述迁移时,我会将索引添加到我的文件中。然后我还有这个其他迁移:structure.sql

class AddUniqueConstraintsOnNamesForProgramsSuppliersCollections < ActiveRecord::Migration[5.2]
  disable_ddl_transaction!

  def up
    sql = <<~END_OF_SQL
      ALTER TABLE public.suppliers ADD CONSTRAINT supplier_company_id_and_name_unique UNIQUE USING INDEX idx_supplier_company_id_and_name_unique;
      ALTER TABLE public.programs ADD CONSTRAINT programs_company_id_and_name_unique UNIQUE USING INDEX idx_programs_company_id_and_name_unique;
      ALTER TABLE public.collections ADD CONSTRAINT collections_supplier_id_and_name_unique UNIQUE USING INDEX idx_collections_supplier_id_and_name_unique;
    END_OF_SQL

    execute(sql)
  end

  def down
    sql = <<~END_OF_SQL
      ALTER TABLE public.suppliers DROP CONSTRAINT supplier_company_id_and_name_unique;
      ALTER TABLE public.programs DROP CONSTRAINT programs_company_id_and_name_unique;
      ALTER TABLE public.collections DROP CONSTRAINT collections_supplier_id_and_name_unique;
    END_OF_SQL
    execute(sql)
  end
end

当我运行第二个迁移索引时,会从我的文件和数据库中删除并添加约束,所以我的猜测是它正在用约束替换索引,但我想两者兼而有之,有什么想法吗?structure.sql

SQL Ruby-on-Rails Ruby PostgreSQL ActiveRecord

评论

1赞 Daniel 8/5/2023
本题的标题在被标记为重复后被编辑。我认为原来的标题让它看起来像是重复的,但问题的主体实际上是在问一些不同的东西。可能值得考虑重新开放它。
4赞 Frank Heikens 8/5/2023
从手册中: .查看 postgresql.org/docs/current/sql-altertable.htmlIf a constraint name is provided then the index will be renamed to match the constraint name. Otherwise the constraint will be named the same as the index.
1赞 smathy 8/5/2023
实际上,我认为我链接的骗子也回答了这个问题。原因在于,由于唯一约束使用/要求索引作为其实现的一部分,因此添加约束根本不会删除索引。PG 开发人员可能得出这样的结论:如果约束存在,那么显示索引注释是多余的,并且当人们试图删除索引并收到有关需要它的约束的错误时会导致混淆,因此一旦添加了约束,则索引将不再显示
1赞 svelandiag 8/5/2023
@smathy如果是这样的话,为什么当我尝试删除索引时,它说它不存在?PG::UndefinedObject: ERROR: index "idx_supplier_company_id_and_name_unique" does not exist
1赞 smathy 8/5/2023
正如我所提到的,因为一旦你创建了约束,就会导致人们独立删除索引的混乱(因为约束需要后台的索引)。

答:

0赞 Laurenz Albe 8/5/2023 #1

PostgreSQL 中的一条规则是约束的名称与实现它的索引的名称相同。

所以如果你写

ALTER TABLE tab ADD UNIQUE USING INDEX abc;

约束将被调用,如果你将abc

ALTER TABLE tab ADD CONSTRAINT def UNIQUE USING INDEX abc;

索引将重命名为 。abcdef

评论

0赞 svelandiag 12/19/2023
有关上述问题的评论中的更多背景和详细信息。