在SQL Server 2005中持久化计算的日期时间列

6

我在一张表中有一个XML列,我想将该XML中的某个值“提升”为计算列,并对其进行索引以实现更快的搜索。我有一个函数,可以接收XML信息并输出感兴趣的元素,就像这样:

CREATE FUNCTION [dbo].[fComputeValue] (@data XML)
RETURNS datetime
WITH SCHEMABINDING
AS
BEGIN
  RETURN @data.value('(/Metadata/Value[@Key="StartDate"])[1]', 'datetime')
END 

然而,当我尝试创建计算列时:
ALTER TABLE dbo.CustomMetadataTable ADD [StartDate] AS ([dbo].[fComputeValue]([CustomMetadataColumn])) PERSISTED

我遇到了以下错误:
Msg 4936,级别 16,状态 1,第 2 行 在表“CustomMetadataTable”中的计算列“StartDate”无法持久化,因为该列是非确定性的。
如果我:
  • 使用 varchar、int、double 值(即除 datetime 之外的其他值)
  • 移除 PERSISTED 关键字(但是这样就无法在该列上创建索引)
那么它可以工作。我还应该提到 datetime 值采用 XSD datetime 格式。有什么想法吗?谢谢。
1个回答

8

你觉得怎样:

CREATE FUNCTION [dbo].[fComputeValue] (@data XML)
RETURNS varchar(50)
WITH SCHEMABINDING
AS
BEGIN
  RETURN @data.value('(/Metadata/Value[@Key="StartDate"])[1]', 'varchar(50)')
END

并且:

ALTER TABLE dbo.CustomMetadataTable ADD [StartDate] AS (convert(datetime,([dbo].[fComputeValue]([CustomMetadataColumn]), 127)) PERSISTED

或者:

return convert(datetime, @data.value('(/Metadata/Value[@Key="StartDate"])[1]', 'varchar(50)'), 127)

来自在线书籍:

CONVERT是确定性的,除非存在以下条件之一:

源类型为sql_variant。

目标类型为sql_variant且其源类型为不确定性的。

源或目标类型为datetime或smalldatetime,另一个源或目标类型为字符字符串,并指定了不确定性样式。为了确定性,样式参数必须是一个常量。此外,小于或等于100的样式是不确定性的,除了样式20和21。大于100的样式是确定性的,除了样式106、107、109和113。

如果您使用样式 127,这可能会有所帮助。


谢谢!我也遇到了同样的问题。不知道为什么127可以工作而其他数字不行? - harpo
这就是原因:“大于100的样式是确定性的,除了106、107、109和113号样式。” - Bogdan Maxim
不必更改 ALTER TABLE 语句,您也可以更改 fComputeValue 函数定义:如果在函数的主体/实现中使用样式 127 调用 CONVERT,则该函数可以返回 OP 所需的 datetime。 - ChrisW
你可以在CONVERT页面找到关于哪些转换样式是确定的信息。 - Sam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接