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制約の名前を任意の名前に変更します。

基本的に1つの巨大なSQLステートメントを構築するというAaronのアプローチを使用すると、カーソルを使用せずに回避することもできます。

これは、「システム名」のデフォルト制約の名前を独自の命名規則に変更するための非常によく似たコードです。これは、上記と同じアプローチを使用し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

DBが異なるスキーマに同様のテーブルを持っている場合、提供されたソリューションは機能しなくなります。これが私が使用しているこのソリューションの私の修正です。

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 に答える