Rails 5.1中.any?与.exists?触发未知列错误问题求助
Rails复合主键模型调用exists?/any?报错的解决方案
问题梳理
- 预存在的SQL Server数据库表
test_table使用复合主键,schema.rb定义:create_table "test_table", primary_key: ["somthing", "somthing1"]... TestTable.all可正常获取数据,但调用TestTable.all.exists?或.any?时触发SQL语法错误:ActiveRecord::StatementInvalid (TinyTds::Error: Invalid column name "somthing", "something1".: EXEC sp_executesql N'SELECT 1 AS one FROM [testtable] ORDER BY [testtable].["something", "somthing1"] ASC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY', N'@0 int', @0 = 1)- 已尝试
composite_primary_keysgem,并在模型中设置self.primary_keys = :something, :something1,但问题未解决
解决方案
1. 修正主键名称拼写错误
从报错信息看,schema里的主键是somthing(缺少字母e),但错误SQL里出现了something,两者拼写不一致。确保模型中的主键定义和数据库、schema.rb完全匹配:
class TestTable < ApplicationRecord self.primary_keys = :somthing, :somthing1 # 严格对应schema里的拼写 end
2. 确保composite_primary_keys版本适配Rails
这个gem对Rails版本兼容性要求高,比如Rails 7需要使用最新稳定版,在Gemfile中指定正确版本:
gem 'composite_primary_keys', '~> 14.0' # 适配Rails 7,根据你的Rails版本调整
执行bundle install后重启 Rails 服务。
3. 手动修正schema.rb的主键定义
预存在的数据库通过schema:dump生成的配置可能存在偏差,手动确认schema.rb中的主键定义,确保列名、顺序和数据库完全一致:
create_table "test_table", primary_key: ["somthing", "somthing1"], force: :cascade do |t| # 其他列定义... end
4. 临时重写exists?方法(应急方案)
如果以上方法都无效,可以针对该模型手动实现exists?,绕过Rails的复合主键生成逻辑:
class TestTable < ApplicationRecord self.primary_keys = :somthing, :somthing1 def self.exists?(conditions = :none) return connection.select_value("SELECT 1 FROM #{table_name} LIMIT 1").present? if conditions == :none # 带条件的情况,手动构造正确的SQL relation = where(conditions) connection.select_value("SELECT 1 FROM #{table_name} #{relation.where_clause} LIMIT 1").present? end end
5. 检查模型表名映射
确保模型和数据库表名对应正确,若表名和模型名不符合Rails约定,手动指定:
class TestTable < ApplicationRecord self.table_name = 'test_table' self.primary_keys = :somthing, :somthing1 end
内容的提问来源于stack exchange,提问作者sneakyfishies
相关产品推荐
相关产品推荐

