Problem z konwencjami nazewnictwa tabel i zarządzaniem zasadami w SQL Server 2016

10

W SQL Server 2012 miałem zestaw strategii, który nie zezwala na spacje w nazwie tabeli. Jednak gdy używam tych samych zasad w programie SQL Server 2016, pojawia się błąd.

Oto kod warunku:

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

Oto kod zasady:

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

W SQL Server 2012 i 2014 daje to oczekiwane wyniki:

CREATE TABLE [test table]
(Id INT NULL)

Zasady „Nazwy tabel” zostały naruszone przez „SQLSERVER: \ SQL \ LSRSQL07 \ SQL2012 \ Databases \ test \ Tables \ dbo.test table”. Transakcja zostanie wycofana. Warunek zasad: „@NAME NOT LIKE”% [-.]% ”AND @Name NOT LIKE”% [^ A-Za-z0-9 [_]]% '' Opis zasad: '' Dodatkowa pomoc: '': „” Oświadczenie: „CREATE TABLE [tabela testowa] (Id INT NULL)”. Msg 3609, poziom 16, stan 1, procedura sp_syspolicy_dispatch_event, wiersz 65 [Batch Start Line 48] Transakcja zakończyła się wyzwalaczem. Partia została przerwana.

A jeśli uruchomię następujący kod, nie otrzymuję błędu:

CREATE TABLE [testtable]
(Id INT NULL)

Jednak jeśli uruchomię dowolną CREATE TABLEinstrukcję, z włączoną zasadą, na serwerze SQL Server 2016 otrzymuję następujący błąd:

Zasady „Nazwy tabel” zostały naruszone przez „SQLSERVER: \ SQL \ LSRSQL07 \ SQL2016 \ Databases \ test \ Tables \ dbo.testtable”. Transakcja zostanie wycofana. Warunek zasad: „@NAME NOT LIKE”%% ”„ Opis zasad: ”„ Dodatkowa pomoc: ”„: ”„ Oświadczenie: „CREATE TABLE [testtable] (Id INT NULL)”. Msg 515, poziom 16, stan 2, procedura sp_syspolicy_execute_policy, wiersz 69 [wiersz wsadowy 44] Nie można wstawić wartości NULL do kolumny „target_query_exeryion”, tabela „msdb.dbo.syspolicy_policy_execution_history_details_internal”; kolumna nie zezwala na wartości null. INSERT nie działa. Instrukcja została zakończona.

W SQL Server 2016 nie mogę utworzyć żadnej tabeli , niezależnie od tego, czy spełnia ona warunek, czy nie.

To jest SQL Server 2016, SP1, CU3.

Jakieś pomysły na ten temat?

Edycja: Potrzebuję trybu oceny do „Przy zmianie: zapobiegaj”

Jan
źródło

Odpowiedzi:

6

Przetestowano skrypty w wystąpieniu SQL Server 2016 SP1 CU2 i zasady działają, jeśli tryb oceny jest ustawiony na „Przy zmianie: Zapobiegaj”. (istnieje błąd , który nie pozwala ocenić zasad korzystających z określonych aspektów).

Tymczasem, jeśli używasz tylko zasad dla nazw tabel, możesz również wypróbować aspekt „Opcja tabeli” zamiast „Nazwa wielu części”, z tą samą konfiguracją ( @NAME NOT LIKE '% %').

Dragos
źródło
Jeśli ustawię tryb oceny na „Na żądanie”, działa, ale żeby być uczciwym, nie próbowałem tego wcześniej. Wolę mieć tę opcję Przy zmianie: zapobiegaj powstrzymywaniu ludzi przed tworzeniem tabel, a następnie zapisywaniem procesów odwołujących się do źle nazwanych tabel.
John
Dla mnie nie działa ustawienie trybu oceny na „Na żądanie” i ręczna ocena polityki. Ale działa dobrze, jeśli ocena jest ustawiona na „Przy zmianie: Zapobiegaj” i spróbuj utworzyć tabele. Możesz spróbować opublikować problem w Microsoft Connect, aby dowiedzieć się, czy jest to błąd, czy nie.
Dragos
Dzięki, @Dragos. Czy dzieje się to na każdym stole, nawet tym, który powinien spełnić ten warunek?
John
Tabele, które nie zawierają białych znaków w nazwie, są tworzone pomyślnie, a tabele zawierające białe znaki nie działają z błędem naruszenia zasad.
Dragos
Mamy ten sam problem z procedurą przechowywaną i aspektami widoku. Jesteśmy na SQL 2016 SP1 CU3 (najnowsze). Jak stwierdził John, wydaje się to być błędem, ale zastanawiał się, czy ktoś był w stanie wymyślić obejście?
DBAuser 17.07.17