直接查sys.user$表的ptime字段可获取用户最后一次密码修改时间,该字段记录oracle内部写入密码哈希的真实时间点,不受profile设置、审计开关或密码复用策略影响,且为空时表示用户从未设置密码。
直接查 sys.user$ 表的 ptime 字段就能拿到最后修改时间,但必须用 sys 用户(或具有 select any dictionary 权限的账号)执行,且结果是 date 类型,不是字符串也不是时间戳。
为什么 PTIME 是最可靠的方式
它记录的是 Oracle 内部实际写入密码哈希值的时间点,不受 profile 设置、审计开关、密码复用策略影响。只要用户改过密(包括 ALTER USER ... IDENTIFIED BY 或登录时强制改密),PTIME 就会更新。不像 DBA_USERS.PASSWORD_LAST_CHANGED 在某些旧版本中可能为空或不准确。
-
PTIME为空表示该用户从未设过密码(比如外部认证用户、或刚创建未赋密) - 如果用户被 DBA 用
IDENTIFIED BY VALUES方式重置密码(绕过验证),PTIME仍会更新 —— 这是它比历史表更“诚实”的地方 - 注意:
sys.user$是核心基表,不建议在生产环境频繁扫描全表;查单个用户即可
怎么安全地查某个用户的 PTIME
别直接 SELECT * FROM sys.user$,权限高、数据敏感、还容易锁表。只查需要的字段和用户:
SELECT NAME, TYPE#, CTIME, PTIME, EXPTIME FROM sys.user$ WHERE NAME = 'SCOTT';
-
NAME必须大写,Oracle 系统基表里的用户名都是大写的 -
CTIME是用户创建时间,EXPTIME是推算出的过期时间(受PASSWORD_LIFE_TIME影响),可一起看做参考 - 如果返回空行,说明用户不存在,或你没权限访问
sys.user$—— 此时先确认连接用户是否有SELECT ANY DICTIONARY
PTIME 和 DBA_USERS.EXPIRY_DATE 的区别在哪
这是最容易混淆的点:PTIME 是“事实”,EXPIRY_DATE 是“推论”。
-
PTIME是真实发生的时间,不可逆、不依赖配置 -
DBA_USERS.EXPIRY_DATE是 Oracle 根据PTIME + PASSWORD_LIFE_TIME算出来的,如果 profile 改了、或者用户被赋予了别的 profile,这个值就会变,但PTIME不会 - 例如:某用户
PTIME是 2026-01-01,profile 的PASSWORD_LIFE_TIME原来是 180,后来改成UNLIMITED,那么EXPIRY_DATE会变为空,但PTIME还是 2026-01-01
常见错误:查不到 PTIME 或显示 NULL
不是语句写错,大概率是权限或对象问题:
- 用普通用户(如
SYSTEM)连上去执行,会报ORA-00942: table or view does not exist—— 因为没权限,不是表不存在 - 用
SYS连但忘了加AS SYSDBA,可能看到空结果或权限不足提示 -
PTIME为 NULL:说明该用户是只读账户、外部认证用户(EXTERNAL)、或刚CREATE USER但还没ALTER USER ... IDENTIFIED BY - 不要试图从
sys.user_history$查最后修改时间 —— 它只存历史密码哈希,且默认关闭,依赖PASSWORD_REUSE_TIME非UNLIMITED才写入
真正要确认“最后一次改密是什么时候”,盯住 sys.user$.PTIME 就够了。其他视图要么是推导值,要么依赖额外配置,反而容易引入误判。











