使用Rails,我如何设置我的主键不是一个整数类型的列? [英] Using Rails, how can I set my primary key to not be an integer-typed column?
问题描述
我使用Rails迁移来管理数据库模式,我创建了一个简单的表,其中我想使用非整数值作为主键(特别是字符串)。为了抽象出我的问题,让我们假设有一个表 employees
,其中雇员通过字母数字字符串来标识。 134SNW
。
I'm using Rails migrations to manage a database schema, and I'm creating a simple table where I'd like to use a non-integer value as the primary key (in particular, a string). To abstract away from my problem, let's say there's a table employees
where employees are identified by an alphanumeric string, e.g. "134SNW"
.
我已经尝试在迁移中创建表格,如下所示:
I've tried creating the table in a migration like this:
create_table :employees, {:primary_key => :emp_id} do |t|
t.string :emp_id
t.string :first_name
t.string :last_name
end
这给我的是什么似乎完全忽略了 t.string:emp_id
行,并使它成为一个整数柱。有没有其他方法来让rails生成PRIMARY_KEY约束(我使用PostgreSQL)为我,而不必写在执行
调用?
What this gives me is what seems like it completely ignored the line t.string :emp_id
and went ahead and made it an integer column. Is there some other way to have rails generate the PRIMARY_KEY constraint (I'm using PostgreSQL) for me, without having to write the SQL in an execute
call?
注意:我知道最好不要使用字符串列作为主键,所以请没有答案只是说添加一个整数主键。我可以添加一个,但这个问题仍然有效。
NOTE: I know it's not best to use string columns as primary keys, so please no answers just saying to add an integer primary key. I may add one anyway, but this question is still valid.
推荐答案
不幸的是,我确定它不可能不使用执行
。
Unfortunately, I've determined it's not possible to do it without using execute
.
通过检查ActiveRecord源代码,我们可以找到 create_table
的代码:
By examining the ActiveRecord source, we can find the code for create_table
:
在 schema_statements.rb code>
:
In schema_statements.rb
:
def create_table(table_name, options={})
...
table_definition.primary_key(options[:primary_key] || Base.get_primary_key(table_name.to_s.singularize)) unless options[:id] == false
...
end
所以我们可以看到,当你尝试在 create_table
选项,它创建具有指定名称的主键(或者如果没有指定名称,则 id
)。它通过调用可以在表定义块中使用的相同方法来执行此操作: primary_key
。
So we can see that when you try to specify a primary key in the create_table
options, it creates a primary key with that specified name (or, if none is specified, id
). It does this by calling the same method you can use inside a table definition block: primary_key
.
href =https://github.com/rails/rails/blob/a63f7a136401b59db52fb802180f6c9793d83bc2/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb#L89 =noreferrer> schema_statements.rb
:
In schema_statements.rb
:
def primary_key(name)
column(name, :primary_key)
end
这只是创建一个指定名称为:primary_key
。这在标准数据库适配器中设置如下:
This just creates a column with the specified name of type :primary_key
. This is set to the following in the standard database adapters:
PostgreSQL: "serial primary key"
MySQL: "int(11) DEFAULT NULL auto_increment PRIMARY KEY"
SQLite: "INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL"
解决方法
因为我们坚持使用这些作为主键类型,我们必须使用 execute
创建不是整数的主键(PostgreSQL的 serial
是使用序列的整数):
The workaround
Since we're stuck with these as the primary key types, we have to use execute
to create a primary key that is not an integer (PostgreSQL's serial
is an integer using a sequence):
create_table :employees, {:id => false} do |t|
t.string :emp_id
t.string :first_name
t.string :last_name
end
execute "ALTER TABLE employees ADD PRIMARY KEY (emp_id);"
并且 Sean McCleary提到,你的ActiveRecord模型应该设置主键 set_primary_key
:
And as Sean McCleary mentioned, your ActiveRecord model should set the primary key using set_primary_key
:
class Employee < ActiveRecord::Base
set_primary_key :emp_id
...
end
这篇关于使用Rails,我如何设置我的主键不是一个整数类型的列?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!