0

次のtsqlを実行しようとしています

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

sp_msforeachdb @command1= "CREATE USER [UserTest] FOR LOGIN [UserTest]"

次のエラーが繰り返し発生します (DB ごとに):

Msg 15023, Level 16, State 1, Line 1
User, group, or role 'UserTest' already exists in the current database.

sp_msforeachdb についての私の理解は間違っていますか? 基本的に、各データベースのコードを個別に記述しなくても、既存のログイン 'UserTest' (ユーザー マッピング) から各データベースのユーザーとして 'UserTest' を作成しようとしています。このタスクに間違った方法で取り組んでいますか?

TSQL の初心者のやや。言語をより完全に理解しようとしているだけです

4

2 に答える 2

2

sp_msforeachdb は使用しないでください。これは文書化されておらず、サポートもされておらず、実際にデータベースをスキップできるバグが何度も指摘されています。私は2つの選択肢を書きました:

これらの優れた代替品のいずれかを使用するか、自分でコマンドを作成する必要があります。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 sys.sp_executesql N''USE ' + QUOTENAME(name) 
       + ';CREATE USER UserTest FOR LOGIN UserTest;'';'
FROM sys.databases
WHERE database_id > 4;

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

-- EXEC sys.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 sys.sp_executesql N''USE ' + QUOTENAME(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 sys.sp_executesql @sql; 
于 2013-03-25T20:56:10.380 に答える
0

?値はデータベース名のプレースホルダーとして使用されるため、例は次のようになります。

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

文書化されていないストアド プロシージャを使用する場合は、ここに記載されている落とし穴に注意してください。

于 2013-03-25T20:49:43.543 に答える