获取 "value "3000002000" 超出整数类型的范围"
Getting "value "3000002000" is out of range for type integer"
我正在使用 Rails 4.2.3 和 PostGre 数据库。我希望我的数据库中的一列存储毫秒数——注意,不是时间戳,而是以毫秒为单位的持续时间。所以我像这样创建了我的专栏
time_in_ms | bigint
但是,当我去 Rails 中存储一个值时,出现以下错误
ActiveRecord::StatementInvalid (PG::NumericValueOutOfRange: ERROR: value "3000002000" is out of range for type integer
: INSERT INTO "my_object_times" ("time_in_ms", "my_object_id", "created_at", "updated_at") VALUES (, , , ) RETURNING "id"):
app/controllers/my_objects_controller.rb:31:in `update'
数字“3000002000”似乎小于该列的最大值(我正在阅读的是“9223372036854775807”),所以我想知道还有什么问题以及如何解决它。
编辑: 为了提供更多信息,在我的 db/schema.rb 文件中,相关列的描述如下...
create_table "my_object_times", force: :cascade do |t|
...
t.integer "time_in_ms", limit: 8
编辑 2: 这是 PSQL
中创建 table 的输出
CREATE TABLE my_object_times (
id integer NOT NULL,
first_name character varying,
last_name character varying,
time_in_ms bigint,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
name character varying,
age integer,
city character varying,
state_id integer,
country_id integer,
overall_rank integer,
age_group_rank integer,
gender_rank integer
);
bigint
是 64 位,而 Rails 是 32 位。
3000002000
大于 2^32
。这就是为什么将其转换为 32 位整数失败并显示 NumericValueOutOfRange
。
编辑: 我刚刚重新阅读了这篇文章,我原来的回答实际上对你的情况没有意义。我确实相信您需要在该专栏之外寻找答案,并手动确认您认为自己知道的关于它状态的每一点。任何细节的添加都将帮助我们找到正确的答案。
设置断点以单步执行请求并查看是否可以发现 integer
create_table "my_object_times", force: :cascade do |t|
...
t.integer "time_in_ms", limit: 8
t.integer
- 在我看来这就是你的罪魁祸首。
...
好吧,我试过了,我最后的想法是它必须与某种 Rails 请求中间件有关,但我不知道具体细节是什么。请求路径中的某些东西认为该列是一个整数。直到现在我才明白 Rails 迁移数据类型是如何工作的,所以我学到了一些东西。 (而且我整天都在钓鱼,所以我会把这一天算作胜利。)祝你好运!
我猜,table my_object_times
可能不是从 schema.rb
文件创建的,或者它可能被其他迁移文件覆盖。因为在迁移文件中限制为 8 的整数列本身就是一个 bigint
。所以你应该交叉检查来自 PG-admin 的 table 定义。如果该列不是 bigInt 则 运行 以下迁移
class ChangeTimeInMsToBigint < ActiveRecord::Migration
def change
execute <<-SQL
ALTER TABLE my_object_times
ALTER COLUMN time_in_ms TYPE bigint USING time_in_ms::bigint
SQL
end
end
我之前遇到过这种情况,当我最初尝试在数据库中创建一个 bigint 字段时,出于某种原因模型认为它是一个整数,即使模式和迁移文件将它指定为大整数。
例如:我有这个迁移文件
class CreateSecureUserTokens < ActiveRecord::Migration
def change
create_table :secure_user_tokens do |t|
t.integer :sso_id, null: false, length: 8
t.string :token, null: false
t.timestamps null: false
end
end
end
注意,它有包含长度:8 的要求,使整数成为 bigint。但是,在我 运行 迁移之后,我遇到了与您相同的问题。最终我只是创建了另一个迁移来尝试解决这个问题,它成功了。这是我用来解决问题的迁移:
class ModifySecureTokensForLargerSsoIdSizes < ActiveRecord::Migration
def change
change_column :secure_user_tokens, :sso_id, :integer, limit: 8
end
end
因此,如果我们更改它以满足您的需求,它将是:
class ObjectTimesBigInt < ActiveRecord::Migration
def change
change_column :my_object_times, :time_in_ms, :integer, limit: 8
end
end
希望对您有所帮助!
-查理
我正在使用 Rails 4.2.3 和 PostGre 数据库。我希望我的数据库中的一列存储毫秒数——注意,不是时间戳,而是以毫秒为单位的持续时间。所以我像这样创建了我的专栏
time_in_ms | bigint
但是,当我去 Rails 中存储一个值时,出现以下错误
ActiveRecord::StatementInvalid (PG::NumericValueOutOfRange: ERROR: value "3000002000" is out of range for type integer
: INSERT INTO "my_object_times" ("time_in_ms", "my_object_id", "created_at", "updated_at") VALUES (, , , ) RETURNING "id"):
app/controllers/my_objects_controller.rb:31:in `update'
数字“3000002000”似乎小于该列的最大值(我正在阅读的是“9223372036854775807”),所以我想知道还有什么问题以及如何解决它。
编辑: 为了提供更多信息,在我的 db/schema.rb 文件中,相关列的描述如下...
create_table "my_object_times", force: :cascade do |t|
...
t.integer "time_in_ms", limit: 8
编辑 2: 这是 PSQL
中创建 table 的输出CREATE TABLE my_object_times (
id integer NOT NULL,
first_name character varying,
last_name character varying,
time_in_ms bigint,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
name character varying,
age integer,
city character varying,
state_id integer,
country_id integer,
overall_rank integer,
age_group_rank integer,
gender_rank integer
);
bigint
是 64 位,而 Rails 是 32 位。
3000002000
大于 2^32
。这就是为什么将其转换为 32 位整数失败并显示 NumericValueOutOfRange
。
编辑: 我刚刚重新阅读了这篇文章,我原来的回答实际上对你的情况没有意义。我确实相信您需要在该专栏之外寻找答案,并手动确认您认为自己知道的关于它状态的每一点。任何细节的添加都将帮助我们找到正确的答案。
设置断点以单步执行请求并查看是否可以发现 integer
create_table "my_object_times", force: :cascade do |t| ... t.integer "time_in_ms", limit: 8
t.integer
- 在我看来这就是你的罪魁祸首。
...
好吧,我试过了,我最后的想法是它必须与某种 Rails 请求中间件有关,但我不知道具体细节是什么。请求路径中的某些东西认为该列是一个整数。直到现在我才明白 Rails 迁移数据类型是如何工作的,所以我学到了一些东西。 (而且我整天都在钓鱼,所以我会把这一天算作胜利。)祝你好运!
我猜,table my_object_times
可能不是从 schema.rb
文件创建的,或者它可能被其他迁移文件覆盖。因为在迁移文件中限制为 8 的整数列本身就是一个 bigint
。所以你应该交叉检查来自 PG-admin 的 table 定义。如果该列不是 bigInt 则 运行 以下迁移
class ChangeTimeInMsToBigint < ActiveRecord::Migration
def change
execute <<-SQL
ALTER TABLE my_object_times
ALTER COLUMN time_in_ms TYPE bigint USING time_in_ms::bigint
SQL
end
end
我之前遇到过这种情况,当我最初尝试在数据库中创建一个 bigint 字段时,出于某种原因模型认为它是一个整数,即使模式和迁移文件将它指定为大整数。
例如:我有这个迁移文件
class CreateSecureUserTokens < ActiveRecord::Migration
def change
create_table :secure_user_tokens do |t|
t.integer :sso_id, null: false, length: 8
t.string :token, null: false
t.timestamps null: false
end
end
end
注意,它有包含长度:8 的要求,使整数成为 bigint。但是,在我 运行 迁移之后,我遇到了与您相同的问题。最终我只是创建了另一个迁移来尝试解决这个问题,它成功了。这是我用来解决问题的迁移:
class ModifySecureTokensForLargerSsoIdSizes < ActiveRecord::Migration
def change
change_column :secure_user_tokens, :sso_id, :integer, limit: 8
end
end
因此,如果我们更改它以满足您的需求,它将是:
class ObjectTimesBigInt < ActiveRecord::Migration
def change
change_column :my_object_times, :time_in_ms, :integer, limit: 8
end
end
希望对您有所帮助! -查理