我有一个包含大量表的数据库,我想根据以下规则重命名主键/外键,索引和默认约束:
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脚本吗?
答案 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