如何仅在登录名不存在时创建SQL Server登录名、对应用户及关联架构
问题核心原因
GO是SSMS、sqlcmd等SQL客户端识别的批处理分隔符,不属于T-SQL语法,每个GO前后的语句会拆分为独立批处理单独执行,所以跨GO的IF NOT EXISTS...BEGIN...END作用域会直接失效,这是你之前尝试失败的根本原因。
可用解决方案
通过会话级临时表存储登录名的存在性判断结果(临时表天生支持跨批处理访问),每个批处理单独读取判断结果控制是否执行对应逻辑,既满足创建登录名后必须分批次创建用户的要求,也实现了仅登录名不存在时才执行全部操作的逻辑,可直接运行的脚本如下:
-- 初始化存储判断结果的临时表 IF OBJECT_ID(N'tempdb..#LoginNotExists') IS NOT NULL DROP TABLE #LoginNotExists GO -- 判断指定SQL登录名是否不存在,将结果存入临时表 SELECT CASE WHEN EXISTS ( SELECT 1 FROM sys.server_principals WHERE name = N'MyLogin' AND type = 'S' -- type='S'代表SQL身份验证登录 ) THEN 0 ELSE 1 END AS IsNotExists INTO #LoginNotExists GO -- 批处理1:仅当登录名不存在时创建登录 IF (SELECT IsNotExists FROM #LoginNotExists) = 1 BEGIN USE [master] CREATE LOGIN [MyLogin] WITH PASSWORD=N'MyPassword', DEFAULT_DATABASE=[MyNewDatabase], DEFAULT_LANGUAGE=[us_english], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF END GO -- 批处理2:仅当登录名不存在时创建用户、分配权限、创建架构 IF (SELECT IsNotExists FROM #LoginNotExists) = 1 BEGIN USE [MyNewDatabase] CREATE USER [MyLogin] FOR LOGIN [MyLogin] WITH DEFAULT_SCHEMA=[MyLogin] -- 旧版兼容写法,SQL Server 2012+推荐用ALTER ROLE写法 exec sp_addrolemember db_datareader, MyLogin; exec sp_addrolemember db_datawriter, MyLogin; -- 新写法示例: -- ALTER ROLE [db_datareader] ADD MEMBER [MyLogin]; -- ALTER ROLE [db_datawriter] ADD MEMBER [MyLogin]; CREATE SCHEMA [MyLogin] END GO -- 清理临时表 DROP TABLE #LoginNotExists GO
补充说明
- 如果你使用的是SQL Server 2016及以上版本,也可以直接用
CREATE LOGIN IF NOT EXISTS语法简化登录创建步骤,但如果你的要求是只要登录名已存在,哪怕对应的用户、架构不存在也完全不执行后续操作,上述临时表方案依然是最符合需求的选择。 - 执行脚本的账号需要持有
ALTER ANY LOGIN(服务端)、对应数据库的ALTER ANY USER、ALTER ANY SCHEMA、ALTER ROLE权限才能正常执行所有操作。
内容的提问来源于stack exchange,提问作者sr28
相关产品推荐
相关产品推荐

