2012-05-19 25 views
6

Tengo una base de datos con una gran cantidad de tablas, y quiero cambiar el nombre de claves foráneas, índices y restricciones predeterminadas de acuerdo con las siguientes reglas primaria /:La implementación de un estándar de nomenclatura para las llaves, índices, restricciones

  • Las claves principales: PK_<table name>
  • de claves foráneas: FK_<table_name>_<column name1>_column name2>...
  • índices: IX_<table_name>_<column name1>_column name2>...
  • restricciones predeterminadas: DF_<table_name>_<column name>
  • C diablos Restricciones: CK_<table_name>_<column name>

¿Alguien ya ha hecho una secuencia de comandos SQL similar?

+0

¿Puede especificar más reglas, por ejemplo, si su índice está filtrado o tiene columnas INCLUIR, ¿desea especificar también esas, o solo columnas clave? ¿Qué pasa con las restricciones de verificación y las restricciones únicas? –

+0

No puedo decir que tengo, pero nunca uso la GUI para crear cosas, y siempre doy mis nombres de cosas en el guión. Probablemente podría hacer lo anterior, pero creo que sería más fácil escribir el db y editarlo para obtener lo que desea, que resolver lo anterior. –

+0

Otra idea es cómo tratar con objetos que tienen caracteres de subrayado en su nombre. Puede ser bastante confuso leer el nombre del objeto de una clave externa para el caso donde 'Document_Folder' tiene una columna llamada' Folder_Name' referenciada por la columna 'Document's' Folder_Name'. 'FK_Document_Folder_Name_Document_Folder_Folder_Name'? No estoy seguro de que sea más útil que el nombre generado por el sistema 'FK__Document__Docum__1DE57479' ... –

Respuesta

8

Para cambiar el nombre de claves principales simplemente 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 

Para cambiar el nombre FKs con el esquema 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 

Para las claves externas si lo que desea FK_TableName_ReferencedName entonces es mucho más simple:

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 

Para los índices, esto va a cambiar el nombre de cualquier i ndexes IX_TableName_Col1_Col2.... Se ignorará las claves principales (ya que se tratan por separado más arriba), agregará UQ_ a índices únicos/limitaciones (por lo IX_UQ_TableName_Col1_Col2..., tratará restricciones únicas e índices únicos de la misma, y ​​no hará caso de columnas incluidas. (Tenga en cuenta que haciendo caso omiso incluido columnas podría producir un conflicto de nombres si tiene índices redundantes que sólo se diferencian por columnas incluidas)

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 

por restricciones predeterminadas:.

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 

Y, finalmente, las restricciones de comprobación:

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 

Tenga en cuenta que no necesariamente PRINT revelar toda la declaración, dependiendo de la configuración de los resultados en el texto y el tamaño de la declaración. Pero debería ser lo suficientemente bueno como para ver si los guiones están haciendo el trabajo correcto. Los configuré todos a PrintOnly de manera predeterminada.

+0

Gracias Aaron, siempre aprendo algo nuevo con tus respuestas. – psadac

2

Y para cambiar el nombre de las claves externas, se puede usar algo como esto (esto todavía no está haciendo exactamente lo que quería - pero lo suficientemente cerca para empezar a trabajar en ella):

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 

Básicamente, itere sobre todas las claves foráneas definidas en su base de datos, y cambie su nombre a algún nombre que decida sobre cómo construirlo en el SELECT que es la base de este cursor.

A continuación, ejecuta el cursor sobre todos los resultados y ejecuta el procedimiento almacenado dbo.sp_rename para cambiar el nombre de su restricción FK a lo que quiera que sea.

Utilizando el enfoque de Aaron de simplemente construir una sola instrucción SQL enorme, incluso podría salir sin tener que usar un cursor.

Este sería el código muy similar para cambiar el nombre de las restricciones predeterminadas "de nombre de sistema" a su propia convención de nomenclatura; utiliza el mismo enfoque que el anterior, SELECT contra las vistas del catálogo del sistema y luego un cursor para iterar todas las entradas y se acumulan y ejecutar una instrucción de cambio de nombre SQL:

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

soluciones aportadas se romperán si DB tiene tablas similares en diferentes esquemas. Aquí está mi modificación de this solution, que yo 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; 

claves principales:

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 

Exteriores Claves:

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 

restricciones únicas:

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 

restricciones predeterminadas: 01

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 

Restricciones de comprobación:

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 
Cuestiones relacionadas