服务器主体无法在SQL Server MS 2012中的当前安全上下文下访问数据库

时间:2013-09-25 15:47:41

标签: sql-server sql-server-2012

我试图通过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中的替代方案吗?

10 个答案:

答案 0 :(得分:73)

检查您的用户是否已映射到您尝试登录的数据库。

答案 1 :(得分:20)

我们在PROD环境中将报告部署到SSRS时遇到了同样的错误。人们发现这个问题甚至可以通过“使用”声明再现。解决方案是将用户的GUID帐户引用与相关数据库重新同步(即,像恢复数据库一样使用“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

答案 2 :(得分:7)

我花了很长时间来解决这个问题,然后我意识到我犯了一个简单的错误,因为我忘记了哪个特定的数据库是我的目标。我使用标准SQL Server连接窗口输入凭据:

SQL Server Connection Window

我必须检查连接属性标签,以验证我是否选择了要连接的正确数据库。我不小心将连接到数据库选项保留在此处,设置为上一个会话中的选择。这就是为什么我无法连接到我想要连接的想到的数据库。

Connection Properties

请注意,您需要点击Options >>按钮才能显示连接属性和其他标签。

答案 3 :(得分:3)

就我而言,该消息是由同义词引起的,该同义词无意中将数据库名称包含在&#34;对象名称&#34;中。当我以新名称还原数据库时,同义词仍然指向旧的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

答案 4 :(得分:1)

这对我有用:

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>';

答案 5 :(得分:0)

我在vb.net中使用服务器管理对象(SMO)时遇到了同样的错误(我确信它在C#中是相同的)

Techie Joe对初始帖子的评论是一个有用的警告,即在共享主机中还有很多其他内容正在进行中。花了一点时间才弄明白,但下面的代码显示了如何在访问SQL数据库时非常具体。每当SMO调用在共享托管环境中没有精确具体时,“服务器主体.​​.....”错误似乎就会出现。

第一部分代码针对本地SQL Express服务器,依赖于简单的Windows身份验证。这些示例中使用的所有代码都基于Robert Kanasz在此Code Project website article中的SMO教程:

  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

上面的代码可以很好地找到本地SQLEXPRESS服务器上每个数据库的.mdf文件,因为身份验证由Windows处理,并且在所有数据库中都是广泛的。

在以下代码中,有两个部分迭代.mdf文件。在这种情况下,只有第一次迭代查找文件组才有效,并且它只找到一个文件,因为连接只是共享托管环境中的一个数据库。

第二次迭代,它是上面工作的迭代的副本,立即窒息,因为它写入的方式它试图访问共享环境中的第一个数据库,这不是用户ID /密码的那个apply,因此SQL Server以“server principal ...”错误的形式返回授权错误。

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

在第二个迭代循环中,代码编译得很好,但由于SMO没有设置为使用精确语法精确访问正确的数据库,因此该尝试失败。

由于我刚刚学习SMO,我认为其他新手可能会欣赏知道这个错误还有一个更简单的解释 - 我们只是编错了。

答案 6 :(得分:0)

即使用户已正确映射到登录名,我们也会遇到相同的错误。

尝试删除用户后,发现有几个SP包含&#34;执行为&#34;那个用户。

通过删除这些SP,删除用户,重新创建链接到登录的用户以及重新创建SP来解决问题。

可能它处于这种状态,从备份恢复(在相关登录不存在的时间)或批量模式同步(如果可能创建具有执行的SP,即使用户没有&#39) ; t存在。也可能与this answer有关。

答案 7 :(得分:0)

SQL 登录是在服务器级别定义的,必须映射到特定数据库中的用户

在SSMS对象浏览器中,要修改的服务器下,展开安全性> 登录,然后双击相应的用户,将弹出“登录属性”。 “对话框。

选择用户映射,它将显示服务器上的所有数据库,并选择已选择现有映射的数据库。在这里,您可以选择其他数据库(并确保选择用户应属于每个数据库中的哪个角色),然后单击确定添加映射。

enter image description here

在还原或类似操作之后,这些映射可能会断开连接。在这种情况下,用户可能仍然存在于数据库中,但实际上并未映射到登录名。如果发生这种情况,您可以运行以下命令来恢复登录名:

USE {database};
ALTER USER {user} WITH login = {login}

您还可以删除数据库用户,然后从“登录属性”对话框中重新创建它,但是任何角色成员身份或其他设置都需要重新创建。

答案 8 :(得分:0)

我相信您在创建数据库用户时可能会丢失“授权连接到”语句。

下面是完整的代码段,您将需要创建针对SQL Server DBMS的登录名以及针对数据库的用户

USE [master]
GO

CREATE LOGIN [SqlServerLogin] WITH PASSWORD=N'Passwordxyz', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=ON
GO

USE [myDatabase]
GO

CREATE USER [DatabaseUser] FOR LOGIN [SqlServerLogin] WITH DEFAULT_SCHEMA=[mySchema]
GO

GRANT CONNECT TO [DatabaseUser]
GO

-- the role membership below will allow you to run a test "select" query against the tables in your database
ALTER ROLE [db_datareader] ADD MEMBER [DatabaseUser]
GO

答案 9 :(得分:0)

在SQL 2017上-数据库A具有与数据库B的同义词。用户可以连接到数据库A,并且对sp(在A上)具有指向指向B的同义词的执行权限。仅当将对公共组的CONNECT授予数据库B时,A上的工作才会执行。我不记得在2012年以这种方式工作,因为授予与用户的连接似乎只是行得通。