如何转换sql_variant以便将其视为确定性



我正试图在SYSTEM_VERSIONINGdbo.Users中创建一个持久化计算列,如下所示:

ALTER TABLE dbo.Users 
ADD SessionId AS usr.GetSession() PERSISTED 
CONSTRAINT FK_dboUsers_IdSession 
FOREIGN KEY REFERENCES dbo.Sessions(IdSession)

其中usr.GetSession()只是检索作为BIGINT存储在SESSION_CONTEXT('IdSession')中的值,并将其再次转换为BIGINT

CREATE OR ALTER FUNCTION usr.GetSession()
RETURNS BIGINT WITH SCHEMABINDING
AS
BEGIN
RETURN CONVERT(BIGINT, SESSION_CONTEXT(N'IdSession'))
END

但是得到以下错误:

表"Users"中的计算列"SessionId"无法持久化,因为该列具有不确定性。

这显然是因为:

SELECT OBJECTPROPERTY(OBJECT_ID('usr.GetSession'), 'IsDeterministic') AS IsDeterministic;

正在返回0

一点点搜索发现了关于确定性和非确定性函数

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

  • 源类型为sql_variant
  • 目标类型是sql_variant,其源类型是不确定的

因此,我理解没有办法使用用户定义的标量函数持久化我的计算列,因为sql_variant不能作为确定性值处理。

或者可以四处走走来解决我的问题?或者其他解决方案?知道吗?

不,没有解决方法除非对sql_variant进行转换(甚至是隐式转换(,否则无法对其执行任何操作,正如您所提到的,这是不确定的。


尽管如此,你似乎还是走错了路。

计算列在这里是错误的,因为在这种情况下,它会在每次读取时发生变化,而您似乎希望它在每次插入行时发生变化。

相反,您需要DEFAULT

ALTER TABLE dbo.Users 
ADD SessionId bigint DEFAULT (usr.GetSession())

最新更新