Genera script per automatizzare la ridenominazione dei vincoli predefiniti


8

Background: alcuni dei nostri vincoli di colonna predefiniti sono stati generati senza nomi espliciti, quindi otteniamo nomi divertenti che variano da server a server come: DF__User__TimeZoneIn__5C4D869D

Preferirei averli tutti gestibili con una denominazione coerente come in DF_Users_TimeZoneInfomodo da poter garantire che esistano i vincoli appropriati sulle future tabelle target (come nel confronto RedGate, o anche solo visivamente)

Ho una sceneggiatura che funziona principalmente per quello che voglio:

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[_][_]%'

Ma questo mi dà solo un set di risultati, e non qualcosa che posso effettivamente passare in un dirigente o altro.

Come posso farlo in modo da poter semplicemente eseguire quegli sp_renamescript senza dover ricorrere a copiare tutti gli elementi restituiti e incollarli in una nuova finestra di query ed eseguirli di nuovo? Sto cercando di salvare il maggior numero possibile di tasti in modo da poterlo correggere in molti ambienti.

inserisci qui la descrizione dell'immagine


<facepalm> Avresti dovuto chiedermelo l'altro giorno - ho preso la mia risposta dalla sceneggiatura che ho fatto esattamente questo. :)
Jon Seigel

@JonSeigel ok, che ne dici di un livello di indrezione attorno a questo da eseguire una volta su ciascuno dei diversi dbs? : D
jcolebrand

Non mettere parentesi quadre attorno al nuovo nome - Ho finito con un mondo di dolore dopo aver eseguito questo script :)
Samjudson,

Risposte:


16

Ok, un paio di cose.

  1. utilizzare sempre EXECquando si eseguono procedure memorizzate; la scorciatoia EXECfunziona solo quando è la prima istruzione nel batch (e non sarà il caso qui).
  2. usa sempre terminatori punto e virgola - in questo caso sono utili al posto di graziosi ritorni a capo e rientri, ma sono sempre saggi da avere.
  3. usa sempre QUOTENAME()invece di applicare manualmente le parentesi quadre. In questo caso probabilmente sei al sicuro, ma ci sono casi in cui l'approccio manuale si interromperà.
  4. puoi testare l' PRINToutput ma non sarà necessariamente completo se il tuo comando totale è> 8k (vedi questo suggerimento per alcuni approcci alternativi ).

    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;

Buono a sapersi dell'EXEC per ogni affermazione, non lo sapevo.
jcolebrand

3
Si tenta di eseguire questo: sp_help; sp_help;.
Aaron Bertrand

3

Sulla base della tua domanda .. che hai rimosso "automatizza lo stesso script su alcuni dei database sull'istanza"

Di seguito è riportato il codice che ti aiuterà

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; 

L'ho rimosso perché alla domanda precedente mancava un po 'di dettagli chiave, poiché i nomi delle colonne cambiano in ogni db, quindi ho bisogno di eseguire la query interna per contesto del singolo db.
jcolebrand

@jcolebrand grazie per l'aggiornamento. In ogni caso, il codice con le mie modifiche ti aiuterà a quello che stai cercando.
Kin Shah,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.