Implementation of a standard for naming keys, indexes, restrictions

I have a database with a large number of tables, and I want to rename primary / foreign keys, indexes, and default restrictions according to the following rules:

  • Primary keys: PK_<table name>
  • Foreign keys: FK_<table_name>_<column name1>_column name2>...
  • Indexes: IX_<table_name>_<column name1>_column name2>...
  • Default restrictions: DF_<table_name>_<column name>
  • Check restrictions: CK_<table_name>_<column name>

Has someone already executed a similar SQL script?

+6
source share
3 answers

To rename primary keys simply 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 

To rename an FK with the schema 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 

For foreign keys, if you just want FK_TableName_ReferencedName , then this is much simpler:

 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 

For indexes, this will rename any indexes IX_TableName_Col1_Col2... It will ignore primary keys (as they are discussed separately above), add UQ_ to unique indexes / constraints (so IX_UQ_TableName_Col1_Col2... will handle unique constraints and unique indexes in the same way and will ignore included columns. Ignoring included columns can lead to name conflicts if you have redundant indexes that differ only in the columns included.)

 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 

For default restrictions:

 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 

And finally, check the limitations:

 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 

Please note that PRINT will not necessarily show the entire operator, depending on your settings for the results in the text and the size of the instruction. But it should be good enough for the eyeball that the scripts do the right job. I set them all to PrintOnly by default.

+8
source

And to rename foreign keys, you can use something like this (it doesn't do what you wanted yet - but close enough to start with it):

 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 

Basically, you iterate over all the foreign keys defined in your database and rename them to some name that you determine how to build in the SELECT that underlies this cursor.

Then you hover over all the results and execute the dbo.sp_rename stored procedure to rename the FK constraint to whatever you want.

Using the Aaron approach, just creating one huge SQL query, you can even leave without using a cursor.

This would be very similar code to rename the "system" default constraints for your own naming convention - it uses the same approach as above, a SELECT for representations of the system catalog, and then a cursor to iterate over all entries and create and execute the SQL rename statement:

 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
source

Provided that the solutions will be broken if the database has similar tables in different schemes. Here, my modification is the solution I am using.

 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; 

Primary Keys:

 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 

Foreign keys:

 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 

Unique restrictions:

  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 

Default Limitations:

 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 

Check restrictions:

 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 
+1
source

Source: https://habr.com/ru/post/916159/


All Articles