Rails报告找不到那里的列

我目前正在尝试使用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) 

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

SQL列名称不区分大小写,除非引用,标准说标识符应该标准化为大写,但PostgreSQL标准化为小写 :

引用标识符也会使其区分大小写,而不带引号的名称始终折叠为小写。 例如,PostgreSQL认为标识符FOOfoo"foo"是相同的,但是"Foo""FOO"与这三个和彼此不同。 (在PostgreSQL中将不带引号的名称折叠为小写字母与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 nullis not nullis distinct from ,或is not distinct from (当取决于你的意图时)可能正在运行NULL。

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

一般来说,请注意您有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]) 

注意到在列名称周围的符号?嗯……虽然很烦人,但这是解决这个问题的方法。