작동버젼 : SQL Sserver 2005 이상
사용방법 : Edit Here 라고 표기되어 있는 곳 수정(타겟 DB명, 변경하고자 하는 Collation명으로 변경)
주의사항 : 여러 Collation이 존재해야 하는 DB에서는 사용하지 말것!
설 명 : DBMS의 Collation이 잘못 설치된 상태에서 디비 생성이 됬을 경우
명시적으로 생성하지 않았다면 테이블의 char, varchar컬럼등도 변경이 필요 하기에 만든 스크립트
전 영역 변경이 필요하지 않을 경우 스크립트 만 추출하여 실행 할 수 있음
--Edit Here
USE [YourDB];
GO
SET NOCOUNT ON;
IF OBJECT_ID('tempdb.dbo.#AlterCollateQuery', 'U') IS NOT NULL
DROP TABLE #AlterCollateQuery;
GO
CREATE TABLE #AlterCollateQuery
(
ExecuteOrder int identity(1,1)
,Query nvarchar(4000)
)
GO
IF OBJECT_ID('dbo.F_GetForeignKeyColumns', 'FN') IS NOT NULL
DROP FUNCTION dbo.F_GetForeignKeyColumns;
GO
CREATE FUNCTION dbo.F_GetForeignKeyColumns
(
@object_id int
)
RETURNS varchar(4000)
AS
BEGIN
DECLARE @return varchar(4000);
DECLARE @referenced_object_id int;
DECLARE @parent_columns varchar(4000);
DECLARE @referenced_columns varchar(4000);
SET @parent_columns = '';
SET @referenced_columns = '';
SELECT
@referenced_object_id = a.referenced_object_id
,@parent_columns = @parent_columns + N', [' + b.name + N']'
,@referenced_columns = @referenced_columns + N', [' + c.name + N']'
FROM sys.foreign_key_columns AS a
INNER JOIN sys.columns AS b ON b.object_id = a.parent_object_id AND b.column_id = a.parent_column_id
INNER JOIN sys.columns AS c ON c.object_id = a.referenced_object_id AND c.column_id = a.referenced_column_id
WHERE a.constraint_object_id = @object_id;
SELECT @return = N'FOREIGN KEY(' + STUFF(@parent_columns, 1, 2, N'') + N') REFERENCES [' + a.name + N'].[' + b.name + N'](' + STUFF(@referenced_columns, 1, 2, N'') + N')'
FROM sys.schemas AS a
INNER JOIN sys.tables AS b ON a.schema_id = b.schema_id
WHERE b.object_id = @referenced_object_id;
RETURN @return;
END;
GO
IF OBJECT_ID('dbo.F_GetIndexColumns', 'FN') IS NOT NULL
DROP FUNCTION dbo.F_GetIndexColumns;
GO
CREATE FUNCTION dbo.F_GetIndexColumns
(
@object_id int
,@index_id int
)
RETURNS varchar(4000)
AS
BEGIN
DECLARE @Return nvarchar(4000);
SET @Return = '';
SELECT @Return = @Return + N', [' + b.name + N'] ' + CASE WHEN a.is_descending_key = 0 THEN N'ASC' ELSE N'DESC' END
FROM sys.index_columns AS a
INNER JOIN sys.columns AS b ON a.object_id = b.object_id AND a.column_id = b.column_id
WHERE a.object_id = @object_id
AND a.index_id = @index_id
ORDER BY a.index_column_id;
RETURN STUFF(@Return, 1, 2, '');
END;
GO
IF OBJECT_ID('tempdb.dbo.#QueryList', 'U') IS NOT NULL
DROP TABLE #QueryList;
GO
CREATE TABLE #QueryList
(
executeDropOrder int
,dropQuery nvarchar(4000)
,executeCreateOrder int
,createQuery nvarchar(4000)
);
GO
DECLARE @collation_name varchar(4000);
--Edit Here
SET @collation_name = N'Korean_Wansung_CI_AS';
INSERT INTO #QueryList(executeDropOrder, dropQuery, executeCreateOrder, createQuery)
SELECT
1 AS executeDropOrder
,N'ALTER TABLE [' + d.name + N'].[' + c.name + N'] DROP CONSTRAINT [' + a.name + N'];' AS DropDF
,4 AS executeDropOrder
,N'ALTER TABLE [' + d.name + N'].[' + c.name + N'] ADD CONSTRAINT [' + a.name + N'] DEFAULT' + a.definition + N' FOR [' + b.name + N'];' AS CreateDF
FROM sys.default_constraints AS a
INNER JOIN sys.columns AS b ON b.object_id = a.parent_object_id AND b.column_id = a.parent_column_id
INNER JOIN sys.tables AS c ON b.object_id = c.object_id
INNER JOIN sys.schemas AS d ON c.schema_id = d.schema_id;
INSERT INTO #QueryList(executeDropOrder, dropQuery, executeCreateOrder, createQuery)
SELECT
2 AS executeDropOrder
,N'ALTER TABLE [' + d.name + N'].[' + c.name + N'] DROP CONSTRAINT [' + a.name + N'];' AS DropCK
,3 AS executeDropOrder
,N'ALTER TABLE [' + d.name + N'].[' + c.name + N'] ADD CONSTRAINT [' + a.name + N'] CHECK' + a.definition + CASE WHEN a.is_not_for_replication = 1 THEN ' NOT FOR REPLICATION' ELSE '' END + N';' AS CreateCK
FROM sys.check_constraints AS a
INNER JOIN sys.columns AS b ON b.object_id = a.parent_object_id AND b.column_id = a.parent_column_id
INNER JOIN sys.tables AS c ON b.object_id = c.object_id
INNER JOIN sys.schemas AS d ON c.schema_id = d.schema_id;
INSERT INTO #QueryList(executeDropOrder, dropQuery, executeCreateOrder, createQuery)
SELECT
3 AS executeDropOrder
,N'ALTER TABLE [' + a.name + N'].[' + b.name + N'] DROP CONSTRAINT [' + c.name + N'];' AS DropFK
,2 AS executeDropOrder
,N'ALTER TABLE [' + a.name + N'].[' + b.name + N'] ADD CONSTRAINT [' + c.name + N'] ' + dbo.F_GetForeignKeyColumns(c.object_id) + CASE WHEN c.delete_referential_action_desc = 'NO_ACTION' THEN '' ELSE ' ON DELETE ' + c.delete_referential_action_desc END + CASE WHEN c.update_referential_action_desc = 'NO_ACTION' THEN '' ELSE ' ON UPDATE ' + c.update_referential_action_desc END + CASE WHEN c.is_not_for_replication = 1 THEN ' NOT FOR REPLICATION' ELSE '' END + N';' COLLATE Latin1_General_CI_AS_KS_WS AS CreateFK
FROM sys.schemas AS a
INNER JOIN sys.tables AS b ON a.schema_id = b.schema_id
INNER JOIN sys.foreign_keys AS c ON b.object_id = c.parent_object_id
WHERE EXISTS(SELECT TOP 1 '' FROM sys.foreign_key_columns AS d INNER JOIN sys.columns AS e ON d.parent_object_id = e.object_id AND d.parent_column_id = e.column_id WHERE e.collation_name <> @collation_name)
AND EXISTS(SELECT TOP 1 '' FROM sys.foreign_key_columns AS d INNER JOIN sys.columns AS e ON d.referenced_object_id = e.object_id AND d.referenced_column_id = e.column_id WHERE e.collation_name <> @collation_name);
INSERT INTO #QueryList(executeDropOrder, dropQuery, executeCreateOrder, createQuery)
SELECT DISTINCT
4 AS executeDropOrder
,CASE
WHEN d.is_primary_key = 0 AND d.is_unique_constraint = 0 THEN N'DROP INDEX [' + d.name + N'] ON [' + f.name + N'].[' + a.name + N'];'
ELSE N'ALTER TABLE [' + f.name + N'].[' + a.name + N'] DROP CONSTRAINT [' + d.name + N'];'
END AS DropIndex
,1 AS executeDropOrder
,CASE
WHEN d.is_primary_key = 0 AND d.is_unique_constraint = 0 THEN N'CREATE ' + CASE WHEN d.is_unique = 1 THEN N'UNIQUE ' ELSE '' END + d.type_desc + ' INDEX [' + d.name + N'] ON [' + f.name + N'].[' + a.name + N'](' + dbo.F_GetIndexColumns(d.object_id, d.index_id) + N')' + CASE WHEN d.fill_factor > 0 THEN N' WITH FILLFACTOR = ' + CONVERT(varchar, d.fill_factor) ELSE N'' END + N' ON [' + e.name + N'];'
ELSE N'ALTER TABLE [' + f.name + N'].[' + a.name + N'] ADD CONSTRAINT [' + d.name + N'] ' + CASE WHEN d.is_primary_key = 1 THEN N'PRIMARY KEY ' WHEN d.is_unique_constraint = 1 THEN N'UNIQUE ' END + d.type_desc + N'(' + dbo.F_GetIndexColumns(d.object_id, d.index_id) + N')' + CASE WHEN d.fill_factor > 0 THEN N' WITH FILLFACTOR = ' + CONVERT(varchar, d.fill_factor) ELSE N'' END + N' ON [' + e.name + N'];'
END COLLATE Latin1_General_CI_AS_KS_WS AS CreateIndex
FROM sys.tables AS a
INNER JOIN sys.columns AS b ON a.object_id = b.object_id
INNER JOIN sys.index_columns AS c ON b.column_id = c.column_id AND b.object_id = c.object_id
INNER JOIN sys.indexes AS d ON c.object_id = d.object_id AND c.index_id = d.index_id
INNER JOIN sys.data_spaces AS e ON d.data_space_id = e.data_space_id
INNER JOIN sys.schemas AS f ON a.schema_id = f.schema_id;
INSERT INTO #AlterCollateQuery(Query)
SELECT dropQuery
FROM #QueryList
ORDER BY executeDropOrder;
INSERT INTO #AlterCollateQuery(Query)
SELECT N'ALTER TABLE [' + a.name + N'].[' + b.name + N'] ALTER COLUMN [' + c.name + N'] ' + d.name + N'(' + CASE WHEN c.max_length < 1 OR c.max_length > 4000 THEN 'MAX' ELSE CONVERT(varchar, c.max_length) END + N') COLLATE ' + @collation_name + CASE WHEN c.is_nullable = 0 THEN N' NOT NULL' ELSE N' NULL' END + N';'
FROM sys.schemas AS a
INNER JOIN sys.tables AS b ON a.schema_id = b.schema_id
INNER JOIN sys.columns AS c ON c.object_id = b.object_id
INNER JOIN sys.types AS d ON d.user_type_id = c.user_type_id
WHERE c.collation_name <> @collation_name;
INSERT INTO #AlterCollateQuery(Query)
SELECT a.Query
FROM
(
SELECT N'ALTER DATABASE ' + DB_NAME() + N' SET SINGLE_USER WITH ROLLBACK IMMEDIATE;' AS Query
UNION ALL SELECT N'ALTER DATABASE ' + DB_NAME() + N' COLLATE ' + @collation_name + ';' AS Query
UNION ALL SELECT N'ALTER DATABASE ' + DB_NAME() + N' SET MULTI_USER;' AS Query
) AS a
WHERE EXISTS(SELECT TOP 1 '' FROM sys.databases WHERE name = DB_NAME() AND collation_name <> @collation_name);
INSERT INTO #AlterCollateQuery(Query)
SELECT createQuery
FROM #QueryList
ORDER BY executeCreateOrder;
GO
IF OBJECT_ID('dbo.F_GetForeignKeyColumns', 'FN') IS NOT NULL
DROP FUNCTION dbo.F_GetForeignKeyColumns;
GO
IF OBJECT_ID('dbo.F_GetIndexColumns', 'FN') IS NOT NULL
DROP FUNCTION dbo.F_GetIndexColumns;
GO
IF OBJECT_ID('tempdb.dbo.#QueryList', 'U') IS NOT NULL
DROP TABLE #QueryList;
GO
DECLARE @Query nvarchar(4000);
DECLARE Collate_Query CURSOR FOR
SELECT a.Query
FROM #AlterCollateQuery AS a WITH(NOLOCK)
ORDER BY a.ExecuteOrder;
OPEN Collate_Query;
FETCH Collate_Query INTO @Query;
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @Query;
EXECUTE sp_executesql @Query;
FETCH Collate_Query INTO @Query;
END;
CLOSE Collate_Query;
DEALLOCATE Collate_Query;
GO
IF OBJECT_ID('tempdb.dbo.#AlterCollateQuery', 'U') IS NOT NULL
DROP TABLE #AlterCollateQuery;
GO