MSSQLSERVER_15517

適用対象:SQL Server

詳細

属性 Value
製品名 SQL Server
イベント ID 15517
イベント ソース MSSQLSERVER
コンポーネント SQLEngine
シンボル名 SEC_CANNOTEXECUTEASUSER
メッセージ テキスト プリンシパル "プリンシパル" が存在しない、この種類のプリンシパルを偽装できない、または権限がないため、データベース プリンシパルとして実行できません。

説明

このエラーは通常、ユーザー ステートメントまたはモジュールで指定されたプリンシパルの実行コンテキストに関する情報を、Microsoft SQL Server がステートメントを使用 EXECUTE AS して取得できないために発生します。

SQL Server インスタンス上にデータベースを作成すると、ログイン情報セキュリティ識別子 (SID) は、テーブル内の対応するデータベース行およびdboデータベース内のテーブル内sys.databasesのユーザー項目のデータベース所有者として自動的にsys.database_principals保存されます。

この句を使用 EXECUTE AS OWNER するステートメントまたはモジュールは、dbo ユーザー用に格納されている SID エントリが有効な場合、期待どおりに動作します。

Note

この問題は、ステートメントで 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. 2 つの一時プリンシパルを作成します。

    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: デモンストレーション データベース内のsys.database_principalsテーブルの値を確認Owner_Nameします。

      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. として SQL Server login2にログインします。

  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_Name値の値をsys.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) 
    */ 
    

参照

他のサーバーへのデータベースのコピー

インスタンス間でログインとパスワードを転送する