次の方法で共有


MSSQLSERVER_15517

適用対象: SQL Server

詳細

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

説明

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

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

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

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

参照

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

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