以编程方式重命名所有系统名称约束

时间:2015-05-27 18:49:57

标签: sql sql-server sql-server-2008

我有一个分布式应用程序,它位于许多客户站点。以前的开发人员在为约束提供用户定义的名称方面不是很好。我怎样才能将所有约束重命名为'DF_ [TableName] _ [ColumnName]'?我可以尝试将光标放在表格列表上。如果我将其部署到客户站点,您认为这会有问题吗?或者有更好的方法来实现这一目标吗?

SELECT sys.schemas.name as [Schema],
sys.tables.name as [TableName],
sys.all_columns.name as [Column],
  default_constraints.name as [Constraint]
  FROM
    sys.all_columns
       INNER JOIN sys.tables
        ON all_columns.object_id = tables.object_id
       INNER JOIN sys.schemas
        ON tables.schema_id = schemas.schema_id
       INNER JOIN sys.default_constraints
        ON all_columns.default_object_id = default_constraints.object_id
       where default_constraints.name like '%[0-9]%'

1 个答案:

答案 0 :(得分:3)

如果您对每种约束类型使用命名约定,那么这将对您有所帮助。这里我举一个如何使用Default约束来处理它的例子。该过程将找到默认约束,删除那些不遵循命名约定的约束,并使用旧的约定创建新的约束。

这是一次运行的简单版本

 DECLARE @SchemaName sysname = 'dbo';
 DECLARE @TableName sysname = NULL;
 DECLARE @ColumnName sysname = NULL;
 DECLARE @sql VARCHAR(max) = '';

SELECT
@sql += 
  'ALTER TABLE [' + s.name + '].[' + o.name + '] DROP CONSTRAINT [' + dc.name + ']; ' + 
  'ALTER TABLE [' + s.name + '].[' + o.name + '] ADD  CONSTRAINT [DF_' + o.name + '_' + c.name + '] DEFAULT ' + dc.DEFINITION + ' FOR [' + c.name + '];'

  FROM dbo.sysobjects do
        INNER JOIN dbo.sysobjects o ON do.parent_obj = o.id
        INNER JOIN sys.default_constraints dc ON dc.object_id = do.id
        INNER JOIN sys.columns c ON c.object_id = o.id
                   AND c.column_id = dc.parent_column_id
        INNER JOIN sys.schemas s ON s.schema_id = dc.schema_id
  WHERE o.type = 'U' 
       AND do.type = 'D'
       AND s.name = @SchemaName
       AND o.name = CASE WHEN ISNULL(@TableName,'') = '' 
                        THEN o.name 
                        ELSE @TableName END
       AND c.name = CASE WHEN ISNULL(@ColumnName,'') = ''
                         THEN c.name 
                         ELSE @ColumnName END
       AND do.name NOT LIKE 'DF_' + o.name + '_' + c.name
  ORDER BY o.name
 --PRINT (@sql)
  EXECUTE(@sql)

这是一个程序,以防您希望每隔一段时间继续运行该程序

USE [YourDatabaseName]
    GO
    -- Check if the procedure exists and drop it if so
    IF  EXISTS (SELECT * 
                FROM sys.objects 
                WHERE object_id = OBJECT_ID(N'[dbo].[usp_NamingConventionDefaultConstraint]') AND type in (N'P', N'PC'))
    DROP PROCEDURE [dbo].[usp_NamingConventionDefaultConstraint]
    GO

    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    --procedure can be used for specific schema/table/columns or those can be left null to include everything. 
    CREATE PROC [dbo].[usp_NamingConventionDefaultConstraint]
                @SchemaName sysname = 'dbo',
                @TableName sysname = NULL,
                @ColumnName sysname = NULL
    AS
    BEGIN
        SET NOCOUNT ON;

        DECLARE @sql VARCHAR(max)

        DECLARE GetIndexes CURSOR
        FOR
            SELECT
 --here drop the old constraint and create a new one with the old's definition
            'ALTER TABLE [' + s.name + '].[' + o.name + '] DROP CONSTRAINT [' + dc.name + ']; ' + 
            'ALTER TABLE [' + s.name + '].[' + o.name + '] ADD  CONSTRAINT [DF_' + o.name + '_' + c.name + '] DEFAULT ' + dc.DEFINITION + ' FOR [' + c.name + '];'
            AS dc_alter
            FROM dbo.sysobjects do
            INNER JOIN dbo.sysobjects o ON do.parent_obj = o.id
            INNER JOIN sys.default_constraints dc ON dc.object_id = do.id
            INNER JOIN sys.columns c ON c.object_id = o.id 
                                     AND c.column_id = dc.parent_column_id
            INNER JOIN sys.schemas s ON s.schema_id = dc.schema_id
            WHERE o.type = 'U' 
            -- work only on default constraints 
            AND do.type = 'D'
            AND s.name = @SchemaName
            AND o.name = CASE WHEN ISNULL(@TableName,'') = '' THEN o.name ELSE @TableName END
            AND c.name = CASE WHEN ISNULL(@ColumnName,'') = '' THEN c.name ELSE @ColumnName END
            -- here goes the naming convention you have in mind
            --DF_TableName_ColumnName
            AND do.name NOT LIKE 'DF_' + o.name + '_' + c.name
            ORDER BY o.name

        OPEN GetIndexes

        FETCH NEXT FROM GetIndexes
        INTO @sql   

        WHILE @@FETCH_STATUS = 0
        BEGIN
            IF  ISNULL(@sql,'')<>''
            BEGIN
                EXEC (@sql)
            END

            FETCH NEXT FROM GetIndexes
            INTO @sql   
        END

        CLOSE   GetIndexes
        DEALLOCATE  GetIndexes

    END
    GO