PostgreSQL时间戳微秒为0时被截断,如何全局统一格式?
我完全懂你的困扰——PostgreSQL默认会把TIMESTAMP末尾的零微秒省略掉,导致输出格式不统一,给PHP解析成DateTime对象添了不必要的麻烦。下面分情况给你靠谱的解决方案:
一、PostgreSQL 12及以上版本(推荐方案)
从PostgreSQL 12开始,官方引入了timestamp_output_format参数,能直接全局控制TIMESTAMP的输出格式:
1. 仅当前会话生效
在psql里执行这条命令,之后当前连接的所有TIMESTAMP查询都会显示完整的6位微秒:
SET timestamp_output_format = 'YYYY-MM-DD HH24:MI:SS.US';
要是想每次打开psql都自动应用这个设置,把这条命令添加到你的~/.psqlrc文件里就好。
2. 全局实例生效(所有连接都用这个格式)
修改PostgreSQL的核心配置文件postgresql.conf,找到或添加以下配置项:
timestamp_output_format = 'YYYY-MM-DD HH24:MI:SS.US'
保存后重启PostgreSQL服务,整个实例的所有客户端连接都会统一输出带完整微秒的TIMESTAMP。
二、PostgreSQL 9.x版本(比如你用的9.5.6)
旧版本没有timestamp_output_format这个参数,你可以试试这些替代方案:
1. 在PHP层面处理(最省心)
其实PHP的DateTime类完全能兼容两种格式,拿到数据库返回的字符串后,直接用format方法转换成你需要的统一格式就行:
// 从数据库获取的可能是截断后的字符串 $dbDateStr = '2018-01-01 00:00:00'; $dateObj = new DateTime($dbDateStr); // 输出带完整微秒的格式 echo $dateObj->format('Y-m-d H:i:s.u'); // 结果:2018-01-01 00:00:00.000000
这个方法不用改任何数据库配置,在PHP端就能搞定格式统一,非常灵活。
2. 用视图包装目标表(数据库端统一输出)
如果必须在数据库层面解决,可以给需要的表创建一个视图,自动格式化TIMESTAMP字段:
CREATE VIEW ts_fail_view AS SELECT to_char(ts, 'YYYY-MM-DD HH24:MI:SS.US') AS ts FROM ts_fail;
之后查询ts_fail_view就能得到带完整微秒的结果,但这个方法只针对单个表,不是全局所有表的通用方案。
3. 配置psql客户端(仅自己用psql查询时生效)
如果只是你自己用psql查询时想看到完整格式,可以在~/.psqlrc中添加:
ALTER ROLE your_username SET datestyle = 'ISO, YMD';
不过这个只能保证日期格式的一致性,还是没法强制显示零微秒,最终还是得配合to_char或者PHP处理。
总结
如果是新版本PostgreSQL,修改timestamp_output_format是最彻底的全局解决方案;如果是旧版本,在PHP端处理格式会更省心,不用折腾数据库配置。
内容的提问来源于stack exchange,提问作者user1068464

