Sql server 一次创建登录并映射到所有数据库

Sql server 一次创建登录并映射到所有数据库,sql-server,tsql,Sql Server,Tsql,我正在尝试执行以下tsql USE [master] GO CREATE LOGIN UserTest WITH Password = 'hi' GO sp_msforeachdb @command1= "CREATE USER [UserTest] FOR LOGIN [UserTest]" 重复获取以下错误(对于每个DB): 我对sp_msforeachdb的理解是否不正确?基本上,我正在尝试从现有登录名“UserTest”(用户映射)创建“UserTest”,作为每个数据库上的用户,而

我正在尝试执行以下tsql

USE [master]
GO
CREATE LOGIN UserTest WITH Password = 'hi'
GO

sp_msforeachdb @command1= "CREATE USER [UserTest] FOR LOGIN [UserTest]"
重复获取以下错误(对于每个DB):

我对sp_msforeachdb的理解是否不正确?基本上,我正在尝试从现有登录名“UserTest”(用户映射)创建“UserTest”,作为每个数据库上的用户,而不必为每个数据库单独编写代码。我是否以错误的方式完成了这项任务


有点像TSQL的初学者。只是想更彻底地理解该语言,
值用作数据库名称的占位符,因此您的示例如下:

sp_msforeachdb @command1= 'USE [?]; CREATE USER [UserTest] FOR LOGIN [UserTest];'

使用未记录的存储过程时,请注意记录的陷阱。

请不要使用sp_msforeachdb。它没有文档记录,不受支持,并且有一个bug,我已经指出很多次了,它实际上可以跳过数据库。我写了两个备选方案:

您应该做的是使用这些高级替换之一,或者自己创建命令。您还应该检查用户是否已经存在,而不仅仅是在SQL Server上抛出一个潜在的错误

DECLARE @sql NVARCHAR(MAX);
SET @sql = N'';

SELECT @sql = @sql + N'
IF NOT EXISTS (SELECT 1 FROM ' 
  + QUOTENAME(name) + '.sys.database_principals
  WHERE name = N''UserTest'')
    EXEC sp_executesql N''USE ' + name + ';CREATE USER UserTest FOR LOGIN UserTest;'';'
FROM sys.databases
WHERE database_id > 4;

PRINT @sql; -- just to debug the first 8K

-- EXEC sp_executesql @sql; 
-- uncomment the above line when you're happy with the output
您还可以在那里添加错误处理,例如

DECLARE @sql NVARCHAR(MAX);
SET @sql = N'';

SELECT @sql = @sql + N'
IF NOT EXISTS (SELECT 1 FROM ' 
  + QUOTENAME(name) + '.sys.database_principals
  WHERE name = N''UserTest'')
BEGIN
  BEGIN TRY
    EXEC sp_executesql N''USE ' + name + ';CREATE USER UserTest FOR LOGIN UserTest;'';
  END TRY
  BEGIN CATCH
    PRINT ''Did not work for ' + name + ';''
  END CATCH
END'
FROM sys.databases
WHERE database_id > 4;

PRINT @sql;

-- EXEC sp_executesql @sql; 

这是离题的,更适合dba。se@Pondlife我不确定我是否喜欢这个副本,只是因为接受的答案推荐了一个不受支持的、未记录的、有问题的隐藏过程。我宁愿把这个扔给dba.SE,也不愿把它当作一个傻瓜。@AaronBertrand是的,这绝对是一个很好的观点,我同意你的观点。仅供参考,引发您提到的错误的一个“常见”场景是SharePoint 2010,它在其数据库名称中附加了一个GUID,因此这些名称不再是常规标识符。@Pondlife我想在投票表决之前,没有其他人会注意到这些评论-(
DECLARE @sql NVARCHAR(MAX);
SET @sql = N'';

SELECT @sql = @sql + N'
IF NOT EXISTS (SELECT 1 FROM ' 
  + QUOTENAME(name) + '.sys.database_principals
  WHERE name = N''UserTest'')
BEGIN
  BEGIN TRY
    EXEC sp_executesql N''USE ' + name + ';CREATE USER UserTest FOR LOGIN UserTest;'';
  END TRY
  BEGIN CATCH
    PRINT ''Did not work for ' + name + ';''
  END CATCH
END'
FROM sys.databases
WHERE database_id > 4;

PRINT @sql;

-- EXEC sp_executesql @sql;