MS SQL Server 2014 DBに共有APIを実装しようとしています。そのアーキテクチャーでは、スキーマは同様の構造を持ち、dboが所有する共有APIを使用し、同時に独自のAPIを公開する必要があります。オブジェクト名を修飾せずに互いに呼び出すには、EXECUTE AS USER
ステートメントが、現在のユーザーの特定のデフォルトスキーマへのコンテキスト切り替えに使用されます。ストアドプロシージャのユーザーのデフォルトスキーマにアクセスすると、SQL Serverのユーザーを切り替えることができません
問題はここにある:ユーザコンテキストの切り替えに即時アクセスが正常に動作している間(例えばEXECUTE AS USER
がSELECT * from test_tbl;
が続く)、ストアドプロシージャのデフォルトのスキーマを介してアクセスがエラーMsg 208, Level 16, State 1
で失敗します。
私の質問を投稿する前に、何度か実験やテストを行い、数日間MSDN、Web、SQLフォーラムを検索しました。
-- DB creation
CREATE DATABASE [test_sql]
CONTAINMENT = NONE
ON PRIMARY
(NAME = N'test_sql', FILENAME = N'<MDF>' , SIZE = 5120KB , FILEGROWTH = 1024KB)
LOG ON
(NAME = N'test_sql_log', FILENAME = N'<LDF>' , SIZE = 2048KB , FILEGROWTH = 10%)
COLLATE Cyrillic_General_CI_AS
GO
ALTER DATABASE [test_sql] SET COMPATIBILITY_LEVEL = 120
GO
ALTER DATABASE [test_sql] SET ANSI_NULL_DEFAULT OFF
GO
ALTER DATABASE [test_sql] SET ANSI_NULLS OFF
GO
ALTER DATABASE [test_sql] SET ANSI_PADDING OFF
GO
ALTER DATABASE [test_sql] SET ANSI_WARNINGS OFF
GO
ALTER DATABASE [test_sql] SET ARITHABORT OFF
GO
ALTER DATABASE [test_sql] SET AUTO_CLOSE OFF
GO
ALTER DATABASE [test_sql] SET AUTO_SHRINK OFF
GO
ALTER DATABASE [test_sql] SET AUTO_CREATE_STATISTICS ON
GO
ALTER DATABASE [test_sql] SET AUTO_UPDATE_STATISTICS ON
GO
ALTER DATABASE [test_sql] SET CURSOR_CLOSE_ON_COMMIT OFF
GO
ALTER DATABASE [test_sql] SET CURSOR_DEFAULT GLOBAL
GO
ALTER DATABASE [test_sql] SET CONCAT_NULL_YIELDS_NULL OFF
GO
ALTER DATABASE [test_sql] SET NUMERIC_ROUNDABORT OFF
GO
ALTER DATABASE [test_sql] SET QUOTED_IDENTIFIER OFF
GO
ALTER DATABASE [test_sql] SET RECURSIVE_TRIGGERS OFF
GO
ALTER DATABASE [test_sql] SET DISABLE_BROKER
GO
ALTER DATABASE [test_sql] SET AUTO_UPDATE_STATISTICS_ASYNC OFF
GO
ALTER DATABASE [test_sql] SET DATE_CORRELATION_OPTIMIZATION OFF
GO
ALTER DATABASE [test_sql] SET PARAMETERIZATION SIMPLE
GO
ALTER DATABASE [test_sql] SET READ_COMMITTED_SNAPSHOT OFF
GO
ALTER DATABASE [test_sql] SET READ_WRITE
GO
ALTER DATABASE [test_sql] SET RECOVERY FULL
GO
ALTER DATABASE [test_sql] SET MULTI_USER
GO
ALTER DATABASE [test_sql] SET PAGE_VERIFY CHECKSUM
GO
ALTER DATABASE [test_sql] SET TARGET_RECOVERY_TIME = 0 SECONDS
GO
ALTER DATABASE [test_sql] SET DELAYED_DURABILITY = DISABLED
GO
USE [test_sql]
GO
IF NOT EXISTS (SELECT name FROM sys.filegroups WHERE is_default=1 AND name = N'PRIMARY') ALTER DATABASE [test_sql] MODIFY FILEGROUP [PRIMARY] DEFAULT
GO
-- Srv login, DB user and schema creation
CREATE LOGIN [test_usr_login] WITH PASSWORD=N'test_usr_login', DEFAULT_DATABASE=[test_sql], DEFAULT_LANGUAGE=[us_english], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
GO
CREATE USER [test_usr] FOR LOGIN [test_usr_login] WITH DEFAULT_SCHEMA=[test_schema]
GO
CREATE SCHEMA [test_schema] AUTHORIZATION [test_usr]
GO
-- Table and stored proc creation
IF OBJECT_id("[test_schema].[test_tbl]", "U") IS NOT NULL
DROP TABLE [test_schema].[test_tbl];
GO
CREATE TABLE [test_schema].[test_tbl](
[tc] [nchar](10) NULL
) ON [PRIMARY]
GO
IF OBJECT_id("[dbo].[TA]", "P") IS NOT NULL
DROP PROCEDURE [dbo].[TA];
GO
CREATE PROCEDURE [dbo].[TA] AS BEGIN
SET NOCOUNT ON;
SELECT * FROM
(VALUES
('CURRENT_USER', CURRENT_USER),
('SCHEMA_NAME', SCHEMA_NAME()),
('have_UNqualified_select', cast(HAS_PERMS_BY_NAME("[test_tbl]", "OBJECT", "SELECT") as nchar(10))),
('have_qualified_select', cast(HAS_PERMS_BY_NAME("[test_schema].[test_tbl]", "OBJECT", "SELECT") as nchar(10)))
) AS tmptbl([key], val); -- select permissions fro [test_tbl] of the current user
SELECT tc as qualified_tc FROM [test_schema].[test_tbl]; -- qualified select
SELECT tc as UNqualified_tc from [test_tbl]; -- unqualified select fails with Msg 208
END
GO
GRANT EXECUTE ON [dbo].[TA] TO [test_usr]
GO
テストスクリプト:再生する
スクリプト(<MDF>
と<LDF>
はappropritateファイルパスとの置換を必要とする)
USE [test_sql]
GO
DECLARE @return_value int
execute as login = N'test_usr_login'; -- even when logged in with test_usr_logn, Msg 208 occurs
EXEC @return_value = [dbo].[TA]
revert
SELECT 'Return Value' = @return_value
GO
出力メッセージ:
メッセージ208、レベル16 、状態1、プロシージャTA、行14無効なオブジェクト名 'test_tbl'。
(1行(複数可)の影響を受ける)
出力結果:
key val
CURRENT_USER test_usr
SCHEMA_NAME test_schema
have_UNqualified_select 1
have_qualified_select 1
私が説明した問題の解決に光をもたらす可能性が誰をいただければ幸いです。
スキーマ "test_schema"に "test_tbl"テーブルを作成しましたが、プロシージャでスキーマを指定しませんでした。とにかく、スキーマを指定する必要がある場合は、デフォルトのスキーマとして実行することがわかります。 –
@SeanLange共有APIのコンセプトは、修飾されていない「test_tbl」によって実装されています。このテーブルには、デフォルトのスキーマ([MSDN](https://msdn.microsoft.com/en-us/library/ms190387.aspx) )。それ以外の場合は、スキーマ名の依存関係のため、APIを共有として提供できません。私は私の質問に光をもたらします[SOF](/質問/ 27357352/SQL-デフォルト・スキーマ解像度・イン・ストアド・プロシージャ)で、別の同様の質問を見つけました。 –