如何将整理更改为数据库的所有列?

时间:2013-05-24 07:48:49

标签: sql-server collation

我想更改数据库所有表的所有列的排序规则。在堆栈溢出的其他帖子中,我找到了这个脚本:(post

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_AI ' + 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

然而,当我看到列的整理时,我发现整理是旧的整理。

实际的整理是AS,所以我可以拥有“ANIMAL”和“ÁNIMAL”。当我执行脚本时,我没有收到任何错误。我认为我会得到一个错误,因为新的排序规则是AI。所以这让我觉得脚本什么都不做。

为什么我可以更改数据库中所有表的所有列的排序规则?

感谢。

7 个答案:

答案 0 :(得分:75)

试试这个 -

<强>查询:

DECLARE @collate SYSNAME
SELECT @collate = 'Cyrillic_General_CS_AS'

SELECT 
      '[' + SCHEMA_NAME(o.[schema_id]) + '].[' + o.name + '] -> ' + c.name
    , 'ALTER TABLE [' + SCHEMA_NAME(o.[schema_id]) + '].[' + o.name + ']
        ALTER COLUMN [' + c.name + '] ' +
        UPPER(t.name) + 
        CASE WHEN t.name NOT IN ('ntext', 'text') 
            THEN '(' + 
                CASE 
                    WHEN t.name IN ('nchar', 'nvarchar') AND c.max_length != -1 
                        THEN CAST(c.max_length / 2 AS VARCHAR(10))
                    WHEN t.name IN ('char', 'varchar') AND c.max_length != -1 
                        THEN CAST(c.max_length AS VARCHAR(10))
                    WHEN t.name IN ('nchar', 'nvarchar', 'char', 'varchar') AND c.max_length = -1 
                        THEN 'MAX'
                    ELSE CAST(c.max_length AS VARCHAR(10)) 
                END + ')' 
            ELSE '' 
        END + ' COLLATE ' + @collate + 
        CASE WHEN c.is_nullable = 1 
            THEN ' NULL'
            ELSE ' NOT NULL'
        END
FROM sys.columns c
JOIN sys.objects o ON c.[object_id] = o.[object_id]
JOIN sys.types t ON c.system_type_id = t.system_type_id AND c.user_type_id = t.user_type_id
WHERE t.name IN ('char', 'varchar', 'text', 'nvarchar', 'ntext', 'nchar')
    AND c.collation_name != @collate
    AND o.[type] = 'U'

<强>输出:

-------------------------------------------------- ------------------------------------------------------------------------------------------------------------------
[dbo].[CategoryType] -> CategoryTypeCD          ALTER TABLE [dbo].[CategoryType] ALTER COLUMN [CategoryTypeCD] VARCHAR(20) COLLATE Cyrillic_General_CI_AS NOT NULL
[dbo].[Employee] -> TabelNumber                 ALTER TABLE [dbo].[Employee] ALTER COLUMN [TabelNumber] VARCHAR(12) COLLATE Cyrillic_General_CI_AS NULL
[dbo].[Supplement] -> WorkFactorCD              ALTER TABLE [dbo].[Supplement] ALTER COLUMN [WorkFactorCD] VARCHAR(50) COLLATE Cyrillic_General_CI_AS NOT NULL
[dbo].[Surcharge] -> WorkFactorCD               ALTER TABLE [dbo].[Surcharge] ALTER COLUMN [WorkFactorCD] VARCHAR(50) COLLATE Cyrillic_General_CI_AS NOT NULL
[dbo].[Surcharge] -> Condition                  ALTER TABLE [dbo].[Surcharge] ALTER COLUMN [Condition] NVARCHAR(MAX) COLLATE Cyrillic_General_CI_AS NULL
[dbo].[WorkFactor] -> WorkFactorCD              ALTER TABLE [dbo].[WorkFactor] ALTER COLUMN [WorkFactorCD] VARCHAR(50) COLLATE Cyrillic_General_CI_AS NOT NULL
[dbo].[WorkFactor] -> Name                      ALTER TABLE [dbo].[WorkFactor] ALTER COLUMN [Name] NVARCHAR(200) COLLATE Cyrillic_General_CI_AS NOT NULL
[dbo].[WorkOut] -> WorkShiftCD                  ALTER TABLE [dbo].[WorkOut] ALTER COLUMN [WorkShiftCD] NVARCHAR(40) COLLATE Cyrillic_General_CI_AS NULL
[dbo].[WorkOut] -> AbsenceCode                  ALTER TABLE [dbo].[WorkOut] ALTER COLUMN [AbsenceCode] VARCHAR(50) COLLATE Cyrillic_General_CI_AS NULL
[dbo].[WorkOut] -> PaymentType                  ALTER TABLE [dbo].[WorkOut] ALTER COLUMN [PaymentType] CHAR(4) COLLATE Cyrillic_General_CI_AS NULL

答案 1 :(得分:7)

我发布了上述答案的编辑内容,该编辑针对char和varchar长度,因为我之前的编辑看起来被拒绝了。

DECLARE @collate SYSNAME
SELECT @collate = 'Cyrillic_General_CS_AS'

SELECT 
  '[' + SCHEMA_NAME(o.[schema_id]) + '].[' + o.name + '] -> ' + c.name
, 'ALTER TABLE [' + SCHEMA_NAME(o.[schema_id]) + '].[' + o.name + ']
    ALTER COLUMN [' + c.name + '] ' +
    UPPER(t.name) + 
    CASE WHEN t.name NOT IN ('ntext', 'text') 
        THEN '(' + 
            CASE 
                WHEN t.name IN ('nchar', 'nvarchar') AND c.max_length != -1 
                    THEN CAST(c.max_length / 2 AS VARCHAR(10))
                WHEN t.name IN ('char', 'varchar') AND c.max_length != -1 
                    THEN CAST(c.max_length AS VARCHAR(10))
                WHEN t.name IN ('nchar', 'nvarchar', 'char', 'varchar') AND c.max_length = -1 
                    THEN 'MAX'
                ELSE CAST(c.max_length AS VARCHAR(10)) 
            END + ')' 
        ELSE '' 
    END + ' COLLATE ' + @collate + 
    CASE WHEN c.is_nullable = 1 
        THEN ' NULL'
        ELSE ' NOT NULL'
    END
FROM sys.columns c WITH(NOLOCK)
    JOIN sys.objects o WITH(NOLOCK) ON c.[object_id] = o.[object_id]
    JOIN sys.types t WITH(NOLOCK) ON c.system_type_id = t.system_type_id AND c.user_type_id = t.user_type_id
WHERE t.name IN ('char', 'varchar', 'text', 'nvarchar', 'ntext', 'nchar')
    AND c.collation_name != @collate
    AND o.[type] = 'U'

答案 2 :(得分:5)

我已将各种不同来源的脚本放在一起,删除依赖项会更新排序规则,然后重新创建依赖对象。这解决了更新具有依赖项(索引,外键约束等)的列的排序规则的问题。

dynamic-component

答案 3 :(得分:2)

感谢大家的建议,在将我的数据库从SQL Server 2008 R2迁移到2014时,它对我有很大帮助

注意:部分结果查询包含无效的VARCHAR( - ),我将其更改为VARCHAR(MAX),并且工作正常。

更改排序规则的步骤:

  1. 运行以上查询并获取Alter表查询
  2. 删除表和表值函数的所有索引
  3. 运行步骤1的生成查询
  4. 创建表和表值函数的索引。

答案 4 :(得分:2)

虽然其他方法都不适合我,this article by Douglas P. Castilho为我提供了一个完整的解决方案。我正在分享它,以防它帮助任何人。

  1. 创建所有数据库的备份。
  2. 停止服务器上的SQL Server服务。
  3. 打开命令提示符并导航到Binn目录,如
  4.   

    C:\ Program Files \ Microsoft SQL Server \ MSSQL11.MSSQLSERVER \ MSSQL \ Binn

    1. 执行以下命令以应用新的排序规则。
    2.   

      sqlservr -m -T4022 -T3659 -q&#34; [输入整理名称]&#34;

      1. 再次启动SQL Server服务。
      2. 那就是它。

答案 5 :(得分:1)

在执行此操作之前,请先阅读本文。 https://www.mssqltips.com/sqlservertip/3221/how-to-change-the-collation-of-a-sql-server-column/

阅读上述文章后,请确保从数据库中删除了以下引用。

  • 计算列
  • 生成的索引分布统计信息 自动或通过CREATE STATISTICS语句
  • 检查约束
  • FOREIGN KEY约束

在您忘记更改数据库归类后,点击数据库中的以下脚本。

DECLARE @collate nvarchar(100);
DECLARE @schema_name nvarchar(255);
DECLARE @table_name nvarchar(255);
DECLARE @column_name nvarchar(255);
DECLARE @column_id int;
DECLARE @data_type nvarchar(255);
DECLARE @max_length int;
DECLARE @is_nullable bit; 
DECLARE @sql nvarchar(max);
DECLARE @sql_column nvarchar(max);

SET @collate = 'SQL_Latin1_General_CP1_CI_AS';


WHILE @@FETCH_STATUS = 0
BEGIN

    DECLARE local_change_cursor CURSOR FOR

    SELECT SCHEMA_NAME(t.schema_id) schemaname,
          t.name table_name
        , c.name column_name
        , s.Name data_type
        , c.max_length
        , c.is_nullable
        , c.column_id 
  FROM sys.tables t INNER JOIN
       sys.columns c ON c.object_id=t.object_id INNER JOIN
       sys.types s ON s.user_type_id=c.user_type_id
 WHERE 
 (c.collation_name LIKE 'SQL_Latin1_General_CP1254_CI_AS' OR c.collation_name LIKE 'Turkish_CI_AS')  AND 
 t.type like 'U'
   AND t.name not like 'spt%'
   AND t.name not like 'MSrep%'
   AND c.collation_name is NOT NULL
order by schemaname 

    OPEN local_change_cursor
    FETCH NEXT FROM local_change_cursor
    INTO @schema_name,@table_name, @column_name, @data_type, @max_length,@is_nullable, @column_id

    WHILE @@FETCH_STATUS = 0
    BEGIN

        DECLARE @nullable nvarchar(255),
                @length   varchar(10);

        IF @is_nullable = 0
            BEGIN
                SET @nullable = ' NOT NULL';
            END
        ELSE 
            BEGIN
                SET @nullable = ' NULL';
            END

            IF @data_type IN ('nchar', 'nvarchar') AND @max_length != -1 
                BEGIN
                    SET @length= CAST(@max_length / 2 AS VARCHAR(10));
                END 
            ELSE IF @data_type IN ('char', 'varchar') AND @max_length != -1 
                BEGIN
                    SET @length= CAST(@max_length AS VARCHAR(10));
                END 
            ELSE IF @data_type IN ('nchar', 'nvarchar', 'char', 'varchar') AND @max_length = -1 
                BEGIN
                    SET @length= 'MAX';
                END 
            ELSE 
                BEGIN
                    SET @length= CAST(@max_length AS VARCHAR(10));
                END

        BEGIN TRY
            IF @schema_name <> 'dbo'
                BEGIN
                    SET @sql = 'ALTER TABLE ['+ @schema_name +'].[' + @table_name + '] ALTER COLUMN [' + @column_name + '] ' + @data_type + '(' + @length + ') COLLATE ' + @collate + ''+ @nullable+' '
                    PRINT @sql
                    EXEC sp_executesql @sql
                END
        END TRY
        BEGIN CATCH
            PRINT 'ERROR: Some index or constraint rely on the column' + @column_name + '. No conversion possible.'
            PRINT @sql
        END CATCH

        FETCH NEXT FROM local_change_cursor
        INTO @schema_name,@table_name, @column_name, @data_type, @max_length,@is_nullable, @column_id

    END

    CLOSE local_change_cursor
    DEALLOCATE local_change_cursor
END

GO

答案 6 :(得分:0)

对于正在使用PHPMyAdmin寻找该解决方案的任何人,“数据库操作”选项卡底部都有一个选项(首先单击数据库,然后在顶部工具栏上单击“操作”选项卡);向下滚动到排序规则框,选择一个排序规则,选中两个复选框(选中第一个时出现一个复选框):

  • 更改所有表的排序规则
  • 更改所有表的列排序规则

似乎基本上像发布的脚本那样运行脚本;控制台显示最终执行的命令:

ALTER TABLE `DB_NAME`.`LAST_TABLE_IN_DB`DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci