SQL Server创建用户后USER/USER_NAME()返回guest的原因及解决咨询
在基于镜像mcr.microsoft.com/mssql/server:2022-latest的全新SQL Server容器中,以sa身份登录后,创建了数据库、data和liquibase两个Schema,以及名为kpadmin的登录名与用户:
-- USE master -- <create database, schema data, liquibase> CREATE LOGIN kpadmin WITH PASSWORD = '<password>' USE <database> GO CREATE USER kpadmin FOR LOGIN kpadmin WITH DEFAULT_SCHEMA = data; GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA ::data TO kpadmin; GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA ::liquibase TO kpadmin; GRANT CREATE TABLE TO kpadmin; GRANT CONNECT TO kpadmin;
随后在SSMS中以kpadmin用户登录,执行查询:
SELECT USER, USER_NAME(), SYSTEM_USER, SUSER_SNAME(), CURRENT_USER
得到结果:
guest guest kpadmin kpadmin guest
疑问:为何USER和USER_NAME()返回guest而非kpadmin?忽略了什么?该如何修复?
此问题已导致Liquibase运行报错:
Liquibase运行时出现意外错误:在Microsoft SQL Server上无法使用默认Schema名称data,因为当前用户(guest)的登录Schema不同,且MSSQL不支持按会话设置默认Schema。
(即使将登录名与用户设为不同名称,问题依然存在)
原因
核心问题是登录名kpadmin未正确映射到目标数据库中的同名用户,导致登录后自动 fallback 到数据库的guest用户。通常是创建用户时的上下文错误,或是登录名与数据库用户的SID关联失效导致的。
修复步骤
验证关联关系
以sa身份登录目标数据库,执行以下查询确认登录名与数据库用户的绑定:SELECT dp.name AS [数据库用户], sp.name AS [登录名] FROM sys.database_principals dp JOIN sys.server_principals sp ON dp.sid = sp.sid WHERE dp.name = 'kpadmin';若无结果返回,说明两者关联已损坏,需重新建立映射。
重建用户与登录名的关联
执行以下SQL修复关联(若数据库用户已存在,可先删除再重建,或直接使用ALTER USER关联):USE <database>; GO -- 可选:若用户存在且权限可保留,跳过删除直接执行ALTER USER DROP USER IF EXISTS kpadmin; GO CREATE USER kpadmin FOR LOGIN kpadmin WITH DEFAULT_SCHEMA = data; -- 或使用ALTER USER直接关联:ALTER USER kpadmin WITH LOGIN = kpadmin; GO -- 重新授予权限 GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA ::data TO kpadmin; GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA ::liquibase TO kpadmin; GRANT CREATE TABLE TO kpadmin; GRANT CONNECT TO kpadmin;禁用guest用户(可选但推荐)
为避免后续出现类似 fallback 问题,禁用目标数据库的guest用户:USE <database>; GO REVOKE CONNECT FROM guest;验证修复效果
重新以kpadmin登录SSMS,执行原查询:SELECT USER, USER_NAME(), SYSTEM_USER, SUSER_SNAME(), CURRENT_USER正常情况下,
USER、USER_NAME()和CURRENT_USER均应返回kpadmin,此时Liquibase的默认Schema错误将自动解决。
内容的提问来源于stack exchange,提问作者Avixon

