Partager via


MSSQLSERVER_15517

S'applique à : SQL Server

Détails

Attribut Valeur
Nom du produit SQL Server
ID de l’événement 15517
Source de l’événement MSSQLSERVER
Composant SQLEngine
Nom symbolique SEC_CANNOTEXECUTEASUSER
Texte du message Impossible d’exécuter en tant que principal de base de données, car le principal « principal » n’existe pas, ce type de principal ne peut pas être emprunt d’identité ou vous n’avez pas d’autorisation.

Explication

Cette erreur se produit généralement parce que Microsoft SQL Server ne peut pas obtenir les informations sur le contexte d’exécution du principal spécifié dans une instruction utilisateur ou un module à l’aide de l’instruction EXECUTE AS .

Votre IDENTIFICATEUR de sécurité des informations de connexion est automatiquement enregistré lorsque vous créez une base de données sur une instance SQL Server en tant que propriétaire de la base de données dans la ligne de base de données correspondante de la sys.databases table et pour l’élément dbo utilisateur de la table dans la sys.database_principals base de données.

Les instructions ou modules qui utilisent la EXECUTE AS OWNER clause fonctionnent comme prévu si l’entrée SID stockée pour l’utilisateur dbo est valide.

Remarque

Le problème peut se produire pour tout principal utilisé dans l’instruction EXECUTE AS et qui n’existe pas sur le serveur sur lequel la base de données est restaurée.

Voici quelques scénarios courants susceptibles de provoquer ce problème :

  • Vous restaurez une base de données sur la même instance de serveur où la sauvegarde a été effectuée à l’origine, mais le principal SQL Server qui a créé la base de données n’est plus valide pour une raison quelconque. Par exemple :

    • La connexion d’authentification SQL Server a été supprimée.
    • La connexion Authentification Windows n’est plus destinée à un utilisateur valide dans Active Directory, car l’employé a quitté l’entreprise.
  • Vous restaurez une base de données sur un serveur différent de l’instance où la sauvegarde a été effectuée à l’origine, mais le principal SQL Server qui a créé la base de données n’est pas un principal valide sur le nouveau serveur.

    • Si l’utilisateur est une connexion SQL Server, le principal peut exister sur le serveur cible ou de destination, mais la sid valeur sera différente.
    • Si l’utilisateur est une connexion Windows, la connexion Windows n’existe pas sur le serveur cible ou n’est plus valide.

L’utilisateur ou l’application qui exécute la procédure stockée, la fonction ou le déclencheur ne dispose pas des autorisations nécessaires pour emprunter l’identité du principal spécifié dans l’instruction EXECUTE AS .

Action utilisateur

Utilisez le nom d’un principal existant ou accordez l’autorisation IMPERSONATE sur ce principal aux utilisateurs requis.

Pour résoudre le problème qui se produit en raison d’une erreur dbo utilisateur non valide, remplacez la dbo_User valeur par une connexion valide sur votre serveur en exécutant la commande suivante :

ALTER AUTHORIZATION ON DATABASE:: DBName TO [NewLogin]  

Exemple de scénario

  1. Créez deux principaux temporaires :

    CREATE LOGIN login1 WITH PASSWORD = 'J345#$)thb';
    CREATE LOGIN login2 WITH PASSWORD = 'Uor80$23b';
    
  2. Ajoutez ces connexions au rôle sysadmin (pour démonstration uniquement).

  3. Connectez-vous à votre instance SQL Server à l’aide login1de .

  4. Créez une base de données de démonstration et une procédure stockée nommée testexec en exécutant le script suivant :

    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. Exécutez les requêtes suivantes et vérifiez si les sid valeurs sont résolues sur une connexion valide :

    • Requête 1 : Vérifiez la valeur de la Owner_Name valeur dans sys.databases.

      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
      
    • Requête 2 : Vérifiez la Owner_Name valeur dans la table dans la sys.database_principals base de données de démonstration :

      SELECT SUSER_SNAME(sid) AS Owner_Name, sid 
      FROM Demodb_15517.sys.database_principals 
      WHERE NAME = N'dbo'; 
      
      Owner_Name    SID
      ------------- ------------------------------------------------ 
      login1        0xDB79ED7B6731CF4E8DC7DF02871E3E36
      
  6. Sauvegardez la base de données de démonstration à l’aide d’une requête semblable au script suivant :

    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. Supprimez la base de données de démonstration et login1:

    DROP DATABASE demodb_15517
    GO
    DROP login login1
    GO
    
  8. Connectez-vous à SQL Server en tant que login2.

  9. Restaurez la base de données de démonstration à partir de la sauvegarde à l’aide d’une instruction semblable au script suivant :

    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. Réexécutez la requête 1 et la requête 2.

  11. Dans la requête 1, vérifiez la valeur de la Owner_Name valeur dans sys.databases. La valeur reflète login2maintenant .

    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. Dans la requête 2, vérifiez la valeur de la Owner_Name valeur dans la table dans la sys.database_principals base de données de démonstration. La valeur reflète NULLmaintenant .

    SELECT SUSER_SNAME(sid) AS Owner_Name, sid
    FROM Demodb_15517.sys.database_principals
    WHERE NAME = N'dbo';
    
    Owner_Name         sid 
      ------------------ -----------------------------------------------
    NULL               0xDB79ED7B6731CF4E8DC7DF02871E3E36 
    
  13. Exécutez la testexec procédure stockée. Vous devez maintenant voir le message d’erreur « 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. Pour résoudre l’erreur, remplacez le dbo par un utilisateur valide (login2) à l’aide de la commande suivante :

    ALTER AUTHORIZATION ON DATABASE:: Demodb_15517 TO [login2]   
    
  15. Réexécutez la requête 2 et vérifiez que les utilisateurs dbo se résolvent désormais à l’utilisateur login2.

    Owner_Name          SID
    ---------------------------------------------------------------- 
    login2              0xD63086DD7277BC4EB88013D359AF73A6 
    
  16. Réessayez pour exécuter la procédure stockée de test. Notez qu’elle s’exécute maintenant correctement.

    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) 
    */ 
    

Voir aussi

Copier des bases de données sur d’autres serveurs

Transférer des connexions et des mots de passe entre des instances