Problema com as convenções de nomenclatura de tabelas e o gerenciamento de políticas no SQL Server 2016


10

No SQL Server 2012, eu tinha uma política definida para não permitir espaços no nome de uma tabela. No entanto, quando uso a mesma política no SQL Server 2016, recebo um erro.

Aqui está o código para a condição:

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

Aqui está o código para a política:

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

No SQL Server 2012 e 2014, isso fornece os resultados esperados:

CREATE TABLE [test table]
(Id INT NULL)

A política 'Nomes da tabela' foi violada por 'SQLSERVER: \ SQL \ LSRSQL07 \ SQL2012 \ Databases \ test \ Tables \ dbo.test table'. Esta transação será revertida. Condição da política: '@Name NOT LIKE'% [-.]% 'AND @Name NOT LIKE'% [^ A-Za-z0-9 [_]]% '' Descrição da política: '' Ajuda adicional: '': Instrução '': 'CREATE TABLE [tabela de teste] (ID INT NULL)'. Msg 3609, Nível 16, Estado 1, Procedimento sp_syspolicy_dispatch_event, Linha 65 [Linha Inicial do Lote 48] A transação terminou no gatilho. O lote foi abortado.

E se eu executar o seguinte código, não recebo erro:

CREATE TABLE [testtable]
(Id INT NULL)

No entanto, se eu executar qualquer CREATE TABLEinstrução, com a política ativada, no SQL Server 2016, recebo o seguinte erro:

A política 'Nomes de tabelas' foi violada por 'SQLSERVER: \ SQL \ LSRSQL07 \ SQL2016 \ Databases \ test \ Tables \ dbo.testtable'. Esta transação será revertida. Condição da política: '@Name NOT LIKE'%% '' Descrição da política: '' Ajuda adicional: '': '' Instrução: 'CREATE TABLE [testtable] (ID INT NULL)'. Mensagem 515, Nível 16, Estado 2, Procedimento sp_syspolicy_execute_policy, Linha 69 [Linha Inicial do Lote 44] Não é possível inserir o valor NULL na coluna 'target_query_expression', tabela 'msdb.dbo.syspolicy_policy_execution_history_details_internal'; A coluna não permite nulos. INSERT falha. A instrução foi encerrada.

No SQL Server 2016, não consigo criar nenhuma tabela , passando ou não a condição.

Este é o SQL Server 2016, SP1, CU3.

Alguma idéia sobre isso?

Editar: estou precisando que o modo de avaliação seja "Em alteração: impedir"

Respostas:


6

Testaram os scripts em uma instância CU2 do SQL Server 2016 SP1 e a diretiva funcionará se o modo Avaliação estiver definido como "Ao alterar: impedir". (existe um erro que não permite avaliar políticas que usam facetas específicas).

Enquanto isso, se você usar apenas a política para nomes de tabelas, também poderá tentar a faceta "Opção de Tabela" em vez de "MultipartName", com a mesma configuração ( @NAME NOT LIKE '% %').


Se eu definir o modo de avaliação como "On Demand", ele funcionará, mas para ser justo, eu não tinha tentado isso anteriormente. Eu preferiria ter essa alteração: impeça a impedir que as pessoas criem tabelas e, em seguida, procs armazenados fazendo referência às tabelas com nomes incorretos.
— John

Para mim, não funciona definir o modo de avaliação como "Sob demanda" e avaliar a política manualmente. Mas funciona bem se a avaliação estiver definida como "Ao alterar: impedir" e tentar criar tabelas. Você pode tentar postar o problema no Microsoft Connect para descobrir se é um bug ou não.
— Dragos

Obrigado, @Dragos. Está acontecendo em qualquer mesa, mesmo aquelas que devem passar pela condição?
— John

As tabelas que não possuem espaços em branco no nome são criadas com êxito e as que possuem espaços em branco falham com um erro de violação da política.
— Dragos

Estamos enfrentando o mesmo problema com o procedimento armazenado e as facetas de exibição. Estamos no SQL 2016 SP1 CU3 (mais recente). Como John afirmou, isso parece um bug, mas estava pensando se alguém seria capaz de descobrir uma solução alternativa?
— dbauser
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.