生成脚本以自动重命名默认约束


8

背景:某些默认的列约束是在没有显式名称的情况下生成的,因此我们得到的有趣的名称因服务器而异,例如: DF__User__TimeZoneIn__5C4D869D

我希望使用一致的命名方式来管理它们,DF_Users_TimeZoneInfo以便我们可以确保将来的目标表上存在适当的约束(例如在RedGate比较中,甚至只是在视觉上)

我有一个脚本,该脚本通常可以满足我的需求:

select 'sp_rename N''[' + s.name + '].[' + d.name + ']'', 
   N''[DF_' + t.name + '_' + c.name + ']'', ''OBJECT'';'
from sys.tables t
    join
    sys.default_constraints d
        on d.parent_object_id = t.object_id
    join
    sys.columns c
        on c.object_id = t.object_id
        and c.column_id = d.parent_column_id
    join sys.schemas s
        on t.schema_id = s.schema_id
WHERE d.NAME like 'DF[_][_]%'

但这只是给我一个结果集,而不是我可以实际传递给exec或其他东西的东西。

如何做到这一点,这样我就可以执行那些sp_rename脚本,而不必复制所有返回的元素并将它们粘贴到新的查询窗口中并再次运行它们?尝试保存尽可能多的击键,以便在许多环境中都可以解决此问题。

在此处输入图片说明


<facepalm>您应该在前几天问我有关此问题的信息-我从确实具有此功能的脚本中获取了答案。:)
乔恩·塞格尔

@JonSeigel好的,围绕此级别的指示如何在几个数据库中的每个数据库上运行一次?:D
jcolebrand

不要在新名称前加上方括号-运行此脚本后,我
感到非常痛苦

Answers:


16

好,几件事。

  1. EXEC在执行存储过程时始终使用;EXEC仅当它是批处理中的第一条语句时,速记表才有效(在此情况下不会如此)。
  2. 始终使用分号终止符 -在这种情况下,它们可以代替漂亮的回车符和缩进来使用,但始终明智。
  3. 始终使用QUOTENAME()而不是自己手动应用方括号。在这种情况下,您可能是安全的,但是在某些情况下,手动方法会中断。
  4. 您可以测试PRINT输出,但是如果您的总命令> 8k,则不一定是完整的(有关其他替代方法,请参见此技巧)。

    DECLARE @sql nvarchar(max) = N'';
    
    SELECT @sql += N'EXEC sys.sp_rename N''' 
        + QUOTENAME(s.name) + '.' + QUOTENAME(d.name) 
        + ''', N''DF_' + t.name + '_' + c.name + ''', ''OBJECT'';'
      FROM sys.tables AS t
      INNER JOIN sys.default_constraints AS d
         ON d.parent_object_id = t.object_id
      INNER JOIN sys.columns AS c
         ON c.object_id = t.object_id
        AND c.column_id = d.parent_column_id
      INNER JOIN sys.schemas AS s
         ON t.schema_id = s.schema_id
      WHERE d.NAME LIKE N'DF[_][_]%';
    
    PRINT @sql;
    -- EXEC sys.sp_executesql @sql;

很高兴知道每个语句的EXEC,我不知道。
jcolebrand

3
是的,请尝试执行以下操作:sp_help; sp_help;
亚伦·伯特兰

3

根据您的问题..您已删除了“在实例上的某些数据库上自动执行相同的脚本”

以下是可以帮助您的代码

set nocount on
DECLARE @table TABLE 
  ( 
     dbname VARCHAR(30) 
  ) 

INSERT INTO @table 
            (dbname) 
VALUES      ( 'dev_construct1' ), 
            ('dev_construct2'), 
            ('dev_construct3' ); 

DECLARE @sql NVARCHAR(max) = N''; 
DECLARE @dbname VARCHAR(30) 

/*  
Added by Kin : While loop and an extra @dbname variable 
*/ 
SELECT @dbname = Min(dbname) 
FROM   @table 

WHILE @dbname IS NOT NULL 
  BEGIN 
      SELECT @sql = N'USE ' + tt.dbname + Char(10) + N' GO;'
      FROM   @table tt 
      WHERE  @dbname = dbname 

      SELECT @sql += Char(10) + N'EXEC sp_rename N''' 
                     + Quotename(s.name) + '.' + Quotename(d.name) 
                     + ''', N''DF_' + t.name + '_' + c.name 
                     + ''', ''OBJECT'';' 
      FROM   sys.tables AS t 
             JOIN sys.default_constraints d 
               ON d.parent_object_id = t.object_id 
             JOIN sys.columns c 
               ON c.object_id = t.object_id 
                  AND c.column_id = d.parent_column_id 
             JOIN sys.schemas s 
               ON t.schema_id = s.schema_id 
             JOIN @table tt 
               ON tt.dbname = tt.dbname 
      WHERE  d.name LIKE 'DF[_][_]%'; 

      PRINT @sql 

      SELECT @dbname = Min(dbname) 
      FROM   @table 
      WHERE  dbname > @dbname 
  END 
-- EXEC sp_executesql @sql; 

我删除了它,是因为上一个问题缺少关键细节,因为每个数据库中的列名都发生了变化,所以我需要针对单个数据库的上下文运行内部查询。
jcolebrand

@jcolebrand感谢您的更新。无论如何,经过我的更改的代码将为您提供所需的帮助。
Kin Shah 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.