Rails Postgresql 多个模式和相同的表名

Posted

技术标签:

【中文标题】Rails Postgresql 多个模式和相同的表名【英文标题】:Rails Postgresql multiple schemas and the same table name 【发布时间】:2012-01-15 16:55:19 【问题描述】:

我有两个不同模式的表,例如 casesevents

在每个模式中我都有基本表

events.basic cases.basic

这些表有关系:

events.basic 有一个cases.basiccases.basic 有很多events.basic

我的尝试失败了:

文件cases_basic.rb

class CasesBasic < ActiveRecord::Base
  set_table_name 'cases.basic'
  set_primary_key 'case_id'
  has_many :Events, :class_name => 'EventsBasic', :foreign_key => 'case_id'
end

文件events_basic.rb

class EventsBasic < ActiveRecord::Base
  set_table_name 'events.basic'
  set_primary_key 'event_id'
  belongs_to :Case, :class_name => 'CasesBasic', :foreign_key => 'case_id'
end

环境: Ruby 1.9.3,Rails 3.1.3gem 'pg'

我需要回答这个问题:

    如何在 Rails Active Record 中处理这种情况? 如何查询这个表? 如何在rake db:schema:dump处理这种情况

编辑:

更改belongs_tohas_many 后(如猫叫建议)我有同样的错误

PGError: ERROR:  column basic.case_id does not exist
LINE 1: ...IN "cases"."basic" ON "cases"."basic"."case_id" = "events"."...
                                                             ^
: SELECT  "events"."basic".* FROM "events"."basic" INNER JOIN "cases"."basic" ON "cases"."basic"."case_id" = "events"."basic"."case_id" LIMIT 3

Rails 生成错误的 SQL。我应该使用一些别名来完成:

SELECT t1.* FROM "events"."basic" t1 INNER JOIN "cases"."basic" t2 ON t1."case_id" = t2."case_id" LIMIT 3


编辑 2: 好的,这是我的错误,我没有在示例数据库中添加 events.basic.case_id 列和外键。 有效!


问题 1 和 2 有效,但我们对 rake db:schema:dump 有疑问,那该怎么办? Rails 仅为公共模式生成模型。

我有很多表和关系,我想生成它们。

【问题讨论】:

您的 :Events:Case 应该是 :events:case 但这可能无法解决问题。 @muistooshort :Events:Case 看起来像别名,在这种情况下不会被带到 SQL 中 我对表格的外观有点困惑,ON "cases"."basic"."case_id" = "events"."basic"."case_id" 连接条件应该是什么样的?其中一张表没有case_id,这是一个问题,如果您手动编写连接条件,您将如何编写? 尝试在您的databases.yaml 中设置schema_search_path: public,events,cases,然后尝试您的rake db:schema:dump 你会得到一个 schema.rb 里面的所有东西,但没有一个表名包含 PostgreSQL 模式前缀,对吧? 【参考方案1】:

我建议使用pg_power gem。它提供了在迁移中创建 PostgreSQL 模式的语法,如下所示:

def change
  drop_schema 'demography'
  create_schema 'politics'
end

并且还负责将模式正确地转储到 schema.rb 文件中。

【讨论】:

【参考方案2】:

[编辑:进一步阅读后,我认为 ActiveRecord 根本不支持多种模式。但我可能是错的。我暂时将这个答案留在这里,尽管几乎可以肯定它是错误的。 (在概念上是对的。但是构建 ActiveRecord 的人可能没有与任何数据库人员交谈,因为数据库人员可能知道什么?)看起来 IBM 在 2008 年就在解决这个问题,但是我不知道这项工作是如何结束的。]

PostgreSQL 在为不同模式中具有相同名称的表设置外键引用时没有任何问题。像这样的代码

class CasesBasic < ActiveRecord::Base
  set_table_name 'cases.basic'
  set_primary_key 'case_id'
  has_many :Events, :class_name => 'EventsBasic', :foreign_key => 'case_id'
end

可能需要模式限定。

现在,cases.basic 表“有很多”事件不是真的,是吗?不,它“有很多”事件。基本。在你的两个课程中进行这种改变,让我们知道它是如何工作的。 (这里没有 Rails,否则我会为你测试它。)

【讨论】:

“但是构建 ActiveRecord 的人可能没有与任何数据库人员交谈,因为数据库人员可能知道什么?”数据库人员知道一些愚蠢的事情,比如引用完整性(Rails 认为这是一个应用程序问题)。 Rails 有很多好主意,ActiveRecord 不是其中之一。 还有 CHECK 约束、函数索引、触发器和其他任何东西,比如 mysql3 不理解的。 是否包含/排除您不想从 SEARCH_PATH 查询的模式并不能解决模式中的表位置问题?另外,您能否通过在要查询的特定模式前面加上前缀来完全限定您的表路径? @BenSimpson:我对 OP 情况的理解是,不,search_path 无济于事,因为每个模式都有同名的表。与 events.basic、cases.basic、other_things.basic 一样。 IMO,那些不是很好的表名,这不是重点。我目前对 Rails 的理解是它不支持 schema.table 语法。这就是为什么我说我的答案几乎肯定是错误的。 @muistooshort:域 (?)。 (不是 Rails 专家。)【参考方案3】:

查看http://blog.jerodsanto.net/2011/07/building-multi-tenant-rails-apps-with-postgresql-schemas/

这描述了如何配置 Rails 应用程序以使用具有多个模式的 Postgres 数据库。他将表格查找比作 Unix 路径的功能,从特定位置开始,然后回退到一般位置。

集成架构路径后,您可以成功查询这些表。 db:schema:dump 将使用您的应用程序喜欢的相同架构优先级读取表。

【讨论】:

感谢您的回复,但不幸的是它没有解决问题,作者在这里使用SET SEARCH_PATH TO schema1,schema2 方法,当您不需要不同模式中的表之间的关系时,它非常适合简单的数据库,并且它不能解决多个架构问题,您无法连接具有相同名称的表。我的系统中有 300 个表,其中许多具有相同的名称。

以上是关于Rails Postgresql 多个模式和相同的表名的主要内容,如果未能解决你的问题,请参考以下文章

使用 PostgreSQL 的模式和 Rails 创建多租户应用程序

跨多个列 PostgreSQL/Rails 的慢速通配符搜索 LIKE

6.PostgreSQL模式Schema

PostgreSQL 相同的触发器函数在 INSERT 上更新到不同的表(使用相同的模式)

PostgreSQL学习总结—— PostgreSQL 模式(SCHEMA)详解

PostgreSQL学习总结—— PostgreSQL 模式(SCHEMA)详解