HASHBYTES的独特约束挑战

问题描述

我有一张下表,其中记录应基于4列是唯一的。

我使用HASHBYTES添加了HashCol。现在这是一条错误消息,说 <BackendListener guiclass="BackendListenerGui" testclass="BackendListener" testname="Some Listener" enabled="true"> <elementProp name="arguments" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" enabled="true"> <collectionProp name="Arguments.arguments"/> </elementProp> <stringProp name="classname">com.k.jmeter.someBackendListener</stringProp> </BackendListener>

在这种情况下如何确保统一性?

Column 'HashCol' in table 'RCM_EM_Benchmarks' cannot be used in an index or statistics or as a partition key because it is non-deterministic.

解决方法

使用convert函数的style参数应使其具有确定性。

例如:

代替:

HashCol AS HASHBYTES('SHA1',[Procedure_Code] + [Benchmark]+ [Practice]+ CONVERT(VARCHAR(25),[Month_Start_Date]) )

使用此代码,它使用101作为样式参数:

 HashCol AS HASHBYTES('SHA1',[Procedure_Code] + [Benchmark]+ [Practice] + CONVERT(VARCHAR(25),[Month_Start_Date],101 ) )
,

这对我有用:

use tempdb;
drop table if exists dbo.myTable;
CREATE TABLE [dbo].[MyTable](
    [RecordID] [int] IDENTITY(1,1) NOT NULL,[Procedure_Code] [varchar](10) NULL,[Procedure_Percentage] [decimal](6,2) NULL,[Claim_Count] [int] NULL,[Benchmark] [varchar](40) NULL,[Practice] [varchar](40) NULL,[Month_Start_Date] [date] NULL,[Procedure_Type] [varchar](40) NULL,[CreatedOnDate] [date] NULL,HashCol AS HASHBYTES('SHA1',[Procedure_Code] + [Benchmark] + [Practice] + convert(char(10),126))
) ON [PRIMARY]
GO

ALTER  TABLE  [MyTable] ADD CONSTRAINT hashCol_Unique UNIQUE (HashCol)
GO

谈到原因,convert()在某些情况下(包括默认样式)是不确定的。您必须选择在the documentation中未被标记为不确定性的样式。具有讽刺意味的是,我尝试了样式23(该样式仅将日期返回为yyyy-mm-dd,并且未标记为不确定性),但这也是不可行的。上面链接的同一文档中有很多词说,低于100的样式是不确定的,因此我给了我个人最喜欢的126个尝试,它奏效了。还要注意,我将数据类型更改为char(10),因为将日期转换为该样式将始终为10个字节。

尽管由于任何原因hashbytes()被列为返回“ varbinary(最大8000字节)”,这仍然会发出警告。但是,在文档中还提供了不同哈希算法的实际输出长度。您可以显式地将hashbytes()调用的结果强制转换为该长度,以避免发出警告或只是忽略它,因为我认为实际上,它永远不会超过算法的规定长度。

我要说的最后一件事是SHA1已过时,已经存在了一段时间。对于新开发,您应该使用SHA2变体之一。由于您的问题被标记为SQL 2016,因此您可以使用SHA2_256和SHA2_512。