SESSION_USER返回会话初始登录用户,不可被SET ROLE修改;PostgreSQL中等价于SESSION_USER(),SQL Server中为SESSION_USER(不带括号),用于审计登录来源而非执行上下文。

SESSION_USER 返回的是登录用户,不是执行上下文用户
在 PostgreSQL、SQL Server 等支持 SESSION_USER 的数据库中,它返回的是当前会话建立时认证的用户名,而非当前执行语句所处的角色(比如通过 SET ROLE 或 EXECUTE AS 切换后的角色)。这点常被误认为等同于 CURRENT_USER 或 USER,但语义不同。
常见错误现象:你用 admin 登录后执行 SET ROLE 'reporter',再查 SESSION_USER,结果仍是 'admin' —— 这不是 bug,是设计如此。
-
SESSION_USER是会话级只读标识,不可被 SET 修改 - PostgreSQL 中它等价于
SESSION_USER()函数调用(带括号也可,但不推荐) - SQL Server 中必须不带括号:
SESSION_USER;带括号会报错Invalid column name 'SESSION_USER' - MySQL 不支持
SESSION_USER,它只有USER()(返回 user@host)和CURRENT_USER()(返回授权匹配的 user@host)
在 WHERE 条件或视图中安全使用 SESSION_USER
想基于当前登录人动态过滤数据?比如只允许用户查看自己名下的订单。这时直接在视图定义里写 WHERE owner = SESSION_USER 是可行的,但要注意权限模型是否允许绕过。
示例(PostgreSQL):
CREATE VIEW my_orders AS SELECT * FROM orders WHERE owner = SESSION_USER;
这个视图对所有用户都生效,且每次查询都会实时取当前会话的登录名。但注意:
使用 Playwright 为 jimeng.jianying.com 管理浏览器会话,导入 cookies/localStorage 以自动化视频生成工作流,支持图片上传等功能
- 如果
owner字段是TEXT类型,而SESSION_USER返回值含大小写或空格,需统一处理,例如用LOWER(SESSION_USER) - SQL Server 中该函数返回
sysname(即nvarchar(128)),与字符串字段比较时建议显式转换,避免隐式转换失败 - 不能在索引表达式或物化视图(如 PostgreSQL 的
MATERIALIZED VIEW)中依赖SESSION_USER,因为它不是稳定函数(volatile)
SESSION_USER vs CURRENT_USER:别混用权限判断逻辑
这是最容易踩坑的地方。如果你在存储过程里做权限校验,用错了函数会导致越权或误拒。
典型场景:DBA 创建了一个 audit_log 表,要求插入时记录操作者身份。用 SESSION_USER 记录的是谁连进来,而 CURRENT_USER 才反映当前执行语句的实际有效角色。
- PostgreSQL 中:
CURRENT_USER可随SET ROLE改变;SESSION_USER始终不变 - SQL Server 中:
CURRENT_USER对应USER_NAME(),SESSION_USER对应SYSTEM_USER(但二者通常相同,除非用了EXECUTE AS) - 若过程内有
EXECUTE AS 'otheruser',则CURRENT_USER变,SESSION_USER不变 - 审计类逻辑优先用
CURRENT_USER;登录来源追踪类逻辑才用SESSION_USER
跨数据库移植时 SESSION_USER 的兼容性陷阱
写可移植 SQL 时,SESSION_USER 并非通用。Oracle 用 USER(等价于 CURRENT_USER),不支持 SESSION_USER;SQLite 完全不支持该函数。
如果你正在抽象一个用户感知的数据访问层,不要硬编码 SESSION_USER。更稳妥的做法是:
- 应用层显式传入当前登录用户名(作为参数或上下文变量)
- 数据库侧用
pg_backend_pid()+pg_stat_activity查登录用户(PostgreSQL 专属,性能开销略高) - SQL Server 中可用
ORIGINAL_LOGIN()替代部分SESSION_USER场景,尤其在EXECUTE AS后仍要追溯原始登录人时 - 避免在 DDL(如分区策略、行级安全策略 RLS)中强依赖该函数,因为不同版本/厂商实现差异大
真正需要区分“谁连进来”和“谁在执行”的时候,得先确认你的数据库版本是否把这两个概念暴露得足够清晰——否则很容易在权限收紧后才发现日志里全是 postgres 或 sa。

















