Generieren Sie ein Skript, um das Umbenennen von Standardeinschränkungen zu automatisieren

8

Hintergrund: Einige unserer Standardspalteneinschränkungen wurden ohne explizite Namen generiert, sodass wir unterhaltsame Namen erhalten, die von Server zu Server variieren, wie z. DF__User__TimeZoneIn__5C4D869D

Ich würde es vorziehen, wenn sie alle mit einer einheitlichen Benennung wie verwaltet DF_Users_TimeZoneInfowerden könnten, damit wir sicherstellen können, dass die entsprechenden Einschränkungen für zukünftige Zieltabellen bestehen (wie im RedGate-Vergleich oder sogar nur visuell).

Ich habe ein Skript, das hauptsächlich für das funktioniert, was ich will:

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

Aber das gibt mir nur eine Ergebnismenge und nichts, was ich tatsächlich an einen Exec oder was auch immer weitergeben kann.

Wie kann ich dies tun, damit ich diese sp_renameSkripte einfach ausführen kann, ohne alle zurückgegebenen Elemente kopieren und in ein neues Abfragefenster einfügen und erneut ausführen zu müssen? Ich versuche, so viele Tastenanschläge wie möglich zu speichern, damit ich dies in vielen Umgebungen korrigieren kann .

Geben Sie hier die Bildbeschreibung ein

jcolebrand
quelle
<facepalm> Sie hätten mich neulich danach fragen sollen - ich habe meine Antwort aus dem Skript gezogen, das genau das tut. :)
Jon Seigel
@ JonSeigel ok, wie wäre es mit einem Grad an Indrection, um dies einmal auf jeder von mehreren DBs auszuführen? : D
jcolebrand
Setzen

Antworten:

16

Ok, ein paar Dinge.

  1. immer verwenden, EXECwenn gespeicherte Prozeduren ausgeführt werden; Die Kurzschrift ohne EXECfunktioniert nur, wenn es sich um die erste Anweisung im Stapel handelt (und dies ist hier nicht der Fall).
  2. Verwenden Sie immer Semikolon-Terminatoren - in diesem Fall sind sie anstelle von hübschen Wagenrückläufen und Einrückungen nützlich, aber es ist immer ratsam, sie zu haben.
  3. Verwenden Sie immer, QUOTENAME()anstatt manuell eckige Klammern selbst anzubringen. In diesem Fall sind Sie wahrscheinlich sicher, aber es gibt Fälle, in denen der manuelle Ansatz nicht funktioniert.
  4. Sie können die PRINTAusgabe testen , sie ist jedoch nicht unbedingt vollständig, wenn Ihr Gesamtbefehl> 8 KB ist ( einige alternative Ansätze finden Sie in diesem Tipp ).

    DECLARE @sql NVARCHAR(MAX) = N'';
    
    SELECT @sql += 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
    WHERE d.NAME like 'DF[_][_]%';
    
    PRINT @sql;
    -- EXEC sp_executesql @sql;
Aaron Bertrand
quelle
Gut zu wissen über die EXEC für jede Aussage, das wusste ich nicht.
Jcolebrand
3
Ja, versuchen Sie Folgendes auszuführen : sp_help; sp_help;.
Aaron Bertrand
3

Basierend auf Ihrer Frage, die Sie entfernt haben "Automatisieren Sie das gleiche Skript für einige der Datenbanken auf der Instanz".

Unten finden Sie den Code, der Ihnen helfen wird

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
quelle
Ich habe es entfernt, weil der vorherigen Frage ein wichtiges Detail fehlte, da sich die Spaltennamen in jeder Datenbank ändern. Daher muss ich die innere Abfrage pro Kontext der einzelnen Datenbank ausführen.
Jcolebrand
@jcolebrand danke für das Update. In jedem Fall hilft Ihnen der Code mit meinen Änderungen, was Sie suchen.
Kin Shah