我正试图在SYSTEM_VERSIONING
表dbo.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())