Problema con las convenciones de nomenclatura de tablas y la administración de políticas en SQL Server 2016

10

En SQL Server 2012, tenía un conjunto de políticas para no permitir espacios en un nombre de tabla. Sin embargo, cuando uso la misma política en SQL Server 2016, aparece un error.

Aquí está el código para la condición:

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

Aquí está el código para la 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

En SQL Server 2012 y 2014, esto proporciona los resultados esperados:

CREATE TABLE [test table]
(Id INT NULL)

La política 'Nombres de tabla' ha sido violada por 'SQLSERVER: \ SQL \ LSRSQL07 \ SQL2012 \ Databases \ test \ Tables \ dbo.test table'. Esta transacción se revertirá. Condición de la política: '@Name NOT LIKE'% [-.]% 'AND @Name NOT LIKE'% [^ A-Za-z0-9 [_]]% '' Descripción de la política: '' Ayuda adicional: '': '' Declaración: 'CREATE TABLE [tabla de prueba] (Id INT NULL)'. Msg 3609, Nivel 16, Estado 1, Procedimiento sp_syspolicy_dispatch_event, Línea 65 [Línea de inicio de lote 48] La transacción finalizó en el activador. El lote ha sido abortado.

Y si ejecuto el siguiente código, no obtengo ningún error:

CREATE TABLE [testtable]
(Id INT NULL)

Sin embargo, si ejecuto alguna CREATE TABLEdeclaración, con la política habilitada, en SQL Server 2016, aparece el siguiente error:

La política 'Nombres de tabla' ha sido violada por 'SQLSERVER: \ SQL \ LSRSQL07 \ SQL2016 \ Databases \ test \ Tables \ dbo.testtable'. Esta transacción se revertirá. Condición de la política: '@Name NOT LIKE'%% '' Descripción de la política: '' Ayuda adicional: '': '' Declaración: 'CREATE TABLE [testtable] (Id INT NULL)'. Mensaje 515, Nivel 16, Estado 2, Procedimiento sp_syspolicy_execute_policy, Línea 69 [Línea de inicio de lote 44] No se puede insertar el valor NULL en la columna 'target_query_expression', tabla 'msdb.dbo.syspolicy_policy_execution_history_details_internal'; La columna no permite nulos. INSERTAR falla. La instrucción se ha terminado.

En SQL Server 2016, no puedo crear ninguna tabla , ya sea que pase la condición o no.

Este es SQL Server 2016, SP1, CU3.

¿Alguna idea sobre esto?

Editar: Necesito que el modo de evaluación sea "En cambio: prevenir"

John
fuente

Respuestas:

6

Probó los scripts en una instancia de SQL Server 2016 SP1 CU2 y la política funciona si el modo de evaluación está configurado en "Al cambiar: evitar". (hay un error que no le permite evaluar las políticas que utilizan facetas específicas).

Mientras tanto, si solo usa la política para los nombres de tabla, también puede probar la faceta "Opción de tabla" en lugar de "MultipartName", con la misma configuración ( @NAME NOT LIKE '% %').

Dragos
fuente
Si configuro el modo de evaluación en "On Demand", funciona, pero para ser justos, no lo había intentado anteriormente. Preferiría tener esto en el cambio: evitar que la gente cree tablas y luego guarde los procesos que hagan referencia a las tablas mal nombradas.
John
Para mí, no funciona establecer el modo de evaluación en "Bajo demanda" y evaluar la política manualmente. Pero funciona bien si la evaluación se establece en "Al cambiar: evitar" e intenta crear tablas. Puede intentar publicar el problema en Microsoft Connect para averiguar si es un error o no.
Dragos
Gracias, @Dragos. ¿Está sucediendo en alguna mesa, incluso aquellas que deberían pasar la condición?
John
Las tablas que no tienen espacios en blanco en el nombre se crean con éxito, y las que tienen espacios en blanco fallan con un error de infracción de política.
Dragos
Tenemos el mismo problema con el procedimiento almacenado y las facetas de visualización. Estamos en el SQL 2016 SP1 CU3 (más reciente). Como dijo John, esto parece un error, pero se preguntaba si alguien fue capaz de encontrar una solución.
DBAuser