PostgreSQL时间戳比较查询未过滤结果及列名大小写疑问
解决PostgreSQL时间戳比较查询失效的问题
问题根源分析
你写的查询里犯了一个关键语法错误:把列名createdAt用单引号包裹了。在PostgreSQL中,单引号是用来定义字符串字面量的,而不是引用数据库对象(列、表)的标识符。
所以你的WHERE子句实际上是在做:
'createdAt' >= '2017-08-01 23:25:53+00'
这是两个字符串的比较,'createdAt'这个字符串本身肯定大于你指定的时间字符串,所以这个条件永远为true;再加上'createdAt' is not null——同样,字符串字面量永远不是null,这个条件也永远为true。两个永真条件叠加,自然会返回表中所有记录,包括createdAt为null的行。
正确的查询写法
因为你的列名是驼峰式的createdAt,而PostgreSQL对带大小写的标识符有严格要求:创建时如果用双引号定义了驼峰列名,查询时必须用双引号来引用它(同时表名user是关键字,也需要用双引号包裹)。正确的查询应该是:
select * from "user" where "createdAt" >= '2017-08-01 23:25:53+00' and "createdAt" is not null order by id desc;
关于PostgreSQL标识符大小写的疑问
PostgreSQL的标识符(表名、列名等)区分大小写,但有特殊规则:
- 如果创建对象时没有用双引号,PostgreSQL会自动把标识符转换为小写存储,查询时不管你写大写、小写还是混合大小写,都会被转成小写匹配,比如
createdat和CreatedAt都会匹配到createdat列; - 如果创建对象时用双引号指定了大小写(比如
"createdAt"),那么存储时会保留原大小写,查询时必须用双引号并严格匹配大小写,否则会找不到对应的对象。
这也是为什么你习惯蛇形命名法(比如created_at)时不会遇到这个问题——蛇形命名全小写,不需要双引号就能正常匹配。
内容的提问来源于stack exchange,提问作者Zachary Springer
相关产品推荐
相关产品推荐

