2009-05-11 3 views
4

데이터베이스에 데이터 정렬 문제가 있으며 직접 솔루션을 개발했습니다.더 나은 방법으로 데이터 정렬 충돌을 해결하려면 어떻게합니까?

솔루션 :

DECLARE @new_collation varchar(128), 
    @conflict_collation varchar(128), 
    @cmd_holder varchar(2000), 
    @cmd_complete varchar(2000), 
    @schema varchar(128), 
    @table_name varchar(128), 
    @constraints_name varchar(128), 
    @column_name varchar(128), 
    @definition varchar(256), 
    @data_type varchar(128), 
    @type varchar(5), 
    @length varchar(4), 
    @nullability varchar(8), 
    @db_name varchar(10) 

SET @new_collation = 'SQL_Latin1_General_CP1_CI_AS' 
SET @conflict_collation = 'French_CI_AS' 

CREATE TABLE #LIST_CONSTRAINT(
    constraints_name VARCHAR(128), 
    table_name VARCHAR(128), 
    definition VARCHAR(256), 
    type VARCHAR(10)) 

INSERT INTO #LIST_CONSTRAINT 
SELECT c.name AS constraints_name, o.name AS table_name, definition, 'CH' AS type 
FROM sys.check_constraints c 
INNER JOIN sysobjects o ON id = parent_object_id 

INSERT INTO #LIST_CONSTRAINT 
SELECT i.name AS index_name, o.name AS table_name, c.name AS field_name, 'UQ' AS type 
FROM sys.indexes i 
INNER JOIN sys.index_columns ic 
    ON i.object_id = ic.object_id and i.index_id = ic.index_id 
INNER JOIN sys.columns c 
    ON ic.object_id = c.object_id and ic.column_id = c.column_id 
INNER JOIN sys.objects o 
    ON i.object_id = o.object_id 
WHERE is_unique_constraint = 1 

SET @cmd_holder = 'ALTER TABLE $table_name DROP CONSTRAINT $constraints_name' 

DECLARE column_cursor 
CURSOR FOR SELECT constraints_name, table_name FROM #LIST_CONSTRAINT GROUP BY constraints_name, table_name 
OPEN column_cursor 
FETCH NEXT FROM column_cursor INTO @constraints_name, @table_name 

WHILE @@Fetch_Status = 0 
    BEGIN 
    SELECT @cmd_complete = @cmd_holder, 
      @cmd_complete = Replace(@cmd_complete, '$table_name', '[' + @table_name +']'), 
      @cmd_complete = Replace(@cmd_complete, '$constraints_name', @constraints_name) 

    --PRINT @cmd_complete 
    EXEC(@cmd_complete) 
    FETCH NEXT FROM column_cursor INTO @constraints_name, @table_name 
    END 
CLOSE column_cursor 
DEALLOCATE column_cursor 

SELECT @db_name = DB_NAME() 
EXEC('ALTER DATABASE ' + @db_name + ' COLLATE ' + @new_collation) 

SET @cmd_holder = 'ALTER TABLE $schema.$table_name ALTER COLUMN $column_name $data_type($length) COLLATE $new_collation $nullability' 

DECLARE column_cursor CURSOR 
    FOR SELECT table_schema, 
       table_name, 
       column_name, 
       data_type, 
       CASE WHEN character_maximum_length = -1 THEN 'max' 
        ELSE Convert(varchar(4), character_maximum_length) 
       END As length, 
       CASE WHEN is_nullable = 'YES' THEN 'NULL' 
        ELSE 'NOT NULL' 
       END As nullability 
     FROM information_schema.columns 
     INNER JOIN sysobjects ON name = table_name 
     WHERE collation_name = @conflict_collation AND xtype = 'U' 
     AND table_name NOT IN ('dtproperties', 'Exotics', 'ContractAccountsBalance', 'TechnicalParameters', 'SavingProducts', 'GeneralParameters') 
OPEN column_cursor 

FETCH NEXT FROM column_cursor INTO @schema, @table_name, @column_name, @data_type, @length, @nullability 

WHILE @@Fetch_Status = 0 
    BEGIN 
    SELECT @cmd_complete = @cmd_holder, 
      @cmd_complete = Replace(@cmd_complete, '$schema', @schema), 
      @cmd_complete = Replace(@cmd_complete, '$table_name', '[' + @table_name +']'), 
      @cmd_complete = Replace(@cmd_complete, '$column_name', '[' + @column_name +']'), 
      @cmd_complete = Replace(@cmd_complete, '$data_type', @data_type), 
      @cmd_complete = Replace(@cmd_complete, '$length', @length), 
      @cmd_complete = Replace(@cmd_complete, '$new_collation', @new_collation), 
      @cmd_complete = Replace(@cmd_complete, '$nullability', @nullability), 
      @cmd_complete = Replace(@cmd_complete, 'text(*)', 'text') 

    --PRINT @cmd_complete 
    EXEC(@cmd_complete) 

    FETCH NEXT FROM column_cursor INTO @schema, @table_name, @column_name, @data_type, @length, @nullability 
    END 
CLOSE column_cursor 
DEALLOCATE column_cursor 

DECLARE @name_constraints VARCHAR(128) 

DECLARE column_cursor 
CURSOR FOR SELECT constraints_name, table_name, definition, [type] FROM #LIST_CONSTRAINT 
OPEN column_cursor 
FETCH NEXT FROM column_cursor INTO @constraints_name, @table_name, @definition, @type 

WHILE @@Fetch_Status = 0 
    BEGIN 
    IF @type = 'CH' 
    SET @cmd_holder = 'ALTER TABLE $table_name WITH NOCHECK ADD CONSTRAINT $constraints_name CHECK NOT FOR REPLICATION $definition ALTER TABLE $table_name CHECK CONSTRAINT $constraints_name' 

    IF @type = 'UQ' 
    BEGIN 
     SET @cmd_holder = 'ALTER TABLE $table_name ADD CONSTRAINT $constraints_name UNIQUE NONCLUSTERED ($definition) WITH(STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)' 

     SET @definition = ''; 

     SELECT @definition = @definition + definition + ', ' 
     FROM #LIST_CONSTRAINT 
     WHERE constraints_name = @constraints_name 

     SELECT @definition = SUBSTRING(@definition, 1, LEN(@definition) - 1)   
    END 


    SELECT @cmd_complete = @cmd_holder, 
      @cmd_complete = Replace(@cmd_complete, '$table_name', '[' + @table_name +']'), 
      @cmd_complete = Replace(@cmd_complete, '$constraints_name', @constraints_name), 
      @cmd_complete = Replace(@cmd_complete, '$definition', @definition) 

    --PRINT @cmd_complete 
    IF (@name_constraints <> @constraints_name) 
     EXEC(@cmd_complete) 

    SET @name_constraints = @constraints_name 

    FETCH NEXT FROM column_cursor INTO @constraints_name, @table_name, @definition, @type 
    END 
CLOSE column_cursor 
DEALLOCATE column_cursor 

DROP TABLE #LIST_CONSTRAINT 

아무도 다른 해결책이 있습니까?

아무도 내 코드를 최적화하기 위해 조언을 제공 할 수 있습니까?

답변

10

tempdb에 데이터베이스와 다른 기본 colation이있는 곳을 보았습니다. "COLLATE DATABASE_DEFAULT"를 내 비교에 추가해야했습니다.

Create table #tmp 
(
     mailbox varchar(50) not null 
) 
. . . 
Select t.mailbox, count(*) 
from #tmp t inner join processed_email e 
on t.mailbox = e.mailbox 

Select t.mailbox, count(*) 
from #tmp t inner join processed_email e 
on t.mailbox COLLATE DATABASE_DEFAULT = e.mailbox COLLATE DATABASE_DEFAULT 
+0

나는이 방법을 여러 번 사용해 왔습니다. 서로 다른 데이터 정렬 유형이 진짜 고통입니다. – inferis

0

진 걱정이 많은 사람의 솔루션은 서로 다른 데이터 정렬 코드를 실행하는 데 유용하게된다. 예를 들어 임시 테이블과 임시 변수는 tempdb 데이터 정렬을 사용합니다.

데이터 정렬을 변경하기 위해 MS는 KB "How to transfer a database from one collation to another collation in SQL Server"을 결합합니다. 그것은 여전히 ​​가능하지 않을 수도 있지만 DTS를 사용하여 언급하고 있습니다. 업데이트 된 기술 자료 문서를 찾을 수 없습니다.