为何PostgreSQL查询返回NULL而非预期boolean?如何返回明确t/f?
问题
我正在开发一个Web应用,发现某条查询返回了NULL,但我预期得到的是boolean类型,数据库显示返回类型确实是boolean。查文档得知PostgreSQL将NULL视为未知布尔值,但我困惑为何<=运算符会返回t/NULL而非t/f。
数据库版本
执行查询:
select version();
结果:
| version |
|---|
| PostgreSQL 13.13 (Debian 13.13-0+deb11u1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit |
执行的SQL查询
SELECT a.email_verified_at <= NOW() AS "emailVerified", pg_typeof(a.email_verified_at <= NOW()) AS "emailVerifiedType", pg_typeof((a.email_verified_at <= NOW())::boolean) AS "emailVerifiedType2" FROM profiles AS p INNER JOIN accounts AS a ON p.id = a.profile_id;
查询结果
| emailVerified | emailVerifiedType | emailVerifiedType2 |
|---|---|---|
| boolean | boolean | |
| t | boolean | boolean |
| boolean | boolean |
请问如何让PostgreSQL返回明确的t/f给我的应用?
解决方案
PostgreSQL遵循SQL三值逻辑规则:只要运算涉及NULL,结果就会是NULL。当email_verified_at字段为NULL时,NULL <= NOW()的结果自然是NULL——数据库没法判断一个“未知”的时间是否小于等于当前时间。
要让结果始终返回明确的t或f,可以用COALESCE函数把NULL替换成业务需要的布尔值。比如把NULL视为“未验证”(即false),修改后的SQL如下:
SELECT COALESCE(a.email_verified_at <= NOW(), false) AS "emailVerified", pg_typeof(COALESCE(a.email_verified_at <= NOW(), false)) AS "emailVerifiedType" FROM profiles AS p INNER JOIN accounts AS a ON p.id = a.profile_id;
COALESCE会返回传入参数里第一个非NULL的值:如果a.email_verified_at <= NOW()计算结果是t或f,就返回原本的结果;如果是NULL,就返回你指定的false。
如果业务需要把NULL视为true,只需要把SQL里的false改成true即可。
内容的提问来源于stack exchange,提问作者ravinggenius
相关产品推荐
相关产品推荐

