Problem mit Tabellennamenskonventionen und Richtlinienverwaltung in SQL Server 2016

10

In SQL Server 2012 war die Richtlinie so festgelegt, dass keine Leerzeichen in einem Tabellennamen zulässig sind. Wenn ich jedoch dieselbe Richtlinie in SQL Server 2016 verwende, wird eine Fehlermeldung angezeigt.

Hier ist der Code für die Bedingung:

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

Hier ist der Code für die Richtlinie:

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

In SQL Server 2012 und 2014 ergeben sich die erwarteten Ergebnisse:

CREATE TABLE [test table]
(Id INT NULL)

Die Richtlinie 'Tabellennamen' wurde von 'SQLSERVER: \ SQL \ LSRSQL07 \ SQL2012 \ Databases \ test \ Tables \ dbo.test table' verletzt. Diese Transaktion wird zurückgesetzt. Richtlinienbedingung: '@Name NOT LIKE'% [-.]% 'UND @Name NOT LIKE'% [^ A-Za-z0-9 [_]]% '' Richtlinienbeschreibung: '' Zusätzliche Hilfe: '': '' Anweisung: 'CREATE TABLE [Testtabelle] (Id INT NULL)'. Nachricht 3609, Ebene 16, Status 1, Prozedur sp_syspolicy_dispatch_event, Zeile 65 [Stapelstartzeile 48] Die Transaktion wurde im Trigger beendet. Der Stapel wurde abgebrochen.

Und wenn ich den folgenden Code ausführe, erhalte ich keine Fehlermeldung:

CREATE TABLE [testtable]
(Id INT NULL)

Wenn ich jedoch eine CREATE TABLEAnweisung mit aktivierter Richtlinie unter SQL Server 2016 ausführe , wird die folgende Fehlermeldung angezeigt:

Die Richtlinie 'Tabellennamen' wurde von 'SQLSERVER: \ SQL \ LSRSQL07 \ SQL2016 \ Databases \ test \ Tables \ dbo.testtable' verletzt. Diese Transaktion wird zurückgesetzt. Richtlinienbedingung: '@Name NOT LIKE' %% '' Richtlinienbeschreibung: '' Zusätzliche Hilfe: '': '' Anweisung: 'CREATE TABLE [testtable] (Id INT NULL)'. Nachricht 515, Ebene 16, Status 2, Prozedur sp_syspolicy_execute_policy, Zeile 69 [Stapelstartzeile 44] Der Wert NULL kann nicht in die Spalte 'target_query_expression', Tabelle 'msdb.dbo.syspolicy_policy_execution_history_details_internal' eingefügt werden. Spalte erlaubt keine Nullen. INSERT schlägt fehl. Die Anweisung wurde beendet.

In SQL Server 2016 kann ich keine Tabelle erstellen , unabhängig davon, ob sie die Bedingung erfüllt oder nicht.

Dies ist SQL Server 2016, SP1, CU3.

Irgendwelche Ideen dazu?

Bearbeiten: Ich benötige den Auswertungsmodus "Bei Änderung: Verhindern".

John
quelle

Antworten:

6

Testete die Skripte auf einer SQL Server 2016 SP1 CU2-Instanz und die Richtlinie funktioniert, wenn der Evaluierungsmodus auf "Bei Änderung: Verhindern" eingestellt ist. (Es gibt einen Fehler , mit dem Sie keine Richtlinien bewerten können, die bestimmte Facetten verwenden.)

Wenn Sie die Richtlinie nur für Tabellennamen verwenden, können Sie auch die Facette "Tabellenoption" anstelle des "MultipartNames" mit derselben Konfiguration ( @NAME NOT LIKE '% %') ausprobieren .

Dragos
quelle
Wenn ich den Evaluierungsmodus auf "On Demand" setze, funktioniert es, aber um fair zu sein, hatte ich das vorher noch nicht versucht. Ich würde es vorziehen, diese Änderung vorzunehmen: Verhindern Sie, dass Personen Tabellen erstellen und dann Prozesse speichern, die auf die schlecht benannten Tabellen verweisen.
John
Für mich funktioniert es nicht, den Evaluierungsmodus auf "On Demand" zu setzen und die Richtlinie manuell zu evaluieren. Es funktioniert jedoch einwandfrei, wenn die Auswertung auf "Bei Änderung: Verhindern" eingestellt ist und versucht wird, Tabellen zu erstellen. Sie können versuchen, das Problem in Microsoft Connect zu veröffentlichen, um herauszufinden, ob es sich um einen Fehler handelt oder nicht.
Dragos
Danke, @Dragos. Passiert es auf einem Tisch, auch auf denen, die die Bedingung erfüllen sollten?
John
Tabellen ohne Leerzeichen im Namen werden erfolgreich erstellt, und Tabellen mit Leerzeichen schlagen mit einem Richtlinienverletzungsfehler fehl.
Dragos
Wir haben das gleiche Problem mit gespeicherten Prozeduren und Ansichtsfacetten. Wir sind auf der SQL 2016 SP1 CU3 (Neueste). Wie John sagte, scheint dies ein Fehler zu sein, fragte sich aber, ob jemand in der Lage war, eine Problemumgehung zu finden?
DBAuser