SQL Server 2016의 테이블 명명 규칙 및 정책 관리 관련 문제


10

SQL Server 2012에서는 테이블 이름에 공백을 허용하지 않는 정책이 설정되었습니다. 그러나 SQL Server 2016에서 동일한 정책을 사용하면 오류가 발생합니다.

조건 코드는 다음과 같습니다.

DECLARE @condition_id INT
EXEC msdb.dbo.sp_syspolicy_add_condition @name=N'No Spaces', @description=N'No spaces in table names.', @facet=N'IMultipartNameFacet', @expression=N'<Operator>
  <TypeClass>Bool</TypeClass>
  <OpType>NOT_LIKE</OpType>
  <Count>2</Count>
  <Attribute>
    <TypeClass>String</TypeClass>
    <Name>Name</Name>
  </Attribute>
  <Constant>
    <TypeClass>String</TypeClass>
    <ObjType>System.String</ObjType>
    <Value>% %</Value>
  </Constant>
</Operator>', @is_name_condition=4, @obj_name=N'% %', @condition_id=@condition_id OUTPUT
SELECT @condition_id

정책 코드는 다음과 같습니다.

DECLARE @object_set_id INT
EXEC msdb.dbo.sp_syspolicy_add_object_set @object_set_name=N'Table Names_ObjectSet', @facet=N'IMultipartNameFacet', @object_set_id=@object_set_id OUTPUT
SELECT @object_set_id

DECLARE @target_set_id INT
EXEC msdb.dbo.sp_syspolicy_add_target_set @object_set_name=N'Table Names_ObjectSet', @type_skeleton=N'Server/Database/Sequence', @type=N'SEQUENCE', @enabled=False, @target_set_id=@target_set_id OUTPUT
SELECT @target_set_id

EXEC msdb.dbo.sp_syspolicy_add_target_set_level @target_set_id=@target_set_id, @type_skeleton=N'Server/Database', @level_name=N'Database', @condition_name=N'', @target_set_level_id=0
EXEC msdb.dbo.sp_syspolicy_add_target_set_level @target_set_id=@target_set_id, @type_skeleton=N'Server/Database/Sequence', @level_name=N'Sequence', @condition_name=N'', @target_set_level_id=0

EXEC msdb.dbo.sp_syspolicy_add_target_set @object_set_name=N'Table Names_ObjectSet', @type_skeleton=N'Server/Database/StoredProcedure', @type=N'PROCEDURE', @enabled=False, @target_set_id=@target_set_id OUTPUT
SELECT @target_set_id

EXEC msdb.dbo.sp_syspolicy_add_target_set_level @target_set_id=@target_set_id, @type_skeleton=N'Server/Database', @level_name=N'Database', @condition_name=N'', @target_set_level_id=0
EXEC msdb.dbo.sp_syspolicy_add_target_set_level @target_set_id=@target_set_id, @type_skeleton=N'Server/Database/StoredProcedure', @level_name=N'StoredProcedure', @condition_name=N'', @target_set_level_id=0

EXEC msdb.dbo.sp_syspolicy_add_target_set @object_set_name=N'Table Names_ObjectSet', @type_skeleton=N'Server/Database/Synonym', @type=N'SYNONYM', @enabled=False, @target_set_id=@target_set_id OUTPUT
SELECT @target_set_id

EXEC msdb.dbo.sp_syspolicy_add_target_set_level @target_set_id=@target_set_id, @type_skeleton=N'Server/Database', @level_name=N'Database', @condition_name=N'', @target_set_level_id=0
EXEC msdb.dbo.sp_syspolicy_add_target_set_level @target_set_id=@target_set_id, @type_skeleton=N'Server/Database/Synonym', @level_name=N'Synonym', @condition_name=N'', @target_set_level_id=0

EXEC msdb.dbo.sp_syspolicy_add_target_set @object_set_name=N'Table Names_ObjectSet', @type_skeleton=N'Server/Database/Table', @type=N'TABLE', @enabled=True, @target_set_id=@target_set_id OUTPUT
SELECT @target_set_id

EXEC msdb.dbo.sp_syspolicy_add_target_set_level @target_set_id=@target_set_id, @type_skeleton=N'Server/Database', @level_name=N'Database', @condition_name=N'', @target_set_level_id=0
EXEC msdb.dbo.sp_syspolicy_add_target_set_level @target_set_id=@target_set_id, @type_skeleton=N'Server/Database/Table', @level_name=N'Table', @condition_name=N'', @target_set_level_id=0

EXEC msdb.dbo.sp_syspolicy_add_target_set @object_set_name=N'Table Names_ObjectSet', @type_skeleton=N'Server/Database/UserDefinedFunction', @type=N'FUNCTION', @enabled=False, @target_set_id=@target_set_id OUTPUT
SELECT @target_set_id

EXEC msdb.dbo.sp_syspolicy_add_target_set_level @target_set_id=@target_set_id, @type_skeleton=N'Server/Database', @level_name=N'Database', @condition_name=N'', @target_set_level_id=0
EXEC msdb.dbo.sp_syspolicy_add_target_set_level @target_set_id=@target_set_id, @type_skeleton=N'Server/Database/UserDefinedFunction', @level_name=N'UserDefinedFunction', @condition_name=N'', @target_set_level_id=0

EXEC msdb.dbo.sp_syspolicy_add_target_set @object_set_name=N'Table Names_ObjectSet', @type_skeleton=N'Server/Database/UserDefinedType', @type=N'TYPE', @enabled=False, @target_set_id=@target_set_id OUTPUT
SELECT @target_set_id

EXEC msdb.dbo.sp_syspolicy_add_target_set_level @target_set_id=@target_set_id, @type_skeleton=N'Server/Database', @level_name=N'Database', @condition_name=N'', @target_set_level_id=0
EXEC msdb.dbo.sp_syspolicy_add_target_set_level @target_set_id=@target_set_id, @type_skeleton=N'Server/Database/UserDefinedType', @level_name=N'UserDefinedType', @condition_name=N'', @target_set_level_id=0

EXEC msdb.dbo.sp_syspolicy_add_target_set @object_set_name=N'Table Names_ObjectSet', @type_skeleton=N'Server/Database/View', @type=N'VIEW', @enabled=False, @target_set_id=@target_set_id OUTPUT
SELECT @target_set_id

EXEC msdb.dbo.sp_syspolicy_add_target_set_level @target_set_id=@target_set_id, @type_skeleton=N'Server/Database', @level_name=N'Database', @condition_name=N'', @target_set_level_id=0
EXEC msdb.dbo.sp_syspolicy_add_target_set_level @target_set_id=@target_set_id, @type_skeleton=N'Server/Database/View', @level_name=N'View', @condition_name=N'', @target_set_level_id=0

EXEC msdb.dbo.sp_syspolicy_add_target_set @object_set_name=N'Table Names_ObjectSet', @type_skeleton=N'Server/Database/XmlSchemaCollection', @type=N'XMLSCHEMACOLLECTION', @enabled=False, @target_set_id=@target_set_id OUTPUT
SELECT @target_set_id

EXEC msdb.dbo.sp_syspolicy_add_target_set_level @target_set_id=@target_set_id, @type_skeleton=N'Server/Database', @level_name=N'Database', @condition_name=N'', @target_set_level_id=0
EXEC msdb.dbo.sp_syspolicy_add_target_set_level @target_set_id=@target_set_id, @type_skeleton=N'Server/Database/XmlSchemaCollection', @level_name=N'XmlSchemaCollection', @condition_name=N'', @target_set_level_id=0


GO

DECLARE @policy_id INT
EXEC msdb.dbo.sp_syspolicy_add_policy @name=N'Table Names', @condition_name=N'No Spaces', @policy_category=N'', @description=N'', @help_text=N'', @help_link=N'', @schedule_uid=N'00000000-0000-0000-0000-000000000000', @execution_mode=1, @is_enabled=True, @policy_id=@policy_id OUTPUT, @root_condition_name=N'', @object_set=N'Table Names_ObjectSet'
SELECT @policy_id


GO

SQL Server 2012 및 2014에서는 다음과 같은 예상 결과를 제공합니다.

CREATE TABLE [test table]
(Id INT NULL)

정책 '테이블 이름'이 'SQLSERVER : \ SQL \ LSRSQL07 \ SQL2012 \ Databases \ test \ Tables \ dbo.test table'에 의해 위반되었습니다. 이 거래는 롤백됩니다. 정책 조건 : '@ 이름이 아님'% [-.] % '및 @ 이름이 아님'% [^ A-Za-z0-9 [_]] % ''정책 설명 : ''추가 도움말 : '': ''명령문 : 'CREATE TABLE [test table] (Id INT NULL)'. 메시지 3609, 수준 16, 상태 1, 절차 sp_syspolicy_dispatch_event, 줄 65 [배치 시작 줄 48] 트랜잭션이 트리거에서 종료되었습니다. 일괄 처리가 중단되었습니다.

그리고 다음 코드를 실행하면 오류가 발생하지 않습니다.

CREATE TABLE [testtable]
(Id INT NULL)

그러나 CREATE TABLESQL Server 2016에서 정책을 사용하도록 설정 한 명령문을 실행 하면 다음 오류가 발생합니다.

정책 '테이블 이름'이 'SQLSERVER : \ SQL \ LSRSQL07 \ SQL2016 \ Databases \ test \ Tables \ dbo.testtable'에 의해 위반되었습니다. 이 거래는 롤백됩니다. 정책 조건 : '@ 이름이'%%이 아님 '정책 설명 :' '추가 도움말 :' ':' '명령문 :'CREATE TABLE [testtable] (Id INT NULL) '. 메시지 515, 수준 16, 상태 2, 절차 sp_syspolicy_execute_policy, 줄 69 [배치 시작 줄 44] 열 'target_query_expression', 테이블 'msdb.dbo.syspolicy_policy_execution_history_details_internal'열에 NULL 값을 삽입 할 수 없습니다. 열은 널을 허용하지 않습니다. INSERT에 실패했습니다. 그 진술서는 만료되었습니다.

SQL Server 2016에서는 조건을 통과했는지 여부에 관계 없이 테이블을 만들 수 없습니다.

SQL Server 2016, SP1, CU3입니다.

이것에 대한 아이디어가 있습니까?

편집 : 평가 모드가 "변경시 : 예방"이어야합니다.

답변:


6

SQL Server 2016 SP1 CU2 인스턴스에서 스크립트를 테스트했으며 평가 모드가 "변경시 : 방지"로 설정된 경우 정책이 작동합니다. (이 버그 특정 측면을 사용하는 정책을 평가하지 않습니다).

한편 테이블 이름에 대해서만 정책을 사용하는 경우 동일한 구성 ( @NAME NOT LIKE '% %')으로 "MultipartName"대신 "Table Option"패싯을 시도 할 수도 있습니다 .


평가 모드를 "주문형"으로 설정하면 작동하지만 공정하기 위해 이전에는 시도하지 않았습니다. 나는 사람들이 테이블을 만들지 못하게하고 이름이 나쁜 테이블을 참조하는 저장된 procs를 방지하는 것을 원합니다.
John

나를 위해 평가 모드를 "주문형"으로 설정하고 정책을 수동으로 평가하는 것은 효과가 없습니다. 그러나 평가가 "변경시 : 예방"으로 설정되어 있고 테이블을 만들려고하면 제대로 작동합니다. 버그가 있는지 확인하기 위해 Microsoft Connect에 문제를 게시 할 수 있습니다.
Dragos

감사합니다, @Dragos. 조건을 통과 해야하는 테이블조차도 모든 테이블에서 발생합니까?
John

이름에 공백이없는 테이블은 성공적으로 작성되고 공백이있는 테이블은 정책 위반 오류로 실패합니다.
Dragos

저장 프로 시저 및 뷰 패싯과 동일한 문제가 있습니다. 우리는 SQL 2016 SP1 CU3 (최신)에 있습니다. John이 말했듯이, 이것은 버그처럼 보이지만 해결 방법을 알아낼 수 있는지 궁금하십니까?
DBAuser
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.