Rails 应用程序可以管理数据库主键 table 序列值吗?
Can database primary key table sequence values be managed by Rails application?
我想根据业务逻辑设置新记录的主键,不需要序列号和触发器等数据库工具,并且独立于现有table数据(例如选择最大值。)初始化变量并增加它或以其他方式使用业务逻辑对每个新记录进行操作都很好,但是我如何在应用程序重新启动时保留该值? (如果这是一个简单到令人尴尬的操作,请善待。)
编辑: 我想我现在可以更好地提出这个问题了。假设我说服我的 DBA 重新定义我的 table,以便为 UUID 添加一个列,然后我们进行必要的更改以正确使用主键。这并没有得到很好的接受,因为即使数据库 tables 可以定义得更好,但人们对进行如此重大的更改感到非常恐惧。以及其他原因。但是假设我们修改了 table 列和数据。
现在假设以前用作主键的列值是一个五位数,我们必须保留此值并将其作为用户认为的“主键”呈现给用户。当然索引该列,将值显示为记录 ID。他们不必了解它不是主键,他们只需要将其视为识别记录的方式即可。业务需求表明该字段的值应该是唯一的、松散顺序的但容忍值之间的差距。对客户来说非常重要的是,他们的表单和视图将此值显示为标识符。我想再次通过业务逻辑管理该值,独立于 table 序列和触发器。可以吗?看似简单的事情,却被不合逻辑的思路搞得头晕目眩。
我不能 100% 确定您要做什么。手动将主键添加到 tables 似乎是个坏主意。
您可以做的 3 件事是 1) 从像 98765 这样的高数字开始索引,或者像这样从 0 开始索引
class CreateReports < ActiveRecord::Migration[6.1]
def self.up
create_table :reports do |t|
...
end
execute("ALTER TABLE reports AUTO_INCREMENT = 98765;")
end
您的号码仍然是连续的,所以 98766、98767、98768、98769 等等。
选项 2 是使用 UUID
我喜欢的设置方式是这样的。
rails g migration enable_uuid
# config/db/migrate/..._enable_uuid.rb
class EnableUuid < ActiveRecord::Migration[6.0]
def change
enable_extension 'pgcrypto'
end
end
将 UUID 设置为默认主键类型
# config/initializers/generators.rb
Rails.application.config.generators do |g|
g.orm :active_record, primary_key_type: :uuid
end
现在您的下一次迁移应该如下所示
rails g migration CreateReports
# config/db/migrate/create_post_with_uuid.rb
class CreateReports < ActiveRecord::Migration[6.0]
def change
create_table :reports, id: :uuid do |t|
...
end
end
end
当你Report.first.id
你应该看到这样的东西#“8485ceca-3a85–41e7-b86e-6b6d93dc4e8b”
选项 3 是你可以创建一个没有主键的 table
像这样
create_table :reports, :id => false do |t|
t.bigint :id
...
end
现在您可以自己管理您的 ID。
我会为 uniqness
设置一个模型约束
希望对您有所帮助。
这是一个 X&Y 问题。
在关系数据库中,主键并不是真正用于在外部识别记录。主键是您的数据库将表链接在一起的方式。
你的主键应该是在数据库中生成的,are very compelling arguments for why it should be a surrogate key里面有完全独立于记录数据的。主要的是简单性、中立性和与业务逻辑变化的分离。
您的模型实际上可以有任意数量的标识符,它们只是可用于查找记录的唯一列。例如可敬的鼻涕虫:
/posts/vanity-urls-for-idiots
在这个假设的博客应用程序中,我们正在查找 post 通过标题生成的列别名:
def show
@post = Post.find_by!(slug: params[:id])
end
Rails 中确实没有任何内容可以防止您在想使用其他标识符时不向外部公开主键。您可能需要在模型中定义 #to_param
方法以避免无意中暴露它们。
您可以很好地在您的应用程序中生成任意数量的标识符,如果需要,您实际上可以使用您的数据库生成序列,甚至可以使用完全外部的标识符,例如来自 OAuth 提供商的 UID。
对我的问题的明确回答使我的 DBA 和我自己放弃了在通过应用程序逻辑插入新记录时以编程方式生成主键的方法。谢谢大家帮忙确定是的,可以做,但是不应该做。
我想根据业务逻辑设置新记录的主键,不需要序列号和触发器等数据库工具,并且独立于现有table数据(例如选择最大值。)初始化变量并增加它或以其他方式使用业务逻辑对每个新记录进行操作都很好,但是我如何在应用程序重新启动时保留该值? (如果这是一个简单到令人尴尬的操作,请善待。)
编辑: 我想我现在可以更好地提出这个问题了。假设我说服我的 DBA 重新定义我的 table,以便为 UUID 添加一个列,然后我们进行必要的更改以正确使用主键。这并没有得到很好的接受,因为即使数据库 tables 可以定义得更好,但人们对进行如此重大的更改感到非常恐惧。以及其他原因。但是假设我们修改了 table 列和数据。
现在假设以前用作主键的列值是一个五位数,我们必须保留此值并将其作为用户认为的“主键”呈现给用户。当然索引该列,将值显示为记录 ID。他们不必了解它不是主键,他们只需要将其视为识别记录的方式即可。业务需求表明该字段的值应该是唯一的、松散顺序的但容忍值之间的差距。对客户来说非常重要的是,他们的表单和视图将此值显示为标识符。我想再次通过业务逻辑管理该值,独立于 table 序列和触发器。可以吗?看似简单的事情,却被不合逻辑的思路搞得头晕目眩。
我不能 100% 确定您要做什么。手动将主键添加到 tables 似乎是个坏主意。
您可以做的 3 件事是 1) 从像 98765 这样的高数字开始索引,或者像这样从 0 开始索引
class CreateReports < ActiveRecord::Migration[6.1]
def self.up
create_table :reports do |t|
...
end
execute("ALTER TABLE reports AUTO_INCREMENT = 98765;")
end
您的号码仍然是连续的,所以 98766、98767、98768、98769 等等。
选项 2 是使用 UUID
我喜欢的设置方式是这样的。
rails g migration enable_uuid
# config/db/migrate/..._enable_uuid.rb
class EnableUuid < ActiveRecord::Migration[6.0]
def change
enable_extension 'pgcrypto'
end
end
将 UUID 设置为默认主键类型
# config/initializers/generators.rb
Rails.application.config.generators do |g|
g.orm :active_record, primary_key_type: :uuid
end
现在您的下一次迁移应该如下所示
rails g migration CreateReports
# config/db/migrate/create_post_with_uuid.rb
class CreateReports < ActiveRecord::Migration[6.0]
def change
create_table :reports, id: :uuid do |t|
...
end
end
end
当你Report.first.id
你应该看到这样的东西#“8485ceca-3a85–41e7-b86e-6b6d93dc4e8b”
选项 3 是你可以创建一个没有主键的 table 像这样
create_table :reports, :id => false do |t|
t.bigint :id
...
end
现在您可以自己管理您的 ID。 我会为 uniqness
设置一个模型约束希望对您有所帮助。
这是一个 X&Y 问题。
在关系数据库中,主键并不是真正用于在外部识别记录。主键是您的数据库将表链接在一起的方式。
你的主键应该是在数据库中生成的,are very compelling arguments for why it should be a surrogate key里面有完全独立于记录数据的。主要的是简单性、中立性和与业务逻辑变化的分离。
您的模型实际上可以有任意数量的标识符,它们只是可用于查找记录的唯一列。例如可敬的鼻涕虫:
/posts/vanity-urls-for-idiots
在这个假设的博客应用程序中,我们正在查找 post 通过标题生成的列别名:
def show
@post = Post.find_by!(slug: params[:id])
end
Rails 中确实没有任何内容可以防止您在想使用其他标识符时不向外部公开主键。您可能需要在模型中定义 #to_param
方法以避免无意中暴露它们。
您可以很好地在您的应用程序中生成任意数量的标识符,如果需要,您实际上可以使用您的数据库生成序列,甚至可以使用完全外部的标识符,例如来自 OAuth 提供商的 UID。
对我的问题的明确回答使我的 DBA 和我自己放弃了在通过应用程序逻辑插入新记录时以编程方式生成主键的方法。谢谢大家帮忙确定是的,可以做,但是不应该做。