公式欄位:循環參照

欄位公式可以讀取關聯記錄的欄位,即使該記錄屬於同一張表。但它不能讀取該記錄上的自身欄位:公式編輯器會拒絕它,並顯示訊息「Circular reference」。

範例

表 Groups 有一個指向自身的參照 Parent:子群組透過它指向所屬的群組。公式欄位 Members 選出某個國家的人員(Country filter),而子群組必須從其所屬群組的成員中選取自己的成員:

Ninox
let country := 'Country filter';
let candidates := if Parent then Parent.Members else select People end;
candidates[Country = country]

公式編輯器拒絕這段程式碼:「Circular reference: Members」。

原因

Ninox 以欄位而非記錄來推理。要編譯 Members 的公式,它必須知道 Parent.Members 的型別,因此要編譯 Members 的公式……而這正是它此刻在編譯的公式。父記錄永遠不會是記錄本身,這一點無關緊要:這種依賴在編譯時就被拒絕了。

注意

同一個運算式透過程式介面(/query)求值時,或者放在另一個欄位的公式中時,都不會報錯。只有它所讀取的那個欄位的公式編輯器會拒絕它:因此,在別處測試成功並不能保證它會被接受。

解決方法:第二個欄位

讓 Members 在不讀取父群組的情況下計算其清單:

Ninox
let country := 'Country filter';
select People where Country = country

然後把限制交給第二個公式欄位 Effective members,它讀取記錄本身及其父記錄上的 Members:

Ninox
if Parent then
    let parentMembers := Parent.Members;
    Members[contains(parentMembers, this)]
else
    Members
end

Effective members 讀取 Members,但 Members 不讀取 Effective members:不再有循環。在方括號內,this 指正在檢查的人員;因此父記錄的成員要事先讀入一個變數。

須知

  • 子群組的 Members 欄位現在包含不屬於該群組的人員:所有顯示或使用成員的地方(檢視、按鈕、全域函式)都必須讀取 Effective members。
  • 循環也可能經過兩個欄位:讀取 Parent.'Effective members' 的 Members 會形成 Members → Effective members → Members 的循環。我們沒有驗證 Ninox 如何處理這種情況:請用同樣的方法避免它。