使用 union 和 tempdb 进行整理

Collation with union and tempdb

我在 tempdb 中有临时 table,在数据库中有 table。当我用这个 2 table 的并集构造查询时。有一个错误:

Cannot resolve the collation conflict between "Cyrillic_General_CI_AI" and "Cyrillic_General_CI_AS" in the UNION operation.

drop table [sysdb].[##temp table];
create table [sysdb].[##temp table](a varchar);
insert into [sysdb].[##temp table] (a) values ('a'),('b');


select grade_name from [mybase].[DDS].[testtable]
union
select * from [sysdb].[##temp table];

我已经使用此查询测试了数据库中的归类参数:

SELECT DATABASEPROPERTYEX('mybase', 'Collation') as collation_dwh,DATABASEPROPERTYEX('tempdb', 'Collation') as collation_tempdb

结果是数据库的排序规则是一样的:

collation_dwh                   | collation_tempdb

Cyrillic_General_CI_AI    | Cyrillic_General_CI_AI

如何解决这个问题?

如果您在 union 中明确设置排序规则,应该没问题:

select grade_name collate Cyrillic_General_CI_AI from [mybase].[DDS].[testtable]
union
select a collate Cyrillic_General_CI_AI from [sysdb].[##temp table];

请注意,列的排序规则可以不同于数据库。

Sql 服务器中的排序规则:

Collation is set of rules that determine how data is sorted and compared. Currently sql has four level of collation (Server,Database,Table & Column).

归类冲突原因:

You faced mismatches in levels of collation between the the tables.

修复:

As per the Microsoft changing the server level collation is not a easy fix. Source: Before that you need to address all non default collation on columns for all tables in SQL Server

DECLARE @DatabaseCollation VARCHAR(100)

SELECT 
    @DatabaseCollation = collation_name 
FROM 
    sys.databases
WHERE 
    database_id = DB_ID()

SELECT 
    @DatabaseCollation 'Default database collation'

SELECT 
    t.Name 'Table Name',
    c.name 'Col Name',
    ty.name 'Type Name',
    c.max_length,
    c.collation_name,
    c.is_nullable
FROM 
    sys.columns c 
INNER JOIN 
    sys.tables t ON c.object_id = t.object_id
INNER JOIN 
    sys.types ty ON c.system_type_id = ty.system_type_id    
WHERE 
    t.is_ms_shipped = 0
    AND 
    c.collation_name <> @DatabaseCollation
  • Re-Build SQL服务器最好的解决方案之一。

For temporary fix use below query.

SELECT grade_name COLLATE DATABASE_DEFAULT from [mybase].[DDS].[testtable]
UNION
SELECT a COLLATE DATABASE_DEFAULT from [sysdb].[##temp table];