Rails 报告找不到存在的列

Posted

技术标签:

【中文标题】Rails 报告找不到存在的列【英文标题】:Rails reports can't find a column that is there 【发布时间】:2012-05-17 01:49:15 【问题描述】:

我目前正在尝试使用 Rails 对表进行复杂的 WHERE 搜索,问题是我得到了错误:

PG::Error: ERROR:  column "email" does not exist
LINE 1: SELECT "bans".* FROM "bans"  WHERE (Email='' AND IP='' AND (...
                                        ^
: SELECT "bans".* FROM "bans"  WHERE (Email='' AND IP='' AND (Username='NULL' ))

而且我知道该专栏确实存在,并且执行rails dbconsole 会给我以下信息:

Jungle=> select * from bans;
 id | Username | IP | Email | Reason | Length | created_at | updated_at 
----+----------+----+-------+--------+--------+------------+------------
(0 rows)

所以这肯定是在数据库中,有没有人有这方面的经验?

【问题讨论】:

你在使用区分大小写的列名的 postgres 吗? SQL和表中大小写完全一样 嗯,是的,我想它在一个地方,虽然它说缺少的那一列完全低于。 @DaveNewton:那是因为 PostgreSQL 将标识符标准化为小写(即使标准说是大写)。 @muistooshort 啊,明白了。我想它是这样的,但是 +1 以获得很好的答案。 【参考方案1】:

除非引用,否则 SQL 列名不区分大小写,标准规定标识符应规范化为大写,但 PostgreSQL normalizes to lower case:

引用标识符也使其区分大小写,而未引用的名称总是折叠为小写。例如,标识符FOOfoo"foo" 被PostgreSQL 认为是相同的,但"Foo""FOO" 与这三个不同并且彼此不同。 (在 PostgreSQL 中将不带引号的名称折叠为小写与 SQL 标准不兼容,SQL 标准说不带引号的名称应折叠为大写。因此,根据标准,foo 应该等同于 "FOO" 而不是 "foo" . 如果您想编写可移植的应用程序,建议您始终引用特定名称或永远不要引用它。)

您在 SQL 中引用了Email

SELECT "bans".* FROM "bans"  WHERE (Email='' ...

但 PostgreSQL 抱怨 email:

column "email" does not exist

您未引用的Email 被视为email,因为PostgreSQL 将标识符标准化为小写。听起来您通过双引号创建了具有大写名称的列:

create table "bans" (
    "Email" varchar(...)
    ...
)

或使用:Email 来标识迁移中的列。如果在创建列名时引用它,则它不会被规范化为小写(或 SQL 标准大小写中的大写),您必须将其双引号并永远匹配大小写:

SELECT "bans".* FROM "bans"  WHERE ("Email"='' ...

修复 Email 后,IPUsernameReasonLength 将遇到同样的问题:您必须在任何引用它们的 SQL 中将它们全部双引号.

最佳做法是使用小写的列名和表名,这样您就不必一直担心引用内容。我建议您将表修复为使用小写的列名。


顺便说一句,您的 'NULL' 字符串文字:

SELECT "bans".* FROM "bans"  WHERE (Email='' AND IP='' AND (Username='NULL' ))
-- -------------------->------------------>---------->---------------^^^^^^

看起来很奇怪,你确定你不是指"Username" is null'NULL' 字符串文字和 NULL 值是完全不同的东西,您不能使用 =!= 将事物与 NULL 进行比较,您必须使用 is null, is not null, is distinct from, or is not distinct from(取决于您的意图)当 NULL 可能是游戏中。

【讨论】:

谢谢,这正是问题所在,我只是使用标准的 rails 生成模型等,这意味着我现在必须重写和重新打印我的整个 DB 设计文档!无论如何,谢谢你的帮助。 @nekosune:也许杀死所有这些树的罪恶感会帮助你在未来避免这个错误:) 我为树木感到难过,是的,更重要的是,在我开始之前需要完成所有更改才能获得批准,但是这种奇怪行为导致的额外工作需要它。跨度> 遵循 Rails 的约定确实可以避免很多麻烦,否则您会发现混合大小写的名称。 我实际上不知道有关此的 Rails 约定,我真的需要花更多时间学习基础知识。【参考方案2】:

看起来你的错误不是来自测试数据库,但如果是这样,请尝试rake db:test:prepare

一般来说,请注意您有 3 个数据库 - 测试、开发、生产。因此很容易将它们混淆并检查错误。

【讨论】:

【参考方案3】:

我在这里遇到了同样的问题,

但正如mu-is-too-short 所说,可以告诉 PostgreSql 搜索列名时区分大小写。

因此,通过实现此代码,我设法绕过了您面临的相同错误:

Transaction.find(:all,:conditions => ["(date between ?  and ?) AND \"Membership_id\" = ?", Time.now.at_beginning_of_month,  Time.now.end_of_month,membership.id])

注意到列名周围的 \" 符号了吗?嗯.. 尽管很烦人,但这就是解决此问题的方法。

【讨论】:

以上是关于Rails 报告找不到存在的列的主要内容,如果未能解决你的问题,请参考以下文章

Rails - 找不到 JavaScript 运行时?

找不到文件'dataTables/jquery.dataTables' Rails 4

Rails 3 在子目录中运行,找不到资产

Rails 4可安装引擎,找不到文件'jquery'

为啥 Rails 找不到我的资产?

Rails 路线有时找不到错误