我使用MS SQL已经有几年了,在以前的工作中从未遇到过这样的问题,但在我现在的工作中,我遇到了一个错误,我真的很想知道原因。
我做了一个存储过程,并在我的Delphi 5(是的,我知道)应用程序中使用一些参数调用它。这在两个数据库(不同时间的副本)上运行良好。但现在我在另一个数据库(同样是副本)上尝试,但它给了我以下错误:
Cannot resolve the collation conflict between "Latin1_General_CI_AS" and
"SQL_Latin1_General_CP1_CI_AS" in the equal to operation.
我创建了一个临时表,然后尝试插入一些数据。我甚至没有加入。有趣的是:当我删除整个WHERE子句时,它工作。2当我离开它时(尽管它只与一个表比较参数),它失败了。
create table #TOP (EDAID int, ParentID char(30), ChildID char(30),
Position int, OrgQty_modified_manually bit)
这将失败:
insert into #TOP
select EDAID, ParentID, ChildID, Position, OrgQty_modified_manually
from EDA_SOBOM
where OrderNr = @OrderNr
and Position = @Position
and LN = @LN
and DL = @DL
and rtrim(ChildID) = @CurrentPart
and rtrim(ParentID) = @ParentID
这是可行的:
insert into #TOP
select EDAID, ParentID, ChildID, Position, OrgQty_modified_manually
from EDA_SOBOM
过程参数声明如下:@部件ID字符(30)、@位置整数、@订单号字符(8)、@LN字符(2)、@DL字符(2)、@父ID字符(30)、@修改位输出
我在这里找到了一个解决方案:Cannot resolve the collation conflict between "SQL_Latin1_General_CP1_CI_AS" and "Latin1_General_CI_AS" in the equal to operation.
所以我在CREATE之后添加了以下代码:
ALTER TABLE #TOP
ALTER COLUMN ParentID
VARCHAR(30) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
ALTER TABLE #TOP
ALTER COLUMN ChildID
VARCHAR(30) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
这使得整个事情再次工作...但是我不明白为什么只带参数比较的WHERE子句会失败...参数也可以有排序规则吗?
DB具有排序规则SQL_Latin1_General_CP1_CI_AS。表EDA_SOBOM在char列上也具有排序规则SQL_Latin1_General_CP1_CI_AS。我通过以下查询发现了这一点:
SELECT col.name, col.collation_name
FROM sys.columns col
WHERE object_id = OBJECT_ID('EDA_SOBOM')
除了DB级和列级之外,还有其他地方可以设置排序规则吗?
我想知道发生了什么事...
3条答案
按热度按时间2vuwiymt1#
排序规则冲突出现在任何比较不同排序规则的字符串的运算符上,例如select中的equals。
TempDb采用服务器默认排序规则,而您的真实的Db可能有不同的排序规则,这导致使用DDL创建的任何临时表都有排序规则差异。
您可以在相等运算符之后添加“collate database_default”子句,这样就可以修复它。或者您可以使用以下命令创建临时表:
这将强制临时表列从您的数据库中获取数据类型(& collation)。
e0uiprwp2#
有一个服务器级别的排序规则设置作为所有系统数据库的默认值。有一个数据库级别的排序规则,正如你所说的。列和表达式可以有一个定义的排序规则。
当数据库与系统数据库(尤其是tempdb)具有不同的排序规则时,会出现许多问题。
我不想重复Peter Wishart的回答(我同意他的回答),我只想补充一点:在开发产品时,您应该决定您将允许什么级别的排序灵活性。为了避免问题,您必须围绕该选择设计代码。如果您不打算要求您的数据库对象与服务器排序一致,然后,您必须应用排序规则修饰符或控制在tempdb中创建表、使用系统表或进行比较时使用的排序规则。在大型产品中,这可能是大量代码。
在SQLServer中还有另一个排序规则经常被忽略。这是任何.Net SP或函数中使用的默认排序规则。该排序规则是基于SQLServer进程的windows用户配置文件定义的。在文档中通常不称为排序规则,它是windows区域设置的一部分。在注册表中称为LCID。
因此,即使数据库、sqlserver、表、列排序规则都匹配,如果在CLR存储过程代码中进行字符串比较,仍然可能会出现不匹配,除非编写代码来避免这种情况。
u91tlkcl3#
若要解决排序规则冲突,请在“=”运算符周围添加 “COLLATE DATABASE_DEFAULT” 关键字。