2012-05-19 11 views
6

Ho un database con un sacco di tavoli, e voglio rinominare il primario/chiavi esterne, indici e vincoli di default secondo le seguenti regole:Implementazione di uno standard di denominazione per chiavi, indici, vincoli

  • Le chiavi primarie: PK_<table name>
  • chiavi Stranieri: FK_<table_name>_<column name1>_column name2>...
  • Indici: IX_<table_name>_<column name1>_column name2>...
  • Vincoli predefinite: DF_<table_name>_<column name>
  • C diamine vincoli: CK_<table_name>_<column name>

Qualcuno ha già eseguito uno script SQL simile?

+0

Puoi specificare più regole, per esempio se il tuo indice è filtrato o include le colonne INCLUDE, vuoi specificarlo anche solo per le colonne chiave? Che dire dei vincoli di controllo e dei vincoli univoci? –

+0

Non posso dire di averlo, ma non uso mai la GUI per creare cose, e confermo sempre i nomi delle mie cose nella sceneggiatura. Probabilmente potresti fare quanto sopra, ma penso che sarebbe più facile codificare il db e modificarlo per ottenere quello che vuoi, piuttosto che capire quanto sopra. –

+0

Un altro pensiero è come gestire gli oggetti che hanno underscore nel loro nome. Può essere abbastanza confuso leggere il nome dell'oggetto di una chiave esterna per il caso in cui 'Document_Folder' ha una colonna denominata' Folder_Name' a cui fa riferimento la colonna 'Document' s 'Folder_Name'. 'FK_Document_Folder_Name_Document_Folder_Folder_Name'? Non sono sicuro che sia più utile del nome generato dal sistema "FK__Document__Docum__1DE57479' ... –

risposta

8

Per rinominare chiavi primarie semplicemente PK_TableName:

CREATE PROCEDURE dbo.Rename_PrimaryKeys 
    @PrintOnly BIT = 1 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE @sql NVARCHAR(MAX); 
    SET @sql = N''; 

    SELECT @sql = @sql + CHAR(13) + CHAR(10) + 'EXEC sp_rename ''' 
     + REPLACE(name, '''', '''''') + ''', ''PK_' 
     + REPLACE(OBJECT_NAME(parent_object_id), '''', '') + ''', ''OBJECT'';' 
    FROM sys.key_constraints 
    WHERE type = 'PK' 
    AND name <> 'PK_' + REPLACE(OBJECT_NAME(parent_object_id), '''', '') 
    AND OBJECTPROPERTY(parent_object_id, 'IsMsShipped') = 0; 

    PRINT @sql; 

    IF @PrintOnly = 0 AND @sql > N'' 
    BEGIN 
     EXEC sp_executesql @sql; 
    END 
END 
GO 

Per rinominare FKS con lo schema FK_TableName_col_col_ReferencedName_col_col:

CREATE PROCEDURE dbo.Rename_ForeignKeys_WithColumns 
    @PrintOnly BIT = 1 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE @sql NVARCHAR(MAX); 
    SET @sql = N''; 

    SELECT @sql = @sql + CHAR(13) + CHAR(10) 
    + 'EXEC sp_rename ''' + REPLACE(name, '''', '''''') 
     + ''', ''FK_' + REPLACE(OBJECT_NAME(fk.parent_object_id), '''', '') 
    + '_' + STUFF((SELECT '_' + REPLACE(c.name, '''', '') 
     FROM sys.columns AS c 
      INNER JOIN sys.foreign_key_columns AS fkc 
      ON fkc.parent_column_id = c.column_id 
      AND fkc.parent_object_id = c.[object_id] 
     WHERE fkc.constraint_object_id = fk.[object_id] 
     ORDER BY fkc.constraint_column_id 
     FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)'), 1, 1, '') 
    + '_' + REPLACE(OBJECT_NAME(fk.referenced_object_id), '''', '') 
    + '_' + STUFF((SELECT '_' + REPLACE(c.name, '''', '') 
     FROM sys.columns AS c 
      INNER JOIN sys.foreign_key_columns AS fkc 
      ON fkc.referenced_column_id = c.column_id 
      AND fkc.referenced_object_id = c.[object_id] 
     WHERE fkc.constraint_object_id = fk.[object_id] 
     ORDER BY fkc.constraint_column_id 
     FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)'), 1, 1, '') 
     + ''', ''OBJECT'';' 
    FROM sys.foreign_keys AS fk 
    WHERE OBJECTPROPERTY(parent_object_id, 'IsMsShipped') = 0; 

    PRINT @sql; 

    IF @PrintOnly = 0 AND @sql > N'' 
    BEGIN 
     EXEC sp_executesql @sql; 
    END 
END 
GO 

Per chiavi esterne, se si desidera solo FK_TableName_ReferencedName poi è molto più semplice:

CREATE PROCEDURE dbo.Rename_ForeignKeys 
    @PrintOnly BIT = 1 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE @sql NVARCHAR(MAX); 
    SET @sql = N''; 

    SELECT @sql = @sql + CHAR(13) + CHAR(10) + 'EXEC sp_rename ''' 
     + REPLACE(name, '''', '''''') + ''', ''FK_' 
     + REPLACE(OBJECT_NAME(parent_object_id), '''', '') 
     + '_' + REPLACE(OBJECT_NAME(referenced_object_id), '''', '') 
     + ''', ''OBJECT'';' 
    FROM sys.foreign_keys 
    WHERE OBJECTPROPERTY(parent_object_id, 'IsMsShipped') = 0; 

    PRINT @sql; 

    IF @PrintOnly = 0 AND @sql > N'' 
    BEGIN 
     EXEC sp_executesql @sql; 
    END 
END 
GO 

Per gli indici, questo rinominerà qualsiasi i ndex IX_TableName_Col1_Col2.... Ignorerà le chiavi primarie (poiché vengono trattate separatamente sopra), aggiungerà UQ_ a indici/vincoli univoci (quindi IX_UQ_TableName_Col1_Col2..., tratterà i vincoli univoci e gli indici univoci uguali e ignorerà le colonne incluse. (Si noti che ignorando le colonne incluse potrebbe produrre un conflitto di denominazione se si dispone di indici ridondanti che differiscono solo per colonne incluse)

CREATE PROCEDURE dbo.Rename_Indexes 
    @PrintOnly BIT = 1 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE @sql NVARCHAR(MAX); 
    SET @sql = N''; 

    SELECT @sql = @sql + CHAR(13) + CHAR(10) 
     + 'EXEC sp_rename ''' + REPLACE(i.name, '''', '''''') 
     + ''', ''IX_' + CASE is_unique_constraint WHEN 1 THEN 'UQ_' ELSE '' END 
     + REPLACE(OBJECT_NAME(i.[object_id]), '''', '') 
     + '_' + STUFF((SELECT '_' + REPLACE(c.name, '''', '') 
      FROM sys.columns AS c 
       INNER JOIN sys.index_columns AS ic 
       ON ic.column_id = c.column_id 
       AND ic.[object_id] = c.[object_id] 
      WHERE ic.[object_id] = i.[object_id] 
      AND ic.index_id = i.index_id 
      AND is_included_column = 0 
      ORDER BY ic.index_column_id 
      FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)'), 1, 1, '') 
     +''', ''OBJECT'';' 
    FROM sys.indexes AS i 
    WHERE index_id > 0 
    AND is_primary_key = 0 -- dealt with separately 
    AND OBJECTPROPERTY(i.[object_id], 'IsMsShipped') = 0; 

    PRINT @sql; 

    IF @PrintOnly = 0 AND @sql > N'' 
    BEGIN 
     EXEC sp_executesql @sql; 
    END 
END 
GO 

Per i vincoli di default:.

CREATE PROCEDURE dbo.Rename_DefaultConstraints 
    @PrintOnly BIT = 1 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE @sql NVARCHAR(MAX); 
    SET @sql = N''; 

    SELECT @sql = @sql + CHAR(13) + CHAR(10) 
     + 'EXEC sp_rename ''' + REPLACE(dc.name, '''', '''''') 
     + ''', ''DF_' + REPLACE(OBJECT_NAME(dc.parent_object_id), '''','') 
     + '_' + REPLACE(c.name, '''', '') + ''', ''OBJECT'';' 
    FROM sys.default_constraints AS dc 
    INNER JOIN sys.columns AS c 
    ON dc.parent_object_id = c.[object_id] 
    AND dc.parent_column_id = c.column_id 
    AND OBJECTPROPERTY(dc.parent_object_id, 'IsMsShipped') = 0; 

    PRINT @sql; 

    IF @PrintOnly = 0 AND @sql > N'' 
    BEGIN 
     EXEC sp_executesql @sql; 
    END 
END 
GO 

E infine controllare vincoli:

CREATE PROCEDURE dbo.Rename_CheckConstraints 
    @PrintOnly BIT = 1 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE @sql NVARCHAR(MAX); 
    SET @sql = N''; 

    SELECT @sql = @sql + CHAR(13) + CHAR(10) 
     + 'EXEC sp_rename ''' + REPLACE(cc.name, '''', '''''') 
     + ''', ''CK_' + REPLACE(OBJECT_NAME(cc.parent_object_id), '''','') 
     + '_' + REPLACE(c.name, '''', '') + ''', ''OBJECT'';' 
    FROM sys.check_constraints AS cc 
    INNER JOIN sys.columns AS c 
    ON cc.parent_object_id = c.[object_id] 
    AND cc.parent_column_id = c.column_id 
    AND OBJECTPROPERTY(dc.parent_object_id, 'IsMsShipped') = 0; 

    PRINT @sql; 

    IF @PrintOnly = 0 AND @sql > N'' 
    BEGIN 
     EXEC sp_executesql @sql; 
    END 
END 
GO 

Si noti che PRINT non rivelerà necessariamente l'intera istruzione, a seconda delle impostazioni per i risultati nel testo e la dimensione della dichiarazione. Ma dovrebbe essere abbastanza buono da far sembrare che gli script stiano facendo il lavoro giusto. Li ho impostati tutti su PrintOnly per impostazione predefinita.

+0

Grazie Aaron, imparo sempre qualcosa di nuovo con le tue risposte. – psadac

2

E per rinominare le chiavi esterne, si può usare qualcosa di simile (questo non è ancora facendo esattamente quello che voleva - ma abbastanza vicino per iniziare su di esso):

DECLARE RenameFKCursor CURSOR FAST_FORWARD 
FOR 
    SELECT 
     'dbo.sp_rename @objName = ''' + fk.Name + ''', @NewName = ''FK_' + t.Name + '_' + ref.Name + ''', @objtype = ''OBJECT''' 
    FROM 
     sys.foreign_keys fk 
    INNER JOIN 
     sys.tables t ON fk.parent_object_id = t.object_id 
    INNER JOIN 
     sys.tables ref ON fk.referenced_object_id = ref.object_id 
    WHERE 
     fk.is_system_named = 1 

DECLARE @RenameFKStmt NVARCHAR(500) 

OPEN RenameFKCursor 

FETCH NEXT FROM RenameFKCursor INTO @RenameFKStmt 

WHILE (@@fetch_status <> -1) 
BEGIN 
    IF (@@fetch_status <> -2) 
    BEGIN 
     PRINT @RenameFKStmt 
     EXEC(@RenameFKStmt) 
    END 

    FETCH NEXT FROM RenameFKCursor INTO @RenameFKStmt 
END 

CLOSE RenameFKCursor 
DEALLOCATE RenameFKCursor 
GO 

In sostanza, si itera su tutte le chiavi esterne definite nel tuo database, e rinominale con un nome che decidi su come costruire nello SELECT che è la base di questo cursore.

Quindi si esegue il cursore su tutti i risultati ed è stata eseguita la procedura memorizzata dbo.sp_rename per rinominare il vincolo FK in base a ciò che si desidera che siano.

Utilizzando l'approccio di Aaron per la semplice creazione di una singola istruzione SQL enorme, si potrebbe anche uscire senza dover utilizzare un cursore.

Questo sarebbe il codice molto simile per rinominare i vincoli predefiniti di "nome sistema" alla propria convenzione di denominazione - utilizza lo stesso approccio di cui sopra, uno SELECT contro le viste del catalogo di sistema e quindi un cursore per scorrere su tutte le voci e costruire ed eseguire un'istruzione SQL rename:

DECLARE DFCursor CURSOR FAST_FORWARD 
FOR 
    SELECT 
     dc.Name, 
     t.Name, 
     c.Name 
    FROM 
     sys.default_constraints dc 
    INNER JOIN 
     sys.tables t ON dc.parent_object_id = t.object_id 
    INNER JOIN 
     sys.columns c ON dc.parent_column_id = c.column_id AND dc.parent_object_id = c.object_id 
    WHERE 
     is_system_named = 1 

DECLARE @OldConstraintName sysname, @TableName sysname, @ColumnName sysname 

OPEN DFCursor 

FETCH NEXT FROM DFCursor INTO @OldConstraintName, @TableName, @ColumnName 

WHILE @@FETCH_STATUS = 0 
BEGIN 
    DECLARE @Stmt NVARCHAR(999) 

    SET @Stmt = 'dbo.sp_rename @objName = ''' + @OldConstraintName + ''', @NewName = ''DF_' + @TableName + '_' + @ColumnName + ''', @objtype = ''OBJECT''' 

    PRINT @Stmt 
    EXEC (@Stmt) 

    FETCH NEXT FROM DFCursor INTO @OldConstraintName, @TableName, @ColumnName 
END 

CLOSE DFCursor 
DEALLOCATE DFCursor 
1

soluzioni fornite si romperà se DB ha tabelle simili in diversi schemi. Ecco la mia modifica di this solution, che io uso.

CREATE PROCEDURE dbo._ImplementNamingStandard 
@SELECT_Only  BIT = 1, 
@PrimaryKeys  BIT = 1, 
@ForeignKeys  BIT = 1, 
@Indexes   BIT = 1, 
@UniqueConstraints BIT = 1, 
@DefaultConstraints BIT = 1, 
@CheckConstraints BIT = 1 

AS 
BEGIN 
SET NOCOUNT ON; 

DECLARE @sql NVARCHAR(MAX), @cr CHAR(2); 
SELECT @sql = N'', @cr = CHAR(13) + CHAR(10); 


DECLARE @TableLimit TINYINT, @ColumnLimit TINYINT; 
SELECT @TableLimit = 24, @ColumnLimit = 24; 

chiavi primarie:

IF @PrimaryKeys = 1 
BEGIN 
    SELECT @sql = @sql + @cr + @cr + N'/* ---- Primary Keys ---- */' + @cr; 
    SELECT @sql = @sql + @cr + N'EXEC sp_rename @objname = N''' 
     + SCHEMA_NAME(schema_id) + '.' 
     + REPLACE(name, '''', '''''') + ''', @newname = N''PK_' 
     + LEFT(REPLACE(OBJECT_NAME(parent_object_id), '''', ''), @TableLimit) + ''';' 
    FROM sys.key_constraints 
    WHERE type = 'PK' 
    AND is_ms_shipped = 0; 
END 

esteri Chiavi:

IF @ForeignKeys = 1 
BEGIN 
    SELECT @sql = @sql + @cr + @cr + N'/* ---- Foreign Keys ---- */' + @cr; 
    SELECT @sql = @sql + @cr + N'EXEC sp_rename @objname = N''' 
     + SCHEMA_NAME(f.schema_id) + '.' 
     + REPLACE(f.name, '''', '''''') + ''', @newname = N''FK_' 
     + LEFT(REPLACE(t.name, '''', ''), @TableLimit) 
     + '_' + LEFT(REPLACE(t2.name, '''', ''), @TableLimit)   
     + '_' + LEFT(REPLACE(c.name, '''', ''), @ColumnLimit) 
     + ''';' 
    FROM 
     sys.foreign_keys as f 
     inner join sys.foreign_key_columns as fk on f.object_id = fk.constraint_object_id 
     inner join sys.tables as t on fk.parent_object_id = t.object_id   
     inner join sys.tables as t2 on fk.referenced_object_id = t2.object_id 
     inner join sys.columns as c on fk.parent_object_id = c.object_id and 
             fk.parent_column_id = c.column_id 


    WHERE f.is_ms_shipped = 0; 
END 

vincoli uniche:

IF (@UniqueConstraints = 1 OR @Indexes = 1) 
     BEGIN 
      SELECT @sql = @sql + @cr + @cr + N'/* ---- Indexes/Unique Constraints ---- */' + @cr; 
      SELECT @sql = @sql + @cr + N'EXEC sp_rename @objname = N''' 
     + CASE is_unique_constraint WHEN 0 THEN 
     QUOTENAME(REPLACE(OBJECT_NAME(i.[object_id]), '''', '''''')) + '.' ELSE '' END 
       + QUOTENAME(REPLACE(i.name, '''', '''''')) + ''', @newname = N''' 
       + CASE is_unique_constraint WHEN 1 THEN 'UQ_' ELSE 'IX_' 
        + CASE is_unique WHEN 1 THEN 'U_' ELSE '' END 
       END + CASE has_filter WHEN 1 THEN 'F_' ELSE '' END 
       + LEFT(REPLACE(OBJECT_NAME(i.[object_id]), '''', ''), @TableLimit) 
       + '_' + STUFF((SELECT '_' + LEFT(REPLACE(c.name, '''', ''), @ColumnLimit) 
        FROM sys.columns AS c 
         INNER JOIN sys.index_columns AS ic 
         ON ic.column_id = c.column_id 
         AND ic.[object_id] = c.[object_id] 
        WHERE ic.[object_id] = i.[object_id] 
        AND ic.index_id = i.index_id 
        AND is_included_column = 0 
        ORDER BY ic.index_column_id FOR XML PATH(''), 
        TYPE).value('.', 'nvarchar(max)'), 1, 1, '') +''';' 
      FROM sys.indexes AS i 
      WHERE index_id > 0 AND is_primary_key = 0 AND type IN (1,2) 
      AND OBJECTPROPERTY(i.[object_id], 'IsMsShipped') = 0; 
     END 

vincoli predefiniti:

IF @DefaultConstraints = 1 
BEGIN 
    SELECT @sql = @sql + @cr + @cr + N'/* ---- DefaultConstraints ---- */' + @cr; 
    SELECT @sql = @sql + @cr + N'EXEC sp_rename @objname = N''' 
     + SCHEMA_NAME(schema_id) + '.' 
     + REPLACE(dc.name, '''', '''''') + ''', @newname = N''DF_' 
     + LEFT(REPLACE(OBJECT_NAME(dc.parent_object_id), '''',''), @TableLimit) 
     + '_' + LEFT(REPLACE(c.name, '''', ''), @ColumnLimit) + ''';' 
    FROM sys.default_constraints AS dc 
    INNER JOIN sys.columns AS c 
    ON dc.parent_object_id = c.[object_id] 
    AND dc.parent_column_id = c.column_id 
    AND dc.is_ms_shipped = 0; 
END 

vincoli CHECK:

IF @CheckConstraints = 1 
BEGIN 
    SELECT @sql = @sql + @cr + @cr + N'/* ---- CheckConstraints ---- */' + @cr; 
    SELECT @sql = @sql + @cr + N'EXEC sp_rename @objname = N''' 
     + SCHEMA_NAME(schema_id) + '.' 
     + REPLACE(cc.name, '''', '''''') + ''', @newname = N''CK_' 
     + LEFT(REPLACE(OBJECT_NAME(cc.parent_object_id), '''',''), @TableLimit) 
     + '_' + LEFT(REPLACE(c.name, '''', ''), @ColumnLimit) + ''';' 
    FROM sys.check_constraints AS cc 
    INNER JOIN sys.columns AS c 
    ON cc.parent_object_id = c.[object_id] 
    AND cc.parent_column_id = c.column_id 
    AND cc.is_ms_shipped = 0; 
END 


SELECT @sql; 


IF @SELECT_Only = 0 AND @sql > N'' 
BEGIN 
    EXEC sp_executesql @sql; 
END 
Problemi correlati