6

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

  • 主键: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 脚本了吗?

4

3 回答 3

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 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(N'./text()[1]', N'nvarchar(max)'), 1, 1, N'') 
    + '_' + 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(N'./text()[1]', N'nvarchar(max)'), 1, 1, N'')  
        + ''', ''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(N'./text()[1]', N'nvarchar(max)'), 1, 1, N'')  
        +''', ''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为默认值。

于 2012-05-19T14:21:54.713 回答
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 语句,您甚至可以在不使用游标的情况下摆脱困境。

这将是将“系统命名”默认约束重命名为您自己的命名约定的非常相似的代码 - 它使用与上述相同的方法,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 
于 2012-05-19T14:25:41.147 回答
1

如果数据库在不同的模式中有类似的表,则提供的解决方案将会中断。这是我使用的这个解决方案的修改。

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
于 2013-11-11T22:21:44.570 回答