动态更新数据库中所有字段的整理

时间:2009-12-10 03:15:58

标签: sql-server-2008

我们最近将数据库从SQL Server 2005服务器迁移到SQL Server 2008服务器。一切都很好,但现在我们发现我们正在收集整理冲突。旧服务器与新服务器的排序规则不同。

现在我们在移动之前创建的表是一个排序规则,之后创建的表是另一个排序规则。

有没有办法用旧的排序规则更新表格/列到新排序规则?

我理解设置默认数据库/服务器排序规则不会修改任何现有表(link)。如果我不需要,我真的不想重新创建数据库。

任何帮助都非常感激。

更新

感谢您的帮助,终于让它工作了。

为了将来参考,这是我的最终脚本:

SELECT 'ALTER TABLE [' + SYSOBJECTS.Name + '] ALTER COLUMN [' + SYSCOLUMNS.Name + '] ' +
SYSTYPES.name + 
    CASE systypes.NAME
    WHEN 'text' THEN ' '
    ELSE
    '(' + RTRIM(CASE SYSCOLUMNS.length
    WHEN -1 THEN 'MAX'
    ELSE CONVERT(CHAR,SYSCOLUMNS.length)
    END) + ') ' 
    END

    + ' ' + ' COLLATE Latin1_General_CI_AS ' + CASE ISNULLABLE WHEN 0 THEN 'NOT NULL' ELSE 'NULL' END
    FROM SYSCOLUMNS , SYSOBJECTS , SYSTYPES
    WHERE SYSCOLUMNS.ID = SYSOBJECTS.ID
    AND SYSOBJECTS.TYPE = 'U'
    AND SYSTYPES.Xtype = SYSCOLUMNS.xtype
    AND SYSCOLUMNS.COLLATION IS NOT NULL
    AND NOT ( sysobjects.NAME LIKE 'sys%' )
    AND NOT ( SYSTYPES.name LIKE 'sys%' )
    GO

以下是包含我基于它的脚本的site。我不得不调整它以使其正常工作。

8 个答案:

答案 0 :(得分:10)

如果有人看着这个使用SQL Server 2008,我不得不做一些修改:

SELECT 'ALTER TABLE [' + sys.objects.name + '] ALTER COLUMN ['
+ sys.columns.name + '] ' + sys.types.name + 
    CASE sys.types.name
    WHEN 'text' THEN ' '
    ELSE
    '(' + RTRIM(CASE sys.columns.max_length
    WHEN -1 THEN 'MAX'
    ELSE CONVERT(CHAR,sys.columns.max_length)
    END) + ') ' 
    END

    + ' ' + ' COLLATE Latin1_General_BIN ' + CASE sys.columns.is_nullable WHEN 0 THEN 'NOT NULL' ELSE 'NULL' END
    FROM sys.columns , sys.objects , sys.types
    WHERE sys.columns.object_id = sys.objects.object_id
    AND sys.objects.TYPE = 'U'
    AND sys.types.system_type_id = sys.columns.system_type_id
    AND sys.columns.collation_name IS NOT NULL
    AND NOT ( sys.objects.NAME LIKE 'sys%' )
    AND NOT ( sys.types.name LIKE 'sys%' )

答案 1 :(得分:6)

您可以使用ALTER DATABASE语句的COLLATE子句更改在用户数据库中创建的任何对象的排序规则。此语句更改任何现有用户定义表中列的排序规则。可以使用ALTER TABLE的COLLATE子句更改这些内容。

参考:Setting and Changing the Database Collation

如果列太多,可以循环访问SYS.COLUMNS以应用ALTER TABLE语句。

答案 2 :(得分:4)

怎么样:

DECLARE @collation NVARCHAR(64)
SET @collation = 'Latin1_General_CI_AS'

SELECT
    'ALTER TABLE [' + TABLE_SCHEMA  + '].[' + TABLE_NAME + '] '
  + 'ALTER COLUMN [' + COLUMN_NAME + '] '
  + DATA_TYPE + '(' + CASE CHARACTER_MAXIMUM_LENGTH 
        WHEN -1 THEN 'MAX' 
        ELSE CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR) END + ') '
  + 'COLLATE ' + @collation + ' '
  + CASE WHEN IS_NULLABLE = 'NO' THEN 'NOT NULL' ELSE 'NULL' END
FROM INFORMATION_SCHEMA.columns
WHERE  COLLATION_NAME IS NOT NULL
AND COLLATION_NAME <> @collation

答案 3 :(得分:3)

要解决此问题,您需要此脚本提供的更多火力。我尝试了脚本并遇到了无法更新的依赖对象的问题:索引,键和过程。使用此代码项目应用程序,最终解决方案仅需5分钟。该应用程序说它适用于Sql Server 2000,但我在2008年成功使用它。

http://www.codeproject.com/Articles/12753/SQL-Server-2000-Collation-Changer

我不能强调这一点。备份你的数据库。我必须使用我的备份三次来完成这项任务。

答案 4 :(得分:2)

一个选项是使用像Red Gate SQL Compare这样的程序(我确定还有其他程序)。有了它,你可以为你的架构生成包含整理的脚本文件(确保在选项中打开它),然后在文件中搜索/替换将其更新为新的整理,然后将它们重新比较回实际数据库中。

此时,SQL Compare将能够应用这些更改(或者如果您愿意,可以将更改保存到脚本文件中),并且您现有的列都已修复。

从理论上讲,你可以在试用期间完成所有这些工作,但我建议它是一个很好的工具,因为它可以让许多SQL任务变得更容易!

答案 5 :(得分:1)

在Owais Iqbal的回答rewritten the code by edosoft and put it in a loop to execute the actual T-SQL statements之前,您可以从数据库中获取默认排序规则

-- **************** BEGIN INPUT **********************
USE [YourDBName]
-- **************** END INPUT ************************

-- **************** BEGIN GET DB COLLATION ***********
DECLARE @collation NVARCHAR(128)
SELECT @collation = collation_name
FROM sys.databases WHERE database_id = DB_ID()

PRINT 'Default database collation: ' + @collation
PRINT ''
-- **************** END GET DB COLLATION *************

-- **************** BEGIN LOGIC **********************

答案 6 :(得分:0)

好的,我已经重新编写了edosoft的代码并将其放在一个循环中来执行实际的T-SQL语句。

-- **************** BEGIN INPUT **********************
USE [YourDBName]

DECLARE @collation NVARCHAR(128)
-- enter you collation name below
SET @collation = N'Latin1_General_CI_AS'
-- **************** END INPUT ************************

-- **************** BEGIN LOGIC **********************
DECLARE @sqlCode VARCHAR(2048)

DECLARE myCursor CURSOR LOCAL FOR
    SELECT 'ALTER TABLE [' + sys.objects.name + '] 
        ALTER COLUMN ['+ sys.columns.name + '] ' + sys.types.name + 
        CASE sys.types.name
            WHEN 'text' THEN ' '
            WHEN 'ntext' THEN ' '
            ELSE '(' + RTRIM(
                CASE
                    WHEN sys.columns.max_length = -1 THEN 'MAX'
                    WHEN sys.columns.max_length > 4000 THEN 'MAX'
                    ELSE CONVERT(CHAR,sys.columns.max_length)
                END) + ')' 
        END
        + ' COLLATE ' + @collation + CASE sys.columns.is_nullable WHEN 0 THEN ' NOT NULL' ELSE ' NULL' END
        FROM sys.columns , sys.objects , sys.types
        WHERE sys.columns.object_id = sys.objects.object_id
            AND sys.objects.TYPE = 'U'
            AND sys.types.system_type_id = sys.columns.system_type_id
            AND sys.columns.collation_name IS NOT NULL
            AND sys.columns.collation_name <> @collation
            AND NOT ( sys.objects.NAME LIKE 'sys%' )
            AND NOT ( sys.types.name LIKE 'sys%' )

OPEN myCursor
FETCH NEXT FROM myCursor INTO @sqlCode

WHILE @@FETCH_STATUS = 0 BEGIN
    PRINT 'Executing: ' + @sqlCode
    BEGIN TRY
        EXEC(@sqlCode);
        PRINT 'Done!' + CHAR(10)
    END TRY
    BEGIN CATCH
        PRINT 'Error: ' + ERROR_MESSAGE() + CHAR(10)
    END CATCH
    FETCH NEXT FROM myCursor INTO @sqlCode
END

PRINT 'Finished!'
-- **************** END LOGIC **********************

如果您收到类似于“无法创建大小为8075且大于允许的最大行大小8060的行”的错误。重建您收到错误的表并再次运行上面的脚本。

ALTER TABLE [dbo].[YourTableName] REBUILD 

答案 7 :(得分:-3)

代码无法考虑NText,NChar和NVarchar双字节。 如果您有NText,它将失败,Ntext(16)无法在NText上设置大小。

对于NChar和NVarChar,它的长度加倍,因为它无法将大小除以2。

另一个古怪的小细节,至少对于Nvarchar来说,-1不是MAX,而是0。

这是一个非常非常难看的代码,只是为了说明问题:

ALTER TABLE [BlanketBruger] ALTER COLUMN [BrugerNavn] nvarchar(50)   COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
ALTER TABLE [BlanketBruger] ALTER COLUMN [BrugerFuldNavn] nvarchar(255)   COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
ALTER TABLE [blanketgruppe] ALTER COLUMN [GruppeNavn] nvarchar(255)   COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
ALTER TABLE [blanketSerie] ALTER COLUMN [SerieTitel] nvarchar(255)   COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
ALTER TABLE [blanketSerie] ALTER COLUMN [SerieAlias] nvarchar(255)   COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
ALTER TABLE [FormUse] ALTER COLUMN [HostName] nvarchar(50)   COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
ALTER TABLE [BackendLog] ALTER COLUMN [value1] nvarchar(1000)   COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE [BackendLog] ALTER COLUMN [value2] nvarchar(1000)   COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE [BackendLog] ALTER COLUMN [ip] varchar(20)   COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
ALTER TABLE [BackendLog] ALTER COLUMN [username] nvarchar(100)   COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE [BackendLog] ALTER COLUMN [gruppenavn] nvarchar(100)   COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE [BackendLog] ALTER COLUMN [scriptname] nvarchar(100)   COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
ALTER TABLE [BackendLog] ALTER COLUMN [querystring] nvarchar(1000)   COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE [BackendLog] ALTER COLUMN [useragent] nvarchar(400)   COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE [BackendLog] ALTER COLUMN [sessionid] varchar(50)   COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE [BackendLog] ALTER COLUMN [htmlcontent] nvarchar(MAX)   COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE [frontendlog] ALTER COLUMN [value1] nvarchar(1000)   COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE [frontendlog] ALTER COLUMN [value2] nvarchar(1000)   COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE [frontendlog] ALTER COLUMN [ip] nvarchar(50)   COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE [frontendlog] ALTER COLUMN [querystring] nvarchar(1000)   COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE [frontendlog] ALTER COLUMN [useragent] nvarchar(400)   COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE [frontendlog] ALTER COLUMN [sessionid] nvarchar(50)   COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE [log4net] ALTER COLUMN [Thread] varchar(255)   COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
ALTER TABLE [log4net] ALTER COLUMN [Level] varchar(50)   COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
ALTER TABLE [log4net] ALTER COLUMN [Logger] varchar(255)   COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
ALTER TABLE [log4net] ALTER COLUMN [Message] text   COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
ALTER TABLE [log4net] ALTER COLUMN [Exception] varchar(MAX)   COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE [log4net] ALTER COLUMN [Server] varchar(255)   COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE [OioSamlLog] ALTER COLUMN [Server] varchar(255)   COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
ALTER TABLE [OioSamlLog] ALTER COLUMN [Thread] varchar(255)   COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
ALTER TABLE [OioSamlLog] ALTER COLUMN [Level] varchar(50)   COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
ALTER TABLE [OioSamlLog] ALTER COLUMN [Message] varchar(MAX)   COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE [BlanketSubmitTemp] ALTER COLUMN [FileContentIdentifier] nvarchar(50)   COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
ALTER TABLE [BlanketSubmitTemp] ALTER COLUMN [FileContent] ntext   COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE [BlanketSubmitTemp] ALTER COLUMN [FileName] nvarchar(255)   COLLATE SQL_Latin1_General_CP1_CI_AS NULL