Buat skrip untuk secara otomatis mengubah nama batasan default

8

Latar Belakang: Beberapa batasan kolom default kami dibuat tanpa nama eksplisit, jadi kami mendapatkan nama yang menyenangkan yang berbeda dari satu server ke server lainnya seperti: DF__User__TimeZoneIn__5C4D869D

Saya lebih suka mengatur semuanya agar dapat dikelola dengan penamaan yang konsisten DF_Users_TimeZoneInfosehingga kami dapat memastikan bahwa ada kendala yang sesuai pada tabel target di masa mendatang (seperti dalam perbandingan RedGate, atau bahkan hanya secara visual)

Saya punya skrip yang sebagian besar berfungsi untuk apa yang saya inginkan:

select 'sp_rename N''[' + s.name + '].[' + d.name + ']'', 
   N''[DF_' + t.name + '_' + c.name + ']'', ''OBJECT'';'
from sys.tables t
    join
    sys.default_constraints d
        on d.parent_object_id = t.object_id
    join
    sys.columns c
        on c.object_id = t.object_id
        and c.column_id = d.parent_column_id
    join sys.schemas s
        on t.schema_id = s.schema_id
WHERE d.NAME like 'DF[_][_]%'

Tapi ini hanya memberi saya hasil, dan bukan sesuatu yang saya benar-benar dapat lulus menjadi eksekutif atau apa pun.

Bagaimana saya bisa membuat ini sehingga saya bisa menjalankan sp_renameskrip - skrip itu tanpa harus menyalin semua elemen yang dikembalikan dan menempelkannya ke jendela permintaan baru dan menjalankannya lagi? Mencoba menyimpan sebanyak mungkin penekanan tombol sehingga saya dapat memperbaikinya di banyak lingkungan.

masukkan deskripsi gambar di sini

jcolebrand
sumber
<facepalm> Anda seharusnya bertanya kepada saya tentang ini tempo hari - saya menarik jawaban saya dari naskah yang saya miliki yang melakukan hal ini. :)
Jon Seigel
@ JonSeigel ok, bagaimana dengan tingkat indreksi sekitar ini untuk dijalankan sekali pada masing-masing beberapa dbs? : D
jcolebrand
Jangan letakkan tanda kurung kotak di sekitar nama baru - Saya berakhir dengan dunia yang terluka setelah menjalankan skrip ini :)
samjudson

Jawaban:

16

Ok, beberapa hal.

  1. selalu gunakan EXECsaat menjalankan prosedur tersimpan; steno tanpa EXEChanya berfungsi ketika itu adalah pernyataan pertama dalam bets (dan itu tidak akan terjadi di sini).
  2. selalu menggunakan terminator semi-kolon - dalam hal ini mereka berguna sebagai pengganti pengembalian dan lekukan kereta yang cantik, tetapi mereka selalu bijaksana untuk memilikinya.
  3. selalu gunakan QUOTENAME()alih-alih menerapkan tanda kurung siku sendiri secara manual. Dalam hal ini Anda mungkin aman, tetapi ada kasus di mana pendekatan manual akan rusak.
  4. Anda dapat menguji PRINToutput tetapi tidak harus lengkap jika total perintah Anda> 8k (lihat tip ini untuk beberapa pendekatan alternatif ).

    DECLARE @sql nvarchar(max) = N'';
    
    SELECT @sql += N'EXEC sys.sp_rename N''' 
        + QUOTENAME(s.name) + '.' + QUOTENAME(d.name) 
        + ''', N''DF_' + t.name + '_' + c.name + ''', ''OBJECT'';'
      FROM sys.tables AS t
      INNER JOIN sys.default_constraints AS d
         ON d.parent_object_id = t.object_id
      INNER JOIN sys.columns AS c
         ON c.object_id = t.object_id
        AND c.column_id = d.parent_column_id
      INNER JOIN sys.schemas AS s
         ON t.schema_id = s.schema_id
      WHERE d.NAME LIKE N'DF[_][_]%';
    
    PRINT @sql;
    -- EXEC sys.sp_executesql @sql;
    
Aaron Bertrand
sumber
Senang mengetahui tentang EXEC untuk setiap pernyataan, saya tidak tahu tentang itu.
jcolebrand
3
Ya mencoba mengeksekusi ini: sp_help; sp_help;.
Aaron Bertrand
3

Berdasarkan pertanyaan Anda .. yang telah Anda hapus "otomatiskan skrip yang sama pada beberapa database pada instance "

Di bawah ini adalah kode yang akan membantu Anda

set nocount on
DECLARE @table TABLE 
  ( 
     dbname VARCHAR(30) 
  ) 

INSERT INTO @table 
            (dbname) 
VALUES      ( 'dev_construct1' ), 
            ('dev_construct2'), 
            ('dev_construct3' ); 

DECLARE @sql NVARCHAR(max) = N''; 
DECLARE @dbname VARCHAR(30) 

/*  
Added by Kin : While loop and an extra @dbname variable 
*/ 
SELECT @dbname = Min(dbname) 
FROM   @table 

WHILE @dbname IS NOT NULL 
  BEGIN 
      SELECT @sql = N'USE ' + tt.dbname + Char(10) + N' GO;'
      FROM   @table tt 
      WHERE  @dbname = dbname 

      SELECT @sql += Char(10) + N'EXEC sp_rename N''' 
                     + Quotename(s.name) + '.' + Quotename(d.name) 
                     + ''', N''DF_' + t.name + '_' + c.name 
                     + ''', ''OBJECT'';' 
      FROM   sys.tables AS t 
             JOIN sys.default_constraints d 
               ON d.parent_object_id = t.object_id 
             JOIN sys.columns c 
               ON c.object_id = t.object_id 
                  AND c.column_id = d.parent_column_id 
             JOIN sys.schemas s 
               ON t.schema_id = s.schema_id 
             JOIN @table tt 
               ON tt.dbname = tt.dbname 
      WHERE  d.name LIKE 'DF[_][_]%'; 

      PRINT @sql 

      SELECT @dbname = Min(dbname) 
      FROM   @table 
      WHERE  dbname > @dbname 
  END 
-- EXEC sp_executesql @sql; 
Kin Shah
sumber
Saya menghapusnya karena pertanyaan sebelumnya tidak ada detail, karena nama kolom berubah di setiap db, jadi saya harus menjalankan kueri dalam per konteks masing-masing db.
jcolebrand
@ jcolebrand terima kasih atas pembaruannya. Bagaimanapun, kode dengan perubahan saya akan membantu Anda apa yang Anda cari.
Kin Shah