Problème avec les conventions d'appellation des tables et la gestion des stratégies dans SQL Server 2016

10

Dans SQL Server 2012, j'avais un ensemble de règles pour ne pas autoriser les espaces dans un nom de table. Cependant, lorsque j'utilise la même stratégie dans SQL Server 2016, j'obtiens une erreur.

Voici le code de la condition:

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

Voici le code de la stratégie:

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

Dans SQL Server 2012 et 2014, cela donne les résultats attendus:

CREATE TABLE [test table]
(Id INT NULL)

La stratégie «Noms de table» a été violée par «SQLSERVER: \ SQL \ LSRSQL07 \ SQL2012 \ Databases \ test \ Tables \ dbo.test table». Cette transaction sera annulée. Condition de stratégie: '@Name NOT LIKE'% [-.]% 'ET @Name NOT LIKE'% [^ A-Za-z0-9 [_]]% '' Description de la stratégie: '' Aide supplémentaire: '': '' Instruction: 'CREATE TABLE [table de test] (Id INT NULL)'. Msg 3609, niveau 16, état 1, procédure sp_syspolicy_dispatch_event, ligne 65 [ligne de démarrage du lot 48] La transaction s'est terminée dans le déclencheur. Le lot a été abandonné.

Et si j'exécute le code suivant, je ne reçois aucune erreur:

CREATE TABLE [testtable]
(Id INT NULL)

Cependant, si j'exécute une CREATE TABLEinstruction, avec la stratégie activée, sur SQL Server 2016, j'obtiens l'erreur suivante:

La stratégie «Noms de table» a été violée par «SQLSERVER: \ SQL \ LSRSQL07 \ SQL2016 \ Databases \ test \ Tables \ dbo.testtable». Cette transaction sera annulée. Condition de stratégie: '@Name NOT LIKE'%% '' Description de la stratégie: '' Aide supplémentaire: '': '' Instruction: 'CREATE TABLE [testtable] (Id INT NULL)'. Msg 515, niveau 16, état 2, procédure sp_syspolicy_execute_policy, ligne 69 [ligne de démarrage par lots 44] Impossible d'insérer la valeur NULL dans la colonne 'target_query_expression', table 'msdb.dbo.syspolicy_policy_execution_history_details_internal'; la colonne n'autorise pas les valeurs NULL. INSERT échoue. La déclaration est terminée.

Dans SQL Server 2016, je ne peux pas créer de table , qu'elle passe la condition ou non.

Il s'agit de SQL Server 2016, SP1, CU3.

Des idées à ce sujet?

Edit: J'ai besoin que le mode d'évaluation soit "On change: prevent"

John
la source

Réponses:

6

Tester les scripts sur une instance SQL Server 2016 SP1 CU2 et la stratégie fonctionne si le mode d'évaluation est défini sur «En cas de changement: empêcher». (il y a un bogue qui ne vous permet pas d'évaluer les politiques qui utilisent des facettes spécifiques).

Pendant ce temps, si vous utilisez uniquement la stratégie pour les noms de table, vous pouvez également essayer la facette "Option de table" au lieu de "MultipartName", avec la même configuration ( @NAME NOT LIKE '% %').

Dragos
la source
Si j'ai défini le mode d'évaluation sur "On Demand", cela fonctionne, mais pour être honnête, je n'avais pas essayé auparavant. Je préférerais que ce changement soit activé: empêchez les gens de créer des tables, puis des procs stockés référençant les tables mal nommées.
John
Pour moi, cela ne fonctionne pas de définir le mode d'évaluation sur "Sur demande" et d'évaluer la politique manuellement. Mais cela fonctionne bien si l'évaluation est définie sur "En cas de changement: empêcher" et essayez de créer des tables. Vous pouvez essayer de publier le problème sur Microsoft Connect pour savoir s'il s'agit d'un bogue ou non.
Dragos
Merci, @Dragos. Cela se passe-t-il sur n'importe quelle table, même celles qui devraient passer la condition?
John
Les tables qui n'ont pas d'espaces blancs dans le nom sont créées avec succès et celles qui ont des espaces blancs échouent avec une erreur de violation de stratégie.
Dragos
Nous rencontrons le même problème avec les procédures stockées et les facettes de vue. Nous sommes sur le SQL 2016 SP1 CU3 (Latest). Comme John l'a déclaré, cela semble être un bug, mais je me demandais si quelqu'un était en mesure de trouver une solution?
DBAuser