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.