【问题标题】:Why is a cast from DATE to VARCHAR non-deterministic?为什么从 DATE 到 VARCHAR 的转换是不确定的?
【发布时间】:2016-10-07 16:22:02
【问题描述】:

在尝试将计算列添加到 SQL Server 表时,我发现将具有 DATE 类型的列直接转换为 VARCHAR 被认为是不确定的。但是,如果我取出日期的各个部分并单独投射它们,那么一切都很好。我想不出一个合理的解释来解释为什么直接从 DATE 到 VARCHAR 的转换是不确定的。有人解释一下吗?

例如

create table [dbo].[junk_CCtest]
(
    PatientId bigint identity not null,
    EmployerId varchar(6) default 'F*Corp',
    EffDate date default getdate()
)
go
-- This works fine.
alter table dbo.junk_CCtest
    add Checksum1 as (hashbytes('sha2_256', EmployerId + '/' + cast(PatientId as varchar(10)) + cast(year(EffDate) as varchar(4)) + cast(month(EffDate) as varchar(2))  + cast(day(EffDate) as varchar(2)))) persisted;
go
-- This results in: "Computed column 'Checksum3' in table 'junk_CCtest' cannot be persisted because the column is non-deterministic."
alter table dbo.junk_CCtest
    add Checksum3 as (hashbytes('sha2_256', EmployerId + '/' + cast(PatientId as varchar(10)) + cast(EffDate as varchar(10)))) persisted;
go

谢谢,

伊恩

【问题讨论】:

  • 如果您将 3 位数的第二个参数添加到 convert(),它仍然是不确定的吗?我认为这在 BOL 中有明确的解释。

标签: sql-server tsql


【解决方案1】:

日期的字符串 (varchar) 表示取决于您的“区域设置”设置(例如,英国的日期通常与美国的日期不同)。

在上面的示例中,您的第一个 CAST() 明确指定了 varchar 的格式,但第二个 CAST() 强制数据库检查其区域设置以确定如何格式化 varchar 结果。

转换依赖于 CAST() 函数外部的东西这一简单事实使其具有不确定性。

换句话说,您使用一种语言环境设置运行 CAST(),更改语言环境,然后再次运行 SAME CAST(),您会得到不同的结果。这是非确定性行为的定义。

【讨论】:

  • 当然,你是对的。我应该考虑到这一点。不过,这让我意识到,有一个更好的选择,那就是使用 CONVERT 而不是 CAST。此解决方案有效,并且比单独投射日期的每个部分要短。 - 这工作正常。 alter table dbo.junk_CCtest add Checksum3 as (hashbytes('sha2_256', EmployerId + '/' + cast(PatientId as varchar(10)) + convert(varchar(8), EffDate, 112))) 持久化;
  • 只是为了澄清最后一条评论,它与 CONVERT 一起正常工作的原因是您将 112 指定为样式参数,这使其具有确定性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-23
  • 2021-01-29
  • 1970-01-01
  • 1970-01-01
  • 2020-03-11
相关资源
最近更新 更多