SQL Server Management Studioを介してホスティングサーバーのデータベースにアクセスしようとしています。ログインまではすべて問題ありませんが、コマンドuse myDatabase
を使用すると、次のエラーが表示されます。
The server principal "****" is not able to access the database "****" under the current security context.
私は検索したところ、ホスティングサービスプロバイダは this 問題を修正しました。
しかし、これは私にとってはうまくいきません。おそらくそれはSQL Server Management Studio 2008用ですが、私はSQL Server Management Studio 2012を使用しています。
これは問題になりますか?そしてもしそうなら、SSMS 2012で誰かが私にその代替案を教えてくれるでしょうか?
ユーザーがログインしようとしているDBにマップされているかどうかを確認してください。
私たちのPROD環境でSSRSにレポートをデプロイするときに同じエラーがありました。問題は「use」ステートメントでも再現できることがわかった。解決策は、ユーザーのGUIDアカウント参照を問題のデータベースと再同期させることでした(つまり、dbを復元した後と同じように "sp_change_users_login"を使用します)。すべてのアカウントを再同期するためのストック(カーソル駆動)スクリプトが添付されています。
USE <your database>
GO
-------- Reset SQL user account guids ---------------------
DECLARE @UserName nvarchar(255)
DECLARE orphanuser_cur cursor for
SELECT UserName = su.name
FROM sysusers su
JOIN sys.server_principals sp ON sp.name = su.name
WHERE issqluser = 1 AND
(su.sid IS NOT NULL AND su.sid <> 0x0) AND
suser_sname(su.sid) is null
ORDER BY su.name
OPEN orphanuser_cur
FETCH NEXT FROM orphanuser_cur INTO @UserName
WHILE (@@fetch_status = 0)
BEGIN
--PRINT @UserName + ' user name being resynced'
exec sp_change_users_login 'Update_one', @UserName, @UserName
FETCH NEXT FROM orphanuser_cur INTO @UserName
END
CLOSE orphanuser_cur
DEALLOCATE orphanuser_cur
私はこの問題にかなりの時間をかけて取り組んできましたが、私が自分の接続先を特定している特定のデータベースを忘れていたという事実に単純な誤りを犯していることに気づきました。資格情報を入力するために、標準のSQL Server接続ウィンドウを使用していました。
接続先の正しいデータベースを選択していることを確認するには、接続プロパティタブを確認する必要がありました。誤ってConnect to databaseオプションを前のセッションの選択に設定したままにしていました。これが、私が考えていたデータベースに接続できなかった理由です接続しようとしていました。
接続のプロパティやその他のタブを表示するには、Options >>
ボタンをクリックする必要があります。
私の場合、メッセージはデータベース名を誤って「オブジェクト名」に含んでいた同義語が原因でした。データベースを新しい名前で復元したとき、同義語がまだ古いDB名を指していました。ユーザが古いDBの権限を持っていなかったので、メッセージが現れました。修正するために、オブジェクト名をデータベース名で修飾せずに同義語を削除して再作成しました。
USE [new_db]
GO
/****** Object: Synonym [dbo].[synTable] Script Date: 10/15/2015 9:45:01 AM ******/
DROP SYNONYM [dbo].[synTable]
GO
/****** Object: Synonym [dbo].[synTable] Script Date: 10/15/2015 9:45:01 AM ******/
CREATE SYNONYM [dbo].[synTable] FOR [dbo].[tTheRealTable]
GO
これは私のために働いた:
use <Database>
EXEC sp_change_users_login @Action='update_one', @UserNamePattern='<userLogin>',@LoginName='<userLogin>';
問題は次のようにして視覚化できます。
SELECT sid FROM sys.sysusers WHERE name = '<userLogin>'
SELECT sid FROM sys.syslogins WHERE name = '<userLogin>';
SQL Loginsはサーバレベルで定義されており、特定のデータベースではsersにマップする必要があります。
SSMSオブジェクトエクスプローラで、変更したいサーバーの下のSecurity> Loginsを展開し、適切なユーザーをダブルクリックして[Login Properties]ダイアログを表示します。
--- ser Mappingを選択すると、サーバー上のすべてのデータベースが表示され、既存のマッピングが選択されているデータベースも表示されます。ここから追加のデータベースを選択し(そして各データベースのどのロールに所属する必要があるかを必ず選択してください)、OKをクリックしてマッピングを追加します。
これらのマッピングは、復元または類似の操作の後に切断される可能性があります。この場合、ユーザーはまだデータベースに存在している可能性がありますが、実際にはログインにマップされていません。その場合は、次のコマンドを実行してログインを復元してください。
USE {database};
ALTER USER {user} WITH login = {login}
DBユーザーを削除して[ログインのプロパティ]ダイアログから再作成することもできますが、ロールのメンバーシップやその他の設定を再作成する必要があります。
Vb.netでServer Management Objects(SMO)を使用しているときに同じエラーが発生しました(C#でも同じです)。
最初の投稿に対するTechie Joeのコメントは、共有ホスティングでさらに多くのことが起こっているという有用な警告です。理解するのに少し時間がかかりましたが、以下のコードは、SQLデータベースにアクセスする方法において、どのように具体的でなければならないかを示しています。 SMO呼び出しが共有ホスティング環境で厳密には特定されていない場合は常に、「サーバープリンシパル...」エラーが表示されるようでした。
このコードの最初のセクションは、ローカルのSQL Expressサーバーに対するもので、単純なWindows認証に依存していました。これらのサンプルで使用されているすべてのコードは、Robert KanaszによるSMOチュートリアルに基づいています Code ProjectのWebサイトの記事 :
Dim conn2 = New ServerConnection()
conn2.ServerInstance = "<local pc name>\SQLEXPRESS"
Try
Dim testConnection As New Server(conn2)
Debug.WriteLine("Server: " + testConnection.Name)
Debug.WriteLine("Edition: " + testConnection.Information.Edition)
Debug.WriteLine(" ")
For Each db2 As Database In testConnection.Databases
Debug.Write(db2.Name & " - ")
For Each fg As FileGroup In db2.FileGroups
Debug.Write(fg.Name & " - ")
For Each df As DataFile In fg.Files
Debug.WriteLine(df.Name + " - " + df.FileName)
Next
Next
Next
conn2.Disconnect()
Catch err As Exception
Debug.WriteLine(err.Message)
End Try
認証はWindowsによって処理され、すべてのデータベースにわたって幅広く行われているため、上記のコードではローカルSQLEXPRESSサーバー上のすべてのデータベースの.mdfファイルを問題なく検出できます。
次のコードでは、.mdfファイルに対して2つのセクションが繰り返されています。この場合、ファイルグループを検索する最初の反復のみが機能し、接続は共有ホスティング環境内の単一のデータベースのみに対するものであるため、単一のファイルのみが検索されます。
上記のように機能した反復のコピーである2回目の反復では、書き込まれた方法で共有環境の1番目のデータベースにアクセスしようとするため、すぐに窒息します。 SQLサーバーは「サーバープリンシパル...」エラーの形式で承認エラーを返します。
Dim sqlConnection1 As New System.Data.SqlClient.SqlConnection
sqlConnection1.ConnectionString = "connection string with User ID/Password to a specific database in a shared hosting system. This string will likely also include the Data Source and Initial Catalog parameters"
Dim conn1 As New ServerConnection(sqlConnection1)
Try
Dim testConnection As New Server(conn1)
Debug.WriteLine("Server: " + testConnection.Name)
Debug.WriteLine("Edition: " + testConnection.Information.Edition)
Debug.WriteLine(" ")
Dim db2 = testConnection.Databases("the name of the database to which the User ID/Password in the connection string applies")
For Each fg As FileGroup In db2.FileGroups
Debug.Write(fg.Name & " - ")
For Each df As DataFile In fg.Files
Debug.WriteLine(df.Name + " - " + df.FileName)
Next
Next
For Each db3 As Database In testConnection.Databases
Debug.Write(db3.Name & " - ")
For Each fg As FileGroup In db3.FileGroups
Debug.Write(fg.Name & " - ")
For Each df As DataFile In fg.Files
Debug.WriteLine(df.Name + " - " + df.FileName)
Next
Next
Next
conn1.Disconnect()
Catch err As Exception
Debug.WriteLine(err.Message)
End Try
その2回目の繰り返しループでは、コードは正常にコンパイルされますが、SMOは正確な構文で正確なデータベースにアクセスするように設定されていないため、その試みは失敗します。
私はただSMOを学んでいるので、私は他の初心者がこのエラーのためのより簡単な説明もあることを知っているのを認めるかもしれないと思った - 私たちはそれを間違ってコーディングした。
ユーザーがログインに正しくマップされていても、同じエラーが発生しました。
ユーザーを削除しようとした後、いくつかのSPがそのユーザーを "with execute as"に含んでいたことがわかりました。
これらのSPを削除し、ユーザーを削除し、ログインにリンクされているユーザーを再作成し、そしてSPを再作成することで問題を解決しました。
おそらく、(関連するログインが存在しない間の)バックアップからの復元、またはバルクスキーマの同期(ユーザーが実行していなくてもexecuteを使用してSPを作成できる場合)からこの状態になります。 この回答 に関連している可能性もあります。