实现键,索引,约束的命名标准

时间:2012-05-19 14:01:23

标签: sql-server sql-server-2008 sql-server-2005

我有一个包含大量表的数据库,我想根据以下规则重命名主键/外键,索引和默认约束:

  • 主键:PK_<table name>
  • 外键:FK_<table_name>_<column name1>_column name2>...
  • 索引:IX_<table_name>_<column name1>_column name2>...
  • 默认约束:DF_<table_name>_<column name>
  • 检查约束:CK_<table_name>_<column name>

有人已经完成了类似的SQL脚本吗?

3 个答案:

答案 0 :(得分:8)

将主键重命名为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

使用方案FK_TableName_col_col_ReferencedName_col_col重命名FK:

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

对于外键,如果你只是想要FK_TableName_ReferencedName那么它就更简单了:

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

对于索引,这将重命名任何索引IX_TableName_Col1_Col2...。它将忽略主键(因为它们在上面单独处理),将UQ_添加到唯一索引/约束(所以IX_UQ_TableName_Col1_Col2...,将处理唯一约束和唯一索引相同,并将忽略包含的列。(请注意,如果您的冗余索引仅包含列,则忽略包含的列可能会产生命名冲突。)

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

对于默认约束:

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

最后检查约束:

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

请注意,PRINT不一定会显示整个语句,具体取决于您对文本结果的设置和语句的大小。但它应该足以让人注意脚本正在做正确的工作。我默认将它们全部设置为PrintOnly

答案 1 :(得分:2)

要重命名外键,你可以使用这样的东西(这还没有完全你想要的东西 - 但足够接近开始吧):

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

基本上,您遍历数据库中定义的所有外键,并将它们重命名为某个名称,您决定如何在SELECT中构造该游标的基础。

然后将光标放在所有结果上,并执行dbo.sp_rename存储过程将FK约束重命名为您想要的任何结果。

使用Aaron的方法基本上构建一个巨大的SQL语句,你甚至可以在不使用游标的情况下离开。

这将是重命名&#34;系统命名的&#34;非常相似的代码。对您自己的命名约定的默认约束 - 它使用与上面相同的方法,对系统目录视图使用SELECT,然后使用游标迭代所有条目并构建并执行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 

答案 2 :(得分:1)

如果DB在不同的模式中具有类似的表,则解决方案将中断。这是我使用的this solution的修改。

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;

主键:

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

外键:

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

独特约束:

 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

默认约束:

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

检查约束:

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