排序规则引起的冲突问题

最近在工作中碰到一例因排序规则而导致的冲突问题,运行环境是SQL 2008,具体代码如下:

DECLARE @URL VARCHAR(500),
	@startdate DATETIME,
	@enddate DATETIME,
	@Identifier VARCHAR(20);	

SELECT @URL = '/articlenet/article.aspx',      
       @startdate = '2010-02-01',	
       @enddate = '2010-02-28',
       @Identifier = 'id';

SELECT CAST(au.PopulateDate AS date) AS DateViewed
		   ,qs.Value
		   ,COUNT(1) AS PageViews
		   ,COUNT(
		      DISTINCT CASE WHEN au.UserId = 6264375 THEN au.FPID 
		                      ELSE du.UserGUID  END
		         ) AS DistinctUsers
FROM Dim_URL u (NOLOCK)
	JOIN dbo.Agg_User_Archive au  (NOLOCK) 
		ON u.URLKey  = au.URLKey 
	JOIN Dim_QueryString qs  (NOLOCK) 
		ON au.AggUserId  = qs.AggUserId 
	JOIN dbo.Dim_UserId du (NOLOCK) 
		ON du.UserKey  = au.UserId 
WHERE URL  = @URL
	AND au.PopulateDate  > @startdate
	AND au.PopulateDate  < @enddate
	AND qs.Identifier  = @Identifier
GROUP BY CAST(au.PopulateDate AS DATE), Value
ORDER BY DateViewed DESC, Value;

--Msg 457, Level 16, State 1, Line 11
--Implicit conversion of varchar value to varchar cannot be performed because the collation of the value is unresolved due to a collation conflict.
 /*该查询是一个已经编写好的查询语句,只是根据需要我们做出了适当的调整。即新增了一个JOIN表Dim_UserId,然后将CASE子句中THEN后  
 面跟的,原来为FPIDKey更换为FPID,ELSE后面的UserId更换为UserGUID。修改后的批处理中语法检查时并没有发现任何错误。执行时出现 
 上述错误提示。从错误的提示来分析是因为排序冲突所致,因此查看新增的两个字段是否使用了相同的排序规则。下面是查看语句: */  
SELECT o.name,o.object_id,c.name,c.column_id,c.collation_name 
FROM sys.columns c
	JOIN sys.objects o
		ON c.object_id = o.object_id 
WHERE o.object_id = OBJECT_ID('dbo.Dim_UserId')
    AND c.name = 'UserGUID'
UNION 
SELECT o.name,o.object_id,c.name,c.column_id,c.collation_name 
FROM sys.columns c
	JOIN sys.objects o
		ON c.object_id = o.object_id 
WHERE o.object_id = OBJECT_ID('dbo.Agg_User_Archive')
    AND c.name = 'FPID'
/*    
name               object_id      name     column_id   collation_name
------------------ ----------- ---------- ----------- ----------------------
Agg_User_Archive   1613248802   FPID       28          Latin1_General_CS_AI
Dim_UserId         1234819461  UserGUID    2           Latin1_General_BIN
*/    

--从查询结果中可以看出,原来是因为两个列使用的不同的排序规则,故在count运算时发生了错误。于是修改语句如下,问题解决。下面仅列出被修改过的语句。 
COUNT(DISTINCT CASE WHEN au.UserId = 6264375 THEN au.FPID COLLATE DATABASE_DEFAULT 
	            ELSE du.UserGUID  COLLATE DATABASE_DEFAULT END
	  ) AS DistinctUsers

以下列出Collate子句的语法:
COLLATE { <collation_name> | database_default }
<collation_name> :: =      { Windows_collation_name } | { SQL_collation_name }

几点注意事项:
一、排序规则可以在以下几个级别指定:
1.创建或更改数据库。
2.创建或更改表列。
3.投影表达式的排序规则。
二、COLLATE 子句只能应用于 char、varchar、text、nchar、nvarchar 和 ntext 数据类型。

其它关于排序规则问题请参照本人的其它文章:SQL server 排序规则(COLLATE)
更多参考:http://msdn.microsoft.com/zh-cn/library/ms184391.aspx

 

### 解决 Navicat 中主键冲突的方法 当遇到主键冲突的情况时,通常是因为尝试插入的数据违反了表定义中的唯一约束条件。为了有效处理这种情况,在数据库设计阶段应考虑数据的唯一性和完整性。 #### 方法一:修改插入逻辑以避免重复 可以采用 `MERGE INTO` 语句来实现更新已存在记录或仅在不存在相同主键的情况下插入新记录的功能[^3]: ```sql MERGE INTO target_table t USING source_table s ON (t.primary_key_column = s.primary_key_column) WHEN MATCHED THEN UPDATE SET column1 = s.column1, column2 = s.column2 -- 更新其他字段 WHEN NOT MATCHED THEN INSERT (primary_key_column, column1, column2) VALUES (s.primary_key_column, s.column1, s.column2); ``` 这种方法能够优雅地应对可能发生的主键冲突问题,并确保不会丢失任何重要信息。 #### 方法二:调整现有数据防止未来发生冲突 如果发现某些记录已经造成了主键冲突,则需要清理这些异常情况。可以通过查询找出具有重复主键值的所有行并决定保留哪一个作为最终版本;之后删除多余的副本或者修正其主键以便符合唯一性的要求。 #### 方法三:设置合适的字符集和校对规则 考虑到不同操作系统之间可能存在大小写的差异,选择适合应用程序需求的字符集以及对应的排序规则collation),比如使用 `_ci` 类型而非 `_cs` 来忽略大小写区别从而减少潜在冲突的可能性[^4]。 通过上述措施之一或多者组合应用,可以在很大程度上预防和解决由主键引起的错误提示。当然具体实施还需依据实际业务场景灵活变通。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清风智语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值