CLR을 사용하지 않고 데이터베이스 레벨 상수 (열거)를 작성 하시겠습니까?


9

원하는 요청 상태에 따라 대체 조치를 수행해야하는 여러 SQL 오브젝트가 있습니다. 저장 프로 시저, 테이블 반환 함수에 전달하고 쿼리에 사용할 수있는 데이터베이스 수준 상수 (열거)를 만드는 방법이 있습니까 (CLR을 사용하지 않고)?

CREATE PROCEDURE dbo.DoSomeWork(@param1 INTEGER, ..., @EnumValue myEnumType)  AS ...;

그리고 그것을 사용하십시오 :

EXEC doSomeWork 85, ..., (myEnumType.EnumValue1 + myEnumType.EnumValue2);

어디 myEnumType몇 가지 열거 값을 저장한다.

절차 에서 필요한 작업을 수행하기 위해 @EnumValue값 을 사용 하여 테스트하고 사용할 수 myEnumType있습니다. 내가 myEnumType고려하고있는 경우 에 대한 비트 마스크 의 값을 만들 것 입니다.

간단한 예를 들어, 거대한 데이터 세트를 가져 와서 더 작지만 여전히 큰 데이터 세트로 줄이는 고가의 프로세스를 고려하십시오. 이 프로세스에서는 결과 중간에 해당 프로세스 중간에 조정이 필요합니다. 이것이 축소 내의 중간 계산 상태에 따라 일부 유형의 레코드를 필터링하는 필터라고 가정하십시오. @EnumValue유형은 myEnumType이것에 대한 테스트에 사용될 수있다

SELECT   ...
FROM     ...
WHERE       (@EnumValue & myEnumType.EnumValue1 = myEnumType.EnumValue1 AND ...)
        OR  (@EnumValue & myEnumType.EnumValue2 = myEnumType.EnumValue2 AND ...)
        OR  ...

CLR을 사용하지 않고 SQL Server에서 이러한 종류의 데이터베이스 수준 상수가 가능합니까?

저장 프로 시저, 함수 등에 매개 변수로 전달할 수 있는 데이터베이스 수준 열거 또는 상수 집합을 찾고 있습니다.

답변:


9

XML 스키마를 사용하여 SQL Server에서 열거 유형을 만들 수 있습니다.

예를 들어 색상.

create xml schema collection ColorsEnum as '
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="Color">
        <xs:simpleType>
            <xs:restriction base="xs:string"> 
                <xs:enumeration value="Red"/>
                <xs:enumeration value="Green"/>
                <xs:enumeration value="Blue"/>
                <xs:enumeration value="Yellow"/>
            </xs:restriction> 
        </xs:simpleType>
    </xs:element>
</xs:schema>';

이를 통해 유형의 변수 또는 매개 변수를 사용할 수 있습니다 xml(dbo.ColorsEnum).

declare @Colors xml(dbo.ColorsEnum);
set @Colors = '<Color>Red</Color><Color>Green</Color>'

색이 아닌 것을 추가하려고하면

set @Colors = '<Color>Red</Color><Color>Ferrari</Color>';

오류가 발생합니다.

Msg 6926, Level 16, State 1, Line 43
XML Validation: Invalid simple type value: 'Ferrari'. Location: /*:Color[2]

이와 같이 XML을 구성하는 것은 약간 지루할 수 있으므로 예를 들어 허용 된 값을 보유하는 도우미보기를 만들 수 있습니다.

create view dbo.ColorsConst as
select cast('<Color>Red</Color>' as varchar(100)) as Red,
       cast('<Color>Green</Color>' as varchar(100)) as Green,
       cast('<Color>Blue</Color>' as varchar(100)) as Blue,
       cast('<Color>Yellow</Color>' as varchar(100)) as Yellow;

그리고 이것을 사용하여 열거를 만듭니다.

set @Colors = (select Red+Blue+Green from dbo.ColorsConst);

XML 스키마에서 동적으로보기를 작성하려면이 조회를 사용하여 색상을 추출 할 수 있습니다.

select C.Name
from (select xml_schema_namespace('dbo','ColorsEnum')) as T(X)
  cross apply T.X.nodes('//*:enumeration') as E(X)
  cross apply (select E.X.value('@value', 'varchar(100)')) as C(Name);

열거는 물론 함수와 프로 시저에 대한 매개 변수로 사용될 수도 있습니다.

create function dbo.ColorsToString(@Colors xml(ColorsEnum))
returns varchar(100)
as
begin
  declare @T table(Color varchar(100));

  insert into @T(Color)
  select C.X.value('.', 'varchar(100)')
  from @Colors.nodes('Color') as C(X);

  return stuff((select ','+T.Color
                from @T as T
                for xml path('')), 1, 1, '');
end
create procedure dbo.GetColors
  @Colors xml(ColorsEnum)
as
select C.X.value('.', 'varchar(100)') as Color
from @Colors.nodes('Color') as C(X);
declare @Colors xml(ColorsEnum) = '
<Color>Red</Color>
<Color>Blue</Color>
';

select dbo.ColorsToString(@Colors);

set @Colors = (select Red+Blue+Green from dbo.ColorsConst);
exec dbo.GetColors @Colors;

6

SQL Server 2016을 사용하고 있기 때문에 다른 가능한 옵션 옵션 을 포기하고 싶습니다 SESSION_CONTEXT.

Leonard Lobel의 기사 인 SQL Server 2016의 상태 공유와 함께 SQL Server 2016SESSION_CONTEXT 의이 새로운 기능에 대한 유용한 정보가 있습니다.

몇 가지 핵심 사항을 요약하면 다음과 같습니다.

데이터베이스 연결 수명 동안 모든 저장 프로 시저와 배치에서 세션 상태를 공유하고 싶었다면 좋아할 것 SESSION_CONTEXT입니다. SQL Server 2016에 연결하면 상태 저장 사전 또는 종종 상태 백이라고하는 문자열 및 숫자와 같은 값을 저장 한 다음 할당 한 키로 검색 할 수 있습니다. 의 경우 SESSION_CONTEXT키는 임의의 문자열이고 값은 sql_variant이므로 다양한 유형을 수용 할 수 있습니다.

에 무언가를 저장 SESSION_CONTEXT하면 연결이 닫힐 때까지 그대로 유지됩니다. 데이터베이스의 어떤 테이블에도 저장되지 않으며 연결이 유지되는 한 메모리에 남아 있습니다. 또한 저장 프로 시저, 트리거, 함수 등에서 실행되는 모든 T-SQL 코드는 사용자가 입력 한 모든 것을 공유 할 수 있습니다 SESSION_CONTEXT.

우리가왔다 지금까지 했어 같은 가장 가까운 것은 CONTEXT_INFO저장하고 (128)에 하나의 이진 값을 공유 할 수 있습니다, 당신이 얻을 사전보다 훨씬 덜 유연하다, 바이트 길이의 SESSION_CONTEXT서로 다른 여러 개의 데이터 값을 지원, 유형.

SESSION_CONTEXTsp_set_session_context를 호출하여 원하는 키로 값을 저장하십시오. 이를 수행 할 때 물론 키와 값을 제공하지만 read_only 매개 변수를 true로 설정할 수도 있습니다. 이것은 세션 컨텍스트에서 값을 잠그므로 연결의 나머지 수명 동안 변경할 수 없습니다. 예를 들어, 클라이언트 응용 프로그램이이 스토어드 프로 시저를 호출하여 데이터베이스 연결을 설정 한 직후 일부 세션 컨텍스트 값을 설정하기 쉽습니다. 응용 프로그램이이 작업을 수행 할 때 read_only 매개 변수를 설정하면 서버에서 실행되는 저장 프로 시저 및 기타 T-SQL 코드는 값만 읽을 수 있으며 클라이언트에서 실행중인 응용 프로그램에서 설정 한 내용은 변경할 수 없습니다.

테스트로 일부 CONTEXT_SESSION정보 를 설정하는 서버 로그인 트리거를 만들었습니다.이 중 하나가 SESSION_CONTEXT로 설정되었습니다 @read_only.

DROP TRIGGER IF EXISTS [InitializeSessionContext] ON ALL SERVER
GO
CREATE TRIGGER InitializeSessionContext ON ALL SERVER
FOR LOGON AS

BEGIN

    --Initialize context information that can be altered in the session
    EXEC sp_set_session_context @key = N'UsRegion'
        ,@value = N'Southeast'

    --Initialize context information that cannot be altered in the session
    EXEC sp_set_session_context @key = N'CannotChange'
        ,@value = N'CannotChangeThisValue'
        ,@read_only = 1

END;

완전히 새로운 사용자로 로그인하여 SESSION_CONTEXT정보 를 추출 할 수있었습니다 .

DECLARE @UsRegion varchar(20)
SET @UsRegion = CONVERT(varchar(20), SESSION_CONTEXT(N'UsRegion'))
SELECT DoThat = @UsRegion

DECLARE @CannotChange varchar(20)
SET @CannotChange = CONVERT(varchar(20), SESSION_CONTEXT(N'CannotChange'))
SELECT DoThat = @CannotChange

나는 'read_only'컨텍스트 정보를 변경하려고 시도했습니다.

EXEC sp_set_session_context @key = N'CannotChange'
    ,@value = N'CannotChangeThisValue'

오류가 발생했습니다.

메시지 15664, 수준 16, 상태 1, 절차 sp_set_session_context, 줄 1 [배치 시작 줄 8] 세션 컨텍스트에서 'CannotChange'키를 설정할 수 없습니다. 이 세션에서 키가 read_only로 설정되었습니다.

로그인 트리거에 대한 중요한 참고 사항 ( 이 게시물에서 )!

로그온 트리거는 sysadmin 고정 서버 역할의 구성원을 포함하여 모든 사용자가 데이터베이스 엔진에 성공적으로 연결하는 것을 효과적으로 방지 할 수 있습니다. 로그온 트리거가 연결을 방해하는 경우 sysadmin 고정 서버 역할의 구성원은 전용 관리자 연결을 사용하거나 최소 구성 모드 (-f)에서 데이터베이스 엔진을 시작하여 연결할 수 있습니다.


잠재적 인 단점은 세션 컨텍스트 인스턴스를 데이터베이스 전체가 아니라 채 웁니다. 이 시점에서 내가 생각할 수있는 유일한 옵션은 다음과 같습니다.

  1. Session_Context다른 데이터베이스에서 동일한 유형 이름에 충돌이 발생하지 않도록 이름-값 쌍 의 이름 앞에 데이터베이스 이름을 붙여 이름을 지정하십시오. Session_Context모든 사용자의 모든 이름-값을 사전 정의하는 문제를 해결하지는 못합니다 .
  2. 로그인 트리거가 발생 EventData하면 로그인 사용자를 추출하는 데 사용할 수있는 (xml)에 액세스 할 수 있으며이를 기반으로 특정 Session_Context이름-값 쌍을 작성할 수 있습니다 .

4

SQL Server에서는 아니요 (1998 년에 Oracle 패키지에서 상수를 생성 한 것을 기억하지만 SQL Server에서 상수를 놓친 경우가 있음).

그리고 방금 테스트 한 결과 SQLCLR 로이 작업을 수행 할 수는 없습니다. 적어도 모든 경우에 작동한다는 의미는 아닙니다. 보류는 저장 프로 시저 매개 변수에 대한 제한 사항입니다. .또는 ::매개 변수 이름을 가질 수없는 것 같습니다 . 나는 시도했다 :

EXEC MyStoredProc @ParamName = SchemaName.UdtName::[StaticField];

-- and:

DECLARE @Var = SchemaName.UdtName = 'something';
EXEC MyStoredProc @ParamName = @Var.[InstanceProperty];

두 경우 모두 SET PARSEONLY ON;다음과 같은 이유로 파싱 ​​단계 (을 사용하여 확인)를 통과하지 못했습니다 .

메시지 102, 수준 15, 상태 1, 줄 xxxxx
'.'근처의 구문이 잘못되었습니다.

반면에 두 방법 모두 사용자 정의 함수 매개 변수에 대해 작동했습니다.

SELECT MyUDF(SchemaName.UdtName::[StaticField]);

-- and:

DECLARE @Var = SchemaName.UdtName = N'something';
SELECT MyUDF(@Var.[InstanceProperty]);

따라서 실제로 할 수있는 최선의 방법은 SQLCLR을 사용하여 UDF, TVF, UDA (내가 가정) 및 쿼리와 직접 작동하는 것을 저장 한 다음 저장 프로 시저와 함께 사용해야 할 때 로컬 변수에 할당하는 것입니다.

DECLARE @VarInt = SchemaName.UdtName::[StaticField];
EXEC MyStoredProc @ParamName = @VarInt;

이것은 실제 열거 형 값을 가질 수있는 기회가있을 때 취한 접근법입니다 (사용법 / 의미에 따라 특정 조회 테이블에 있어야하는 조회 값과 반대).


"constant"/ "enum"값을 추출하기 위해 UDF (User-Defined Function)로이를 시도하는 것과 관련하여 Stored Procedure 매개 변수로 전달하는 측면에서 작동하지 못했습니다.

EXEC MyStoredProc @ParamName = FunctionName(N'something');

문자열을 숫자로 바꾸더라도 SSMS가 괄호 안의 모든 것을 강조 표시하거나 전달할 매개 변수가없는 경우 오른쪽 괄호를 사용하여 "잘못된 구문"오류를 반환합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.