填 now()(小写无引号)——Navicat 识别为函数调用,生成 DEFAULT now();类型须选 timestamp with time zone;已有数据需手动 UPDATE 补全;GENERATED 列不支持图形界面配置。
PostgreSQL时间戳默认值在Navicat里填什么才生效
navicat 的「默认值」输入框不是自由文本编辑器,直接写 now() 或 current_timestamp 会当作字符串存进去,导致插入时字段值是字面量,不是实时时间。
必须用 Navicat 特定的表达式语法才能触发 PostgreSQL 的函数调用:
- 填
now()(小写,无引号)——这是最稳妥的选择,Navicat 会识别为函数调用,生成DEFAULT now() - 填
CURRENT_TIMESTAMP(全大写、无括号、无引号)——部分 Navicat 版本支持,但低版本可能失败 - 避免填
'now()'、"now()"、now(缺括号)、NOW()(大写)——这些都会被当作文本或语法错误
需要带时区还是不带?TIMESTAMP WITHOUT TIME ZONE vs TIMESTAMP WITH TIME ZONE
选错类型会导致默认值行为异常:比如你设了 now() 默认值,但列类型是 TIMESTAMP WITHOUT TIME ZONE,PostgreSQL 会悄悄丢掉时区信息,后续按本地时区解释时间,查出来可能比实际晚 8 小时。
真实场景建议:
- 记录业务发生时间(如订单创建、日志打点)→ 用
TIMESTAMP WITH TIME ZONE,配合now()默认值,保证跨时区一致 - 只做日期范围过滤、且系统严格单一时区 → 可用
TIMESTAMP WITHOUT TIME ZONE,但得确保应用层和数据库都用同一时区启动 - Navicat 建表时,在「类型」下拉里选
timestamp with time zone,别手误选成timestamp(后者是 without 的缩写)
修改已有字段加默认值,Navicat 会静默跳过
对已存在数据的表,用 Navicat「设计表」界面给时间戳字段加默认值,点击保存后,Navicat 默认只执行 ALTER TABLE ... ALTER COLUMN ... SET DEFAULT ...,不会更新老数据。结果就是:新插入行有时间,老数据仍是 NULL 或旧值。
如果真要补全历史记录:
- 先手动执行
UPDATE table_name SET created_at = now() WHERE created_at IS NULL; - 再用 Navicat 加默认值,或直接运行
ALTER TABLE table_name ALTER COLUMN created_at SET DEFAULT now(); - 注意:如果字段允许 NULL,Navicat 不会自动加
NOT NULL约束,得单独勾选「非空」并保存两次
Navicat 15+ 版本对 GENERATED ALWAYS AS 不支持
PostgreSQL 12+ 支持用 GENERATED ALWAYS AS (now()) STORED 做计算列,但 Navicat 当前所有版本都不识别这种语法。你在「默认值」栏填任何表达式,它只会尝试映射到 DEFAULT,而不是生成列。
所以:
- 别指望在 Navicat 图形界面里配置自动生成的时间戳列
- 真要用
GENERATED,得切到「查询」窗口,手写ALTER TABLE ... ADD COLUMN updated_at TIMESTAMP WITH TIME ZONE GENERATED ALWAYS AS (now()) STORED; - 这类列不可写,连
INSERT ... VALUES (...)显式赋值都会报错cannot insert into column "updated_at"
最易忽略的是:Navicat 的「默认值」框看似简单,实则混着三套逻辑——字符串字面量、函数调用、SQL 表达式,而它只认其中一种写法。填错一个字母,表看着建好了,跑起来才发现时间永远停在 2024-01-01。










