Masalah dengan Konvensi Penamaan Tabel dan Manajemen Kebijakan di SQL Server 2016

10

Di SQL Server 2012, saya menetapkan kebijakan untuk tidak mengizinkan spasi dalam nama tabel. Namun, ketika saya menggunakan kebijakan yang sama di SQL Server 2016, saya mendapatkan kesalahan.

Berikut adalah kode untuk kondisinya:

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

Berikut adalah kode untuk kebijakan ini:

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

Di SQL Server 2012 dan 2014, ini memberikan hasil yang diharapkan:

CREATE TABLE [test table]
(Id INT NULL)

Kebijakan 'Nama Tabel' telah dilanggar oleh 'SQLSERVER: \ SQL \ LSRSQL07 \ SQL2012 \ Databases \ test \ Tables \ dbo.test table'. Transaksi ini akan dibatalkan. Kondisi kebijakan: '@Name NOT LIKE'% [-.]% 'AND @NAME NOT LIKE'% [^ A-Za-z0-9 [_]]% '' Deskripsi kebijakan: '' Bantuan tambahan: '': Bantuan tambahan: '': '' Pernyataan: 'CREATE TABLE [tabel tes] (Id INT NULL)'. Msg 3609, Level 16, Status 1, Prosedur sp_syspolicy_dispatch_event, Jalur 65 [Garis Mulai Batch 48] Transaksi berakhir pada pelatuk. Batch telah dibatalkan.

Dan jika saya menjalankan kode berikut, saya tidak mendapatkan kesalahan:

CREATE TABLE [testtable]
(Id INT NULL)

Namun, jika saya menjalankan CREATE TABLEpernyataan apa pun , dengan kebijakan diaktifkan, di SQL Server 2016, saya mendapatkan kesalahan berikut:

Kebijakan 'Nama Tabel' telah dilanggar oleh 'SQLSERVER: \ SQL \ LSRSQL07 \ SQL2016 \ Databases \ test \ Tables \ dbo.testtable'. Transaksi ini akan dibatalkan. Kondisi kebijakan: '@NAMA TIDAK SEPERTI'%% '' Deskripsi kebijakan: '' Bantuan tambahan: '': '' Pernyataan: 'CREATE TABLE [testtable] (Id INT NULL)'. Msg 515, Level 16, Negara 2, Prosedur sp_syspolicy_execute_policy, Baris 69 [Garis Mulai Batch 44] Tidak dapat memasukkan nilai NULL ke dalam kolom 'target_query_expression', tabel 'msdb.dbo.syspolicy_policy_execution_details_internal'; kolom tidak memungkinkan nulls. INSERT gagal. Pernyataan itu telah dihentikan.

Di SQL Server 2016, saya tidak bisa membuat tabel apa pun , apakah itu melewati kondisi atau tidak.

Ini adalah SQL Server 2016, SP1, CU3.

Ada ide tentang ini?

Sunting: Saya memerlukan mode evaluasi untuk menjadi "Saat perubahan: cegah"

John
sumber

Jawaban:

6

Menguji skrip pada contoh SQL Server 2016 SP1 CU2 dan kebijakan berfungsi jika mode Evaluasi diatur ke "Di Ubah: Mencegah". (ada bug yang tidak memungkinkan Anda mengevaluasi kebijakan yang menggunakan aspek tertentu).

Sementara itu, jika Anda hanya menggunakan kebijakan untuk nama tabel, Anda juga dapat mencoba aspek "Table Option" alih-alih "MultipartName", dengan konfigurasi yang sama ( @NAME NOT LIKE '% %').

Drago
sumber
Jika saya mengatur mode evaluasi ke "On Demand", itu berhasil, tetapi untuk bersikap adil, saya belum mencobanya sebelumnya. Saya lebih suka memiliki ini Pada perubahan: mencegah agar orang-orang dari membuat tabel dan kemudian menyimpan procs referensi tabel yang bernama buruk.
John
Bagi saya itu tidak bekerja untuk mengatur mode evaluasi ke "Sesuai permintaan" dan mengevaluasi kebijakan secara manual. Tapi itu berfungsi dengan baik jika evaluasi diatur ke "Pada Perubahan: Cegah" dan cobalah untuk membuat tabel. Anda dapat mencoba memposting masalah di Microsoft Connect untuk mengetahui apakah itu bug atau tidak.
Dragos
Terima kasih, @Dragos. Apakah itu terjadi di meja mana pun, bahkan yang harus melewati kondisi tersebut?
John
Tabel yang tidak memiliki spasi putih dalam nama berhasil dibuat, dan mereka yang memiliki spasi putih gagal dengan kesalahan pelanggaran kebijakan.
Dragos
Kami memiliki masalah yang sama dengan prosedur tersimpan dan aspek tampilan. Kami berada di SQL 2016 SP1 CU3 (Terbaru). Seperti yang dikatakan John, ini sepertinya seperti bug tetapi bertanya-tanya apakah ada yang bisa menemukan solusinya?
DBAuser