简化持久计算列的 T-SQL 用户函数

Streamlining T-SQL user function for persisted computed column

我正在尝试简化以下 T-SQL 用户函数,以便在我的 table 之一的持久计算列中使用。我知道我可以在其他方法中使用视图中的计算列,但是由于用户要求的各种原因,最好按此方式实现此列。

但是为了在计算机专栏中使用这个标量函数,我正在努力使其尽可能高效和流线。函数的某些部分带有以下 SELECT COUNT 语句

SELECT COUNT([JunctionID])
FROM dbo.ApplicationJunctionT
WHERE [AccountID] = @AccountID 
  AND [Outcome] IS NULL 
  AND [Change Account Status] IS NULL

我反复使用,我想知道是否有更好的方法来重组此功能以提高效率。我确实尝试过使用 CTE 来包装这个 select 语句,但不断地 运行 陷入语法问题并且已经放弃了那个想法。

ALTER FUNCTION [dbo].[fnAccountReadyByID_Test] 
    (@JunctID INT = Null,
     @AccountID VARCHAR(20) = NULL)
RETURNS VARCHAR(10)
AS
BEGIN
    DECLARE @FamilyAccountReady as varchar(10),
            @TotalFamily as INT;

    SET @TotalFamily = (SELECT COUNT([JunctionID])
                        FROM dbo.ApplicationJunctionT
                        WHERE [AccountID] = @AccountID 
                          AND [Outcome] IS NULL 
                          AND [Change Account Status] IS NULL)

    IF @TotalFamily = 1
        SET @FamilyAccountReady = (SELECT AccountStatus 
                                   FROM dbo.ApplicationJunctionT 
                                   WHERE JunctionID = @JunctID)
    ELSE
        SET @FamilyAccountReady = (CASE 
                                      WHEN (SELECT COUNT([JunctionID]) 
                                            FROM dbo.ApplicationJunctionT 
                                            WHERE [AccountID] = @AccountID 
                                              AND [Outcome] IS NULL 
                                              AND [Change Account Status] IS NULL 
                                              AND [AccountStatus] = '-') > 0 
                                         THEN '-'
                                      WHEN (SELECT COUNT([JunctionID]) 
                                            FROM dbo.ApplicationJunctionT 
                                            WHERE [AccountID] = @AccountID 
                                              AND [Outcome] IS NULL 
                                              AND [Change Account Status] IS NULL 
                                              AND [AccountStatus] = 'Frozen') > 0 
                                         THEN 'Frozen'
                                      WHEN (SELECT COUNT([JunctionID]) 
                                            FROM dbo.ApplicationJunctionT 
                                            WHERE [AccountID] = @AccountID 
                                              AND [Outcome] IS NULL 
                                              AND [Change Account Status] IS NULL 
                                              AND [AccountStatus] = 'Closed') > 0 
                                         THEN 'Closed'
                                      WHEN (SELECT COUNT([JunctionID]) 
                                            FROM dbo.ApplicationJunctionT 
                                            WHERE [AccountID] = @AccountID 
                                              AND [Outcome] IS NULL 
                                              AND [Change Account Status] IS NULL 
                                              AND [AccountStatus] = 'Tentative') > 0 
                                         THEN 'Tentative'
                                      ELSE 'GRANT'
                               END)

       -- Return the result of the function
       RETURN UPPER(@FamilyAccountReady)
END

另外,网上看了多篇文章也没找到电脑栏是怎么触发的。更新记录上的任何字段时是否触发?还是仅在更新变量字段时触发?

在这种情况下,我使用 AccountIDJunctionID 作为变量,它们都是不会改变的静态字段。我的计算列在这种情况下是否仍然有效?

尽管我不喜欢效率低下,但除非这里的专家社区可以提出一些改进建议,否则我可能不得不采用这种设计!

非常感谢您的协助!

如果您想使用 CTE,请尝试这样的操作:

WITH CTE AS (
    SELECT [AccountStatus]
    FROM dbo.ApplicationJunctionT 
    WHERE [AccountID] = @AccountID 
        AND [Outcome] IS NULL 
        AND [Change Account Status] IS NULL 
) 
SELECT @FamilyAccountReady = CASE 
    WHEN EXISTS (SELECT * FROM CTE WHERE [AccountStatus] = '-') THEN '-'
    WHEN EXISTS (SELECT * FROM CTE WHERE [AccountStatus] = 'Frozen') THEN 'Frozen'
    WHEN EXISTS (SELECT * FROM CTE WHERE [AccountStatus] = 'Closed') THEN 'Closed'
    WHEN EXISTS (SELECT * FROM CTE WHERE [AccountStatus] = 'Tentative') THEN 'Tentative'
    ELSE 'GRANT'
END

但是,我认为使用基于访问其他表的函数的计算列不是一个好主意:您会收到一条错误消息 "Computed column 'ColumnName' in table 'TableName' cannot be persisted because the column is non-deterministic."