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:
引用标识符也使其区分大小写,而未引用的名称总是折叠为小写。例如,标识符
FOO
、foo
和"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
后,IP
、Username
、Reason
和 Length
将遇到同样的问题:您必须在任何引用它们的 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 报告找不到存在的列的主要内容,如果未能解决你的问题,请参考以下文章