DWH-ETL-OLAP
October 8, 2019

Изменение Collation для всех столбцов всех таблиц БД

Если для БД изменить Collation не так сложно вручную через SSMS, то для каждого столбца придется писать дополнительный отдельный запрос, тк изменения collation для БД не означает автоматическое изменения этого параметра для каждого столбца.

Здесь поможет вот этот скриптик:

DECLARE @collate nvarchar(100);
DECLARE @table nvarchar(255);
DECLARE @column_name nvarchar(255);
DECLARE @column_id int;
DECLARE @data_type nvarchar(255);
DECLARE @max_length int;
DECLARE @row_id int;
DECLARE @sql nvarchar(max);
DECLARE @sql_column nvarchar(max);
SET @collate = 'SQL_Latin1_General_CP1251_CI_AS';
DECLARE local_table_cursor CURSOR FOR
SELECT SCHEMA_NAME(o.schema_id) +'.'+ so.[name]
FROM sysobjects so
join sys.objects o on o.object_id = so.id
WHERE OBJECTPROPERTY(id, N'IsUserTable') = 1
OPEN local_table_cursor
FETCH NEXT FROM local_table_cursor
INTO @table
WHILE @@FETCH_STATUS = 0
BEGIN
    DECLARE local_change_cursor CURSOR FOR
    SELECT ROW_NUMBER() OVER (ORDER BY ORDINAL_POSITION) AS row_id 
	,COLUMN_NAME column_name
	,data_type
	,CHARACTER_MAXIMUM_LENGTH max_length
	,ORDINAL_POSITION column_id
	from INFORMATION_SCHEMA.COLUMNS
	WHERE TABLE_SCHEMA + '.' + TAble_NAme = @table
    ORDER BY ORDINAL_POSITION    
OPEN local_change_cursor
    FETCH NEXT FROM local_change_cursor
    INTO @row_id, @column_name, @data_type, @max_length, @column_id
    WHILE @@FETCH_STATUS = 0
    BEGIN
        IF (@max_length = -1) OR (@max_length > 4000) SET @max_length = 4000;
        IF (@data_type LIKE '%char%')
        BEGIN TRY
            SET @sql = 'ALTER TABLE ' + @table + ' ALTER COLUMN ' + @column_name + ' ' + @data_type + '(' + CAST(@max_length AS nvarchar(100)) + ') COLLATE ' + @collate
            PRINT @sql
            EXEC sp_executesql @sql
        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 @row_id, @column_name, @data_type, @max_length, @column_id
    END
    CLOSE local_change_cursor
    DEALLOCATE local_change_cursor
    FETCH NEXT FROM local_table_cursor
    INTO @table
END
CLOSE local_table_cursor
DEALLOCATE local_table_cursor
GO