MSSQLSERVER_15517

适用于:SQL Server

详细信息

属性
产品名称 SQL Server
事件 ID 15517
事件来源 MSSQLSERVER
组件 SQLEngine
符号名称 SEC_CANNOTEXECUTEASUSER
消息正文 无法作为数据库主体执行,因为主体“主体不存在,此类主体无法模拟,或者您没有权限。

说明

此错误通常是因为Microsoft SQL Server 无法使用语句获取有关在用户语句或模块 EXECUTE AS 中指定的主体的执行上下文的信息。

在 SQL Server 实例上创建数据库时,登录信息安全标识符(SID)会自动保存,作为表中相应数据库行 sys.databases 中的数据库所有者以及 dbo 数据库中表中的用户项 sys.database_principals

如果为 dbo 用户存储的 SID 条目有效,则使用该 EXECUTE AS OWNER 子句的语句或模块将按预期工作。

注意

对于语句中使用的 EXECUTE AS 任何主体以及数据库还原到的服务器上不存在,可能会出现此问题。

下面是一些可能导致此问题的常见方案:

  • 在最初创建备份的同一服务器实例上还原数据库,但创建数据库的 SQL Server 主体出于某种原因不再有效。 例如:

    • SQL Server 身份验证登录名已删除。
    • Windows 身份验证登录名不再适用于 Active Directory 中的有效用户,因为员工离开了公司。
  • 在与最初创建备份的实例不同的服务器上还原数据库,但创建数据库的 SQL Server 主体在新服务器上不是有效的主体。

    • 如果用户是 SQL Server 登录名,则主体可能存在于目标或目标服务器上,但 sid 该值会有所不同。
    • 如果用户是 Windows 登录名,则目标服务器上不存在 Windows 登录名,或者该登录名不再有效。

运行存储过程、函数或触发器的用户或应用程序没有模拟语句中指定的 EXECUTE AS 主体所需的权限。

用户操作

使用现有主体的名称,或向所需用户授予对该主体的 IMPERSONATE 权限。

若要解决由于 dbo 用户错误无效而发生的问题,请运行以下命令,将 dbo_User 值更改为服务器上的有效登录名:

ALTER AUTHORIZATION ON DATABASE:: DBName TO [NewLogin]  

示例方案

  1. 创建两个临时主体:

    CREATE LOGIN login1 WITH PASSWORD = 'J345#$)thb';
    CREATE LOGIN login2 WITH PASSWORD = 'Uor80$23b';
    
  2. 将这些登录名添加到 sysadmin 角色(仅用于演示)。

  3. 使用 login1 登录到 SQL Server 实例。

  4. 创建演示数据库和存储过程,该存储过程通过运行以下脚本进行命名 testexec

    CREATE DATABASE Demodb_15517
    GO
    USE Demodb_15517
    GO
    CREATE procedure [dbo].[testexec]
    WITH EXECUTE AS owner
    AS SELECT @@VERSION
    GO
    EXEC dbo.testexec
    GO
    
  5. 运行以下查询,并检查值是否 sid 解析为有效的登录名:

    • 查询 1:检查 sys.databases 中值的值 Owner_Name

      SELECT NAME AS Database_Name, owner_sid, SUSER_SNAME(owner_sid) AS OwnerName
      FROM sys.databases
      WHERE NAME = N'Demodb_15517';
      
      Database_Name         owner_sid                               OwnerName
      --------------------- -------------------------------------- ----------------------------
      Demodb_15517          0xDB79ED7B6731CF4E8DC7DF02871E3E36      login1
      
    • 查询 2:检查 Owner_Name 演示数据库中表中的值 sys.database_principals

      SELECT SUSER_SNAME(sid) AS Owner_Name, sid 
      FROM Demodb_15517.sys.database_principals 
      WHERE NAME = N'dbo'; 
      
      Owner_Name    SID
      ------------- ------------------------------------------------ 
      login1        0xDB79ED7B6731CF4E8DC7DF02871E3E36
      
  6. 使用类似于以下脚本的查询备份演示数据库:

    BACKUP DATABASE [Demodb_15517] TO DISK = N'C:\SQLBackups\Demodb_15517.bak' WITH NOFORMAT, NOINIT, NAME = N'Demodb_15517 Full backup', SKIP, EWIND, NOUNLOAD, STATS = 10 
    GO
    
  7. 删除演示数据库并 login1

    DROP DATABASE demodb_15517
    GO
    DROP login login1
    GO
    
  8. 以 . 身份 login2登录到 SQL Server。

  9. 使用类似于以下脚本的语句从备份还原演示数据库:

    USE [master] 
    RESTORE DATABASE [Demodb_15517] FROM   
    DISK = N'C:\SQLBackups\Demodb_15517.bak' WITH FILE = 1,   
    MOVE N'Demodb_15517' TO N'C:\SQLBackups\Demodb_15517.mdf',   
    MOVE N'Demodb_15517_log' TO N'C:\SQLBackups\\Demodb_155172_log.ldf',   
    NOUNLOAD, STATS = 5 
    GO 
    
  10. 重新运行查询 1 和查询 2。

  11. 在查询 1 中,检查Owner_Name值的值。sys.databases 值现在反映 login2

    SELECT NAME AS Database_Name, owner_sid, SUSER_SNAME(owner_sid) AS OwnerName 
    FROM sys.databases 
    WHERE NAME = N'Demodb_15517';
    
    Database_Name  owner_sid                               OwnerName
    -------------- --------------------------------------- ---------------------
    Demodb_15517   0xD63086DD7277BC4EB88013D359AF73A6      login2
    
  12. 在查询 2 中,检查演示数据库中表中的值Owner_Namesys.database_principals。 值现在反映 NULL

    SELECT SUSER_SNAME(sid) AS Owner_Name, sid
    FROM Demodb_15517.sys.database_principals
    WHERE NAME = N'dbo';
    
    Owner_Name         sid 
      ------------------ -----------------------------------------------
    NULL               0xDB79ED7B6731CF4E8DC7DF02871E3E36 
    
  13. testexec运行存储过程。 现在应会看到“15517”错误消息。

    USE Demodb_15517 
    GO 
    EXEC dbo.testexec 
    GO
    
    Msg 15517, Level 16, State 1, Procedure dbo.testexec, Line 0 [Batch Start Line 19] 
    Cannot execute as the database principal because the principal "dbo" does not exist, this type of principal cannot be impersonated, or you do not have permission. 
    
  14. 若要解决此错误,请使用以下命令将 dbo 更改为有效用户(login2):

    ALTER AUTHORIZATION ON DATABASE:: Demodb_15517 TO [login2]   
    
  15. 重新运行查询 2 并验证 dbo 用户现在是否解析为 login2 用户。

    Owner_Name          SID
    ---------------------------------------------------------------- 
    login2              0xD63086DD7277BC4EB88013D359AF73A6 
    
  16. 请重试运行测试存储过程。 请注意,它现在已成功运行。

    USE Demodb_15517 
    GO 
    EXEC dbo.testexec 
    GO
    
    /* -- You get an output that resembles the following 
    ---------------------------------------------------------------------------------------------------------
    Microsoft SQL Server 2019 (RTM-CU16-GDR) (KB5014353) - 15.0.4236.7 (X64)  
    May 29 2022 15:55:47  
    Copyright (C) 2019 Microsoft Corporation 
    Express Edition (64-bit) on Windows 10 Enterprise 10.0 <X64> (Build 22621: ) (Hypervisor) 
    */ 
    

另请参阅

将数据库复制到其他服务器

在实例之间传输登录名和密码