使用SQL Server 2016时,我遇到了一些问题。
这是我的用例,给我造成问题...
create table dbo.Example (
Id int identity (1, 1) not null,
[Name] nvarchar(100) not null,
Email nvarchar(255) not null,
DOB datetime2(7) not null,
RowHash as convert(nvarchar(66), hashbytes('SHA1', coalesce(
convert(nvarchar(max), [Name]),
convert(nvarchar(max), Email),
convert(nvarchar(max), DOB)
))) persisted
constraint [PK_Example] primary key clustered (Id asc)
);
drop table dbo.Example;
我收到的消息是:
消息4936,第16级,状态1,第1行 表'Example'中的计算列'RowHash'无法保留,因为该列不确定。
当我将列设置为不持久时,数据类型正确解释为nvarchar(66),但是我希望它持久。问题似乎与datetime2列有关,但是我在表上混合了数据类型。
所以目标是使用一个持久的hashbytes列来保存表中所有值的哈希值。
有什么想法吗?
谢谢!
答案 0 :(得分:1)
为什么用coalesce()
而不是concat()
?
示例
create table dbo.Example (
Id int identity (1, 1) not null,
[Name] nvarchar(100) not null,
Email nvarchar(255) not null,
DOB datetime2(7) not null,
RowHash as convert(nvarchar(66), hashbytes('SHA1', concat(
[Name],
Email,
DOB
))) persisted
constraint [PK_Example] primary key clustered (Id asc)
);
Select * from [dbo].[Example]
--drop table dbo.Example;
结果
答案 1 :(得分:1)
您可以通过指定日期转换格式来解决此问题:
create table dbo.Example (
Id int identity (1, 1) not null,
[Name] nvarchar(100) not null,
Email nvarchar(255) not null,
DOB date not null, -- I figure date is good enough
RowHash as convert(nvarchar(66), hashbytes('SHA1', concat(
convert(nvarchar(max), [Name]),
convert(nvarchar(max), Email),
convert(nvarchar(max), DOB, 121)
))) persisted
constraint [PK_Example] primary key clustered (Id asc)
);
问题在于,默认的日期到字符串的转换取决于系统参数,因此不确定。对于持久化列,所有组件都必须是确定性的。
我想说文档很好地平衡了这一奇异之处。不完全的。您可以从此documentation中获得想法。请原谅-它也适用于date
,datetime2
和其他数据类型。
答案 2 :(得分:0)
这是上面两个答案的总和。非常感谢您的帮助。
create table dbo.Example (
Id int identity (1, 1) not null,
[Name] nvarchar(100) not null,
Email nvarchar(255) not null,
DOB datetime2(7) null,
RowHash as convert(nvarchar(66), hashbytes('SHA1', concat(
convert(nvarchar(max), [Name]),
convert(nvarchar(max), Email),
convert(nvarchar(max), DOB, 121)
))) persisted
constraint [PK_Example] primary key clustered (Id asc)
);
drop table dbo.Example;