MS SQL Server 2014 DB에서 공유 API를 구현하려고합니다. 이 아키텍처에서 스키마는 비슷한 구조를 가져야하고 dbo가 소유 한 공유 API를 사용해야하며 동시에 자신의 API를 노출해야합니다. 개체 이름을 지정하지 않고 서로를 호출하려면 EXECUTE AS USER
문이 현재 사용자의 특정 기본 스키마로 컨텍스트를 전환하는 데 사용됩니다. 저장된 프로 시저에서 사용자의 기본 스키마를 통해 액세스 할 때 SQL Server에서 사용자 전환시
문제
은 여기에서 : 사용 문맥 전환 즉각적인 액세스가 미세한 (예컨대SELECT * from test_tbl;
하였다
EXECUTE AS USER
) 동작, 저장 프로 시저의 기본 스키마를 통해 액세스 오류
Msg 208, Level 16, State 1
실패있다.
내 질문을 게시하기 전에 많은 실험과 테스트를 시도하고 MSDN, 웹 및 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] (/ questions/27357352/sql-default-schema-resolution-in-stored-procedure)와 비슷한 또 다른 질문을 발견했습니다. –