【问题标题】:ActiveRecord::StatementInvalid SQLite3::SQLException: no such column: true:ActiveRecord::StatementInvalid SQLite3::SQLException:没有这样的列:true:
【发布时间】:2011-08-11 17:17:44
【问题描述】:

我想让@messages 返回@folder.messages,其中“已删除”列的值不等于true。我不确定为什么这会一直抛出 SQLException。我想我没有正确格式化删除的属性,但我不确定如何修复它。

任何帮助将不胜感激。提前致谢。

错误信息:

ActiveRecord::StatementInvalid in MailboxController#index  
SQLite3::SQLException: no such column: true: SELECT     "message_copies".* FROM       "message_copies"  WHERE     ("message_copies".folder_id = 1) AND (deleted != true)  

应用程序跟踪:

app/controllers/mailbox_controller.rb:14:in `show'  
app/controllers/mailbox_controller.rb:5:in `index'  

邮箱控制器.rb

1   class MailboxController < ApplicationController  
2     def index  
3       current_user = User.find(session[:user_id])  
4       @folder = Folder.where("user_id = #{current_user.id}").first  
5       show  
6       render :action => "show"  
7     end
8  
9     def show  
10      current_user = User.find(session[:user_id])  
11      @folder = Folder.where("user_id = #{current_user.id}").first  
12      @msgs = @folder.messages  
13      @ms = @msgs.where("deleted != true")  
14      @messages = @ms.all.paginate :per_page => 10,  
15                 :page => params[:page], :include => :message,  
16                 :order => "messages.created_at DESC"  
17    end  
18  end  

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 sqlite sqlexception sqlite3-ruby


    【解决方案1】:

    SQLite 使用 C 风格 boolean values:

    SQLite 没有单独的布尔存储类。相反,布尔值存储为整数 0(假)和 1(真)。

    所以,当你这样说时:

    deleted != true
    

    SQLite 不知道 true 是什么,因此它假定您正在尝试引用另一个列名。

    处理此问题的正确方法是让 AR 将您的 Ruby 布尔值转换为 SQLite 布尔值(如 Tam 和 fl00r 的答案)。不过,我认为知道自己做错了什么很有用。

    更新:如果你想检查非真deleted 并包含NULL,那么你会想要这个:

    @ms = @msgs.where("deleted != ? OR deleted IS NULL", true)
    

    或者更好的是,根本不允许在deleted 中使用NULL。你不应该允许 NULL 是任何列,除非你绝对必须这样做(ActiveRecord 的可空性默认值与它应该是完全相反的)。 SQL NULL 是一种奇怪的野兽,您总是必须特别对待它,最好不要允许它,除非您需要列的“不存在”或“未指定”值。

    【讨论】:

    • 我认为它存储了t/f 对。但我可能是错的:)。但是现在我查看了您的链接-我错了:) 但是有人存储t/f。绝对!
    • 感谢您的解释。这很有帮助。只是为了确保我正确理解 sql...它如何处理 nil 值?通过说 != 1 (true),它还会返回具有 nil 值的行吗?再次感谢。
    • 只需将此工作传递给 Rails:@msgs.where("deleted != ?", nil)。这就像 sql IS NULL 条件
    • 我正在尝试返回已删除 = false 且已删除 = nil 的行。我试过 @msgs.where(["deleted = ?", nil] || ["deleted = ?", false]) 但它仍然没有返回已删除为空的行。
    • @fl00r: 你确定它会重写 SQL sn-p 吗?我刚刚通过 AR3 代码进行了快速跟踪,我看到了类似 statement.gsub('?') 的内容,但没有任何东西会将 = 更改为 IS 作为特殊情况。我认为发送{ :deleted =&gt; nil } 会起作用。
    【解决方案2】:
    @ms = @msgs.where("deleted != ?", true) 
    # OR
    @ms = @msgs.where(:deleted => false) 
    

    true 对于不同的数据库是不同的。在某些情况下它是t/f 值,在某些情况下是true/false,因此您应该或将其放在引号中并确保它是否适合您的特定数据库,或者您应该将其排除在您的 sql 之外,以便 Rails 执行为你工作。

    UPD

    如果deletedNULL。第一的。 将已删除字段默认设置为 false。二、如何用AR找到它:

    @ms = @msgs.where("deleted = ? OR deleted = ?", false, nil)
    # wich won't work, Thanks to @mu is too short
    @ms = @msgs.where("deleted = ? OR deleted IS NULL", false)
    

    【讨论】:

      【解决方案3】:

      试试

      @ms = @msgs.where(["deleted != ?",true])
      

      【讨论】:

      • 好吧,它不再抛出错误,所以这很好。但它仍然没有返回我想要的结果。还有一个问题,正如语句所写...我假设这也应该返回未设置“已删除”的值(即它不等于真值或假值)我是否正确假设?
      • 这个只会让你得到真实的。如果你想返回那些为空的,那么做类似的事情:@ms = @msgs.where(["deleted is NULL OR deleted != ?",true])
      猜你喜欢
      • 2013-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-24
      • 2015-10-08
      • 2016-12-08
      • 1970-01-01
      相关资源
      最近更新 更多