问题描述
我有一张下表,其中记录应基于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。