ruby-on-rails-3 - 对于 Rails 3.2.16 中的 Postgres,序列 "setval"操作与 "nextval"的工作方式不同

标签 ruby-on-rails-3 postgresql pg

我有一个模型,可以使用 pg gem 将数据直接加载到数据库中。它通过动态创建 CSV 文件并通过调用将值分配给 id 字段来实现此目的:

self.class.select("nextval('apps_id_seq'::regclass)").first['nextval']

to_csv 实例方法中。

这在生产中效果很好。但是,我正在填写一些测试,如果首先运行此测试,或者单独运行此测试,它会失败,因为数据库刚刚被数据库清理器 gem 和序列重置被重置。但它们没有给出起始值。

Postgres 文档说您可以对相关序列调用 setval 来进行设置。假设我想将其设置为从 1 开始,以便下次调用 nextval 时,它将返回 1:

select setval('apps_id_seq'::regclass, 1, false);

但我不能像上面调用 nextval 那样调用它,因为它根本不起作用。它返回 nil,并且不设置序列。

我尝试过的任何事情都没有迭代:

self.class.select("setval('apps_id_seq'::regclass)").first
App.connection.execute("select setval('apps_id_seq'::regclass,1,false)")
ActiveRecord::Base.connection.execute("select setval('apps_id_seq'::regclass,1)")
ActiveRecord::Base.connection.execute("select setval('apps_id_seq'::regclass,1,false)")
ActiveRecord::Base.connection.execute("select setval('apps_id_seq'::regclass,1,false)")

它们的任何组合都不起作用,它只是拒绝起作用。我不知道这是否是 pg gem 问题。

更新

这些语句在开发模式下工作:

App.select("setval('apps_id_seq'::regclass,1)").first

和:

App.select("nextval('apps_id_seq'::regclass)").first

然而,它们在测试中都不起作用。

但是,这些语句确实可以在测试模式下工作:

ActiveRecord::Base.connection.execute("select setval('apps_id_seq'::regclass,1,false)").first

和:

ActiveRecord::Base.connection.execute("select nextval('apps_id_seq'::regclass)").first

据我所知,这两种环境中的唯一区别是一种环境有数据,而另一种环境没有数据。我的测试数据库是使用 rake db:test:preparestructure.sql 文件创建的。

最佳答案

无论序列附加到的表中是否有数据,

setvalnextval 都会起作用。序列可以被创建和递增,甚至无需与现有表的列相关联。当您使用 Model.select 执行原始 SQL 时,ActiveRecord 会为您正在使用的模型的表生成带有 from 子句的 SQL:

> App.select("setval('apps_id_seq'::regclass,1)").first

  SELECT nextval('apps_id_seq'::regclass)
  FROM "apps" ORDER BY "apps"."id" ASC LIMIT 1'

=> nil

因为apps表中没有记录,所以setval函数永远不会被执行。这就是为什么直接使用连接时相同的选择可以工作,因为选择没有无关的 from 子句:

> ActiveRecord::Base.connection.execute("SELECT setval('apps_id_seq'::regclass, 1)").first

  SELECT setval('apps_id_seq'::regclass, 1)

=> {"setval"=>"1"}

使用此形式执行 SQL,以便确保始终对 setval 函数进行求值。

关于ruby-on-rails-3 - 对于 Rails 3.2.16 中的 Postgres,序列 "setval"操作与 "nextval"的工作方式不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21146760/

相关文章:

ruby-on-rails-3.1 - 无法推送应用程序 Heroku - 无法通过 Bundler 安装 gems

ruby-on-rails - 使用 Rails 中的回形针上传到谷歌驱动器

ruby-on-rails-3 - 如何允许异常在 rspec 请求规范中冒泡

ruby-on-rails - 使用 twitter 设计/omniauth 登录 - 验证失败 : email can't be blank

ruby - 如何检查 Ruby 中是否已存在准备好的语句?

ruby-on-rails - Postgresql 适配器 (pg) : could not connect to server

ruby-on-rails - 在 FreeBsd 中配置 Ruby On Rails 3

java - jOOQ - 选择查询数组

visual-studio - 如何修复 psqlodbc 驱动程序中的缓冲区溢出

postgresql - 一次更新多行(postgres)