2012-05-19 30 views
6

Tôi có một cơ sở dữ liệu với rất nhiều bảng, và tôi muốn đổi tên chính/phím nước ngoài, chỉ số và hạn chế mặc định theo các quy tắc sau:Thực hiện một tiêu chuẩn đặt tên cho các phím, các chỉ số, hạn chế

  • khóa chính: PK_<table name>
  • phím nước ngoài: FK_<table_name>_<column name1>_column name2>...
  • Indexes: IX_<table_name>_<column name1>_column name2>...
  • Mặc định ràng buộc: DF_<table_name>_<column name>
  • C heck Constraints: CK_<table_name>_<column name>

Ai đó đã thực hiện một tập lệnh SQL tương tự?

+0

bạn có thể chỉ định quy tắc khác, ví dụ nếu chỉ mục của bạn được lọc hoặc có cột INCLUDE, bạn cũng muốn chỉ định các cột đó hay chỉ các cột chính? Còn về ràng buộc kiểm tra và ràng buộc duy nhất thì sao? –

+0

Không thể nói rằng tôi có, nhưng tôi không bao giờ sử dụng GUI để tạo ra các công cụ, và tôi luôn luôn cung cấp cho tên công cụ của tôi trong kịch bản. Bạn có thể thử nghiệm làm điều trên, nhưng tôi nghĩ rằng sẽ dễ dàng hơn khi viết kịch bản cho db và chỉnh sửa để có được những gì bạn muốn, hơn là tìm ra ở trên. –

+0

Một suy nghĩ khác là cách đối phó với các đối tượng có dấu gạch dưới trong tên của chúng. Có thể khá khó hiểu khi đọc tên đối tượng của khóa ngoài cho trường hợp 'Document_Folder' có một cột có tên' Folder_Name' được tham chiếu bởi cột 'Document' 'Folder_Name'. 'FK_Document_Folder_Name_Document_Folder_Folder_Name'? Tôi không chắc là hữu ích hơn tên hệ thống được tạo ra 'FK__Document__Docum__1DE57479' ... –

Trả lời

8

Để đổi tên Primary Keys để đơn giản 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 

Để đổi tên FKS với chương trình 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 

Đối với các phím nước ngoài nếu bạn chỉ muốn FK_TableName_ReferencedName sau đó nó đơn giản hơn rất nhiều:

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 

Đối với chỉ mục, điều này sẽ đổi tên bất kỳ i ndexes IX_TableName_Col1_Col2.... Nó sẽ bỏ qua các khóa chính (vì chúng được xử lý riêng biệt ở trên), sẽ thêm UQ_ vào các chỉ mục/ràng buộc duy nhất (vì vậy IX_UQ_TableName_Col1_Col2..., sẽ xử lý các ràng buộc duy nhất và các chỉ mục duy nhất giống nhau, và sẽ bỏ qua các cột được bao gồm. tạo ra một cuộc xung đột đặt tên nếu bạn có chỉ số không cần thiết mà chỉ khác nhau bởi các cột bao gồm)

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 

Đối với những hạn chế mặc định:.

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 

Và cuối cùng kiểm tra các ràng buộc:

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 

Lưu ý rằng PRINT sẽ không nhất thiết tiết lộ toàn bộ câu lệnh, tùy thuộc vào cài đặt của bạn cho kết quả trong văn bản và kích thước của câu lệnh. Nhưng nó phải đủ tốt để nhãn cầu rằng các kịch bản đang làm đúng công việc. Tôi đặt tất cả chúng thành PrintOnly theo mặc định.

+0

Cảm ơn Aaron, tôi luôn học hỏi điều gì đó mới mẻ với câu trả lời của bạn. – psadac

2

Và để đổi tên các phím nước ngoài, bạn có thể sử dụng một cái gì đó như thế này (điều này vẫn chưa được làm chính xác những gì bạn muốn - nhưng đủ gần để bắt đầu vào nó):

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 

Về cơ bản, bạn lặp qua tất cả các khóa ngoài được xác định trong cơ sở dữ liệu của bạn và bạn đổi tên chúng thành một số tên mà bạn quyết định cách xây dựng trong SELECT là cơ sở của con trỏ này.

Sau đó, bạn chạy con trỏ trên tất cả các kết quả và thực hiện thủ tục được lưu trữ dbo.sp_rename để đổi tên ràng buộc FK của bạn thành bất kỳ thứ gì bạn muốn.

Sử dụng phương pháp của Aaron về cơ bản là xây dựng một câu lệnh SQL lớn duy nhất, thậm chí bạn có thể thoát ra mà không phải sử dụng con trỏ. Đây là mã rất giống với việc đổi tên các ràng buộc mặc định "hệ thống tên" thành quy ước đặt tên của riêng bạn - nó sử dụng cách tiếp cận tương tự như trên, SELECT đối với các chế độ xem danh mục hệ thống, và sau đó một con trỏ để lặp lại tất cả các mục nhập và xây dựng và thực thi câu lệnh đổi tên 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

Giải pháp được cung cấp sẽ phá vỡ nếu DB có bảng tương tự trong các lược đồ khác nhau. Đây là sửa đổi của tôi this solution, mà tôi sử dụng.

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; 

phím chính:

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 

Keys nước ngoài:

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 

Ràng buộc duy nhất:

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 

Mặc định khó khăn:

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 

Kiểm tra ràng buộc:

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 
Các vấn đề liên quan