Patch 函式

適用於 畫布應用程式 模型導向應用程式 Power Platform CLI

修改或建立 資料來源 中的一或多筆 記錄,或合併資料來源外的記錄。

在複雜情況下,使用 Patch 函式來修改記錄,例如,當您執行的更新不需要使用者互動或使用跨多個畫面的表單時。

若要更輕鬆地更新資料來源中的記錄以進行簡單變更,請改用 Edit form 控制項。 當您新增 Edit form 控制項時,您會提供表單供使用者填寫,然後將變更儲存至資料來源。 如需詳細資訊,請參閱 了解資料表單

觀看此影片瞭解如何使用 Patch 函式:

概觀

使用 Patch 函式修改資料來源的一或多筆記錄。 會修改特定 欄位 值而不影響其他屬性。 例如,此公式會變更名為 Contoso 客戶的電話號碼︰

Patch( Customers, First( Filter( Customers, Name = "Contoso" ) ), { Phone: "1-212-555-1234" } )

使用 PatchDefaults 函式建立記錄。 使用此行為組建 單一畫面控制項 建立和編輯記錄。 例如,此公式會建立名為 Contoso 客戶的記錄:

Patch( Customers, Defaults( Customers ), { Name: "Contoso" } )

即使您不使用資料來源,也可以使用 Patch 合併兩筆或多筆記錄。 例如此公式會將兩筆記錄合併為一筆記錄,以識別 Contoso 的電話號碼和位置:

Patch( { Name: "Contoso", Phone: "1-212-555-1234" }, { Name: "Contoso", Location: "Midtown" } )

描述

修改或建立資料來源中的記錄

若要使用此函式與資料來源,請指定資料來源,然後指定基底記錄︰

  • 若要修改一筆記錄,基底記錄必須來自資料來源。 基底記錄可能會取自資源庫的 Items 屬性、已放入 上下文變數,或透過其他若干路徑。 但您可以將基底記錄追回資料來源。 這十分重要,因為該記錄將包含其他資訊以協助您再次找到要修改的記錄。
  • 若要建立記錄,請使用 Defaults 函式使用預設值建立基底記錄。

然後指定一或多筆變更記錄,其中每一筆皆包含在基底記錄中覆寫屬性值的新屬性值。 變更記錄會依引數清單開頭到結尾的順序處理,並以新的屬性值覆寫舊的屬性值。

Patch 的傳回值是您修改或建立的記錄。 如果您建立一筆記錄,傳回值可能包含資料來源自動產生的屬性。 但是,傳回值並未為相關資料表的欄位提供值。

例如,您使用 Set(MyAccount, Patch(Accounts, First(Account), 'Account Name': "Example name"));,接著使用 MyAccount.'Primary Contact'.'Full Name'。 本案例中您不能暫止完整名稱。 相反地,若要存取相關資料表的欄位,請使用獨立的查詢,例如:

LookUp(Accounts, Account = MyAccount.Account).'Primary Contact'.'Full Name'

當您更新資料來源時,可能會發生一或多個問題。 使用 IfErrorIsError,以及從 Patch 傳回的值來偵測並回應錯誤,如同錯誤處理中的說明。 您也可以使用 Errors 函式識別及檢查問題,如搭配資料來源所述。

相關函式包括 Update 函式,取代整筆記錄及 Collect 函式,建立一筆記錄。 使用 UpdateIf 函式,根據條件修改多筆記錄的特定屬性。

修改或建立資料來源中的一組記錄

Patch 也可用來建立或修改透過單一呼叫的多筆記錄。

可在第二個引數中提供基底記錄的資料表,而不是傳遞單一基底記錄。 也會在資料表中提供變更記錄,以基底記錄對應一對一。 每個變更資料表中的記錄數目必須與基底資料表中的記錄數目相同。

以這種方式使用 Patch 時,傳回值也是包含每個記錄對應一對一與基底和變更記錄的資料表。

合併資料來源外部的記錄

指定您想要合併的兩筆或多筆記錄。 記錄會依引數清單開頭到結尾的順序處理,並以新的屬性值覆寫舊的屬性值。

Patch 會傳回合併的記錄,且不會修改其引數或任何資料來源中的記錄。

語法

修改或建立資料來源中的記錄

Patch( DataSource, BaseRecord, ChangeRecord1 [, ChangeRecord2, … ])

  • DataSource – 必要項目。 包含您想要修改之記錄或將包含您想要建立之記錄的資料來源。
  • BaseRecord – 必要項目。 要修改或建立的記錄。 如果記錄來自資料來源,則已找到並修改記錄。 如果使用 Defaults 的結果,可建立記錄。
  • ChangeRecord(s) - 必要項目。 包含要在 BaseRecord 中修改屬性的一或多筆記錄。 變更記錄會依引數清單開頭到結尾的順序處理,並以新的屬性值覆寫舊的屬性值。

修改或建立資料來源中的一組記錄

Patch( DataSource, BaseRecordsTable, ChangeRecordTable1 [, ChangeRecordTable2, … ] )

  • DataSource – 必要項目。 包含您想要修改之記錄或將包含您想要建立之記錄的資料來源。
  • BaseRecordTable – 必要項目。 要修改或建立的記錄資料表。 如果記錄來自資料來源,則已找到並修改記錄。 如果使用 Defaults 的結果,可建立記錄。
  • ChangeRecordTable(s) – 必要項目。 包含要針對 BaseRecordTable 的每筆記錄修改屬性的一個或多個記錄資料表。 變更記錄會依引數清單開頭到結尾的順序處理,並以新的屬性值覆寫舊的屬性值。

合併記錄

Patch( Record1, Record2 [, …] )

  • Record(s) – 必要項目。 至少兩筆您想要合併的記錄。 記錄會依引數清單開頭到結尾的順序處理,並以新的屬性值覆寫舊的屬性值。

範例

修改或建立記錄 (在資料來源中)

在這些範例中,您會修改或建立資料來源中的記錄,名為 IceCream,其中包含在此資料表中的資料,並在 ID欄位中自動產生值:

範例 icecream。

公式 描述 Result
Patch( IceCream,
LookUp( IceCream, Flavor = "Chocolate" ), { Quantity: 400 } )
修改 IceCream 資料來源中的記錄︰
  • 要修改記錄的 ID 欄位包含值 1。 (Chocolate 記錄具有該 ID。)
  • Quantity 欄位值會變更為 400
{ ID: 1, Flavor: "Chocolate", Quantity: 400 }

IceCream 資料來源中的 Chocolate 項目已修改。
Patch( IceCream, Defaults( IceCream ), { Flavor: "Strawberry" } ) 建立 IceCream 資料來源中的記錄︰
  • ID 欄位包含資料來源自動產生的值 3
  • Quantity 欄位包含 0,是 IceCream 資料來源中該欄位的預設值,如 Defaults 函式所指定。
  • Flavor 欄位包含值 Strawberry
{ ID: 3, Flavor: "Strawberry", Quantity: 0 }

IceCream 資料來源中的 Strawberry 項目已建立。

評估過上述公式之後,資料來源最後會顯示這些值︰

範例冰淇淋之後。

合併記錄 (資料來源外)

公式 描述 結果
Patch( { Name: "James", Score: 90 }, { Name: "Jim", Passed: true } ) 合併資料來源外部的兩筆資料:
  • 每筆記錄的 Name 欄位值都不符合。 結果包含較接近引數清單結尾記錄中的值 (Jim),而不是較接近開始記錄中的值 (James)。
  • 第一筆記錄包含的欄位 (Score) 不存在於第二筆記錄。 結果會包含該欄位與其值 (90)。
  • 第二筆記錄包含的欄位 (Passed) 不存在於第一筆記錄。 結果會包含該欄位與其值 (true)。
{ Name: "Jim", Score: 90, Passed: true }

使用 AsThisRecord

在公式中使用 AsThisRecord 關鍵字可避免不明確的計算上下文。

在下面的範例中,請考慮 If 陳述式中的第一個查詢。 (OrderID = A[@OrderID]) 預計會將查詢範圍中的 OrderIdForAll 範圍中集合 AOrderId 進行比較。 在此案例中,您可能希望將 A[@OrderId] 解析為本機參數。 但是不明確。

Power Apps 目前會將左側 OrderId 和右側 A[@OrderId] 解釋為查詢範圍中的欄位。 因此,查詢將始終會在 [dbo].[Orders1] 中尋找第一列,因為條件始終為 true(即任何列的 OrderId 值都等於自身)。

ClearCollect(
    A,
    Filter(
        '[dbo].[Orders1]',
        OrderId = 8888888
    )
);
ForAll(
    A,
    If(
        LookUp(
            '[dbo].[Orders1]',
            OrderId = A[@OrderId],
            "OK"
        ) = "OK",
        Patch(
            '[dbo].[Orders1]',
            LookUp(
                '[dbo].[Orders1]',
                OrderId = A[@OrderId]
            ),
            {
      OrderName: "val1"
       }
   ),
   Patch(
            '[dbo].[Orders1]',
            Defaults('[dbo].[Orders1]'),
            {
      OrderName: "val2"
       }
   )
    )
)

使用 AsThisRecord

只要有可能,請使用 As 運算子或 ThisRecord 來消除左側的歧義。 針對上述案例建議使用 As

當您的公式在同一個資料來源或表格上使用具有 ForAllFilterLookup 的多個範圍時,範圍參數可能會與其他地方的同一欄位衝突。 因此,建議使用 As 運算子或 ThisRecord 來解析欄位名稱,避免混淆。

例如,您可以使用 As 運算子來消除下列範例中的歧義。

ClearCollect(
    A,
    Filter(
        '[dbo].[Orders1]',
        OrderId = 8888888
    )
);
ForAll(
    A,
    If(
        LookUp(
            '[dbo].[Orders1]' As B,
            B.OrderId = A[@OrderId],
            "OK"
        ) = "OK",
        Patch(
            '[dbo].[Orders1]',
            LookUp(
                '[dbo].[Orders1]' As C,
                C.OrderId = A[@OrderId]
            ),
            {
      OrderName: "val1"
       }
   ),
   Patch(
            '[dbo].[Orders1]',
            Defaults('[dbo].[Orders1]'),
            {
      OrderName: "val2"
       }
   )
    )
)

或者,您也可以使用 ThisRecord 來進行相同的目的。

ClearCollect(
    A,
    Filter(
        '[dbo].[Orders1]',
        OrderId = 8888888
    )
);
ForAll(
    A,
    If(
        LookUp(
            '[dbo].[Orders1]',
            ThisRecord.OrderId = A[@OrderId],
            "OK"
        ) = "OK",
        Patch(
            '[dbo].[Orders1]',
            LookUp(
                '[dbo].[Orders1]',
                ThisRecord.OrderId = A[@OrderId]
            ),
            {
      OrderName: "val1"
       }
   ),
   Patch(
            '[dbo].[Orders1]',
            Defaults('[dbo].[Orders1]'),
            {
      OrderName: "val2"
       }
   )
    )
)

若要進一步了解 As 運算子和 ThisRecord 的用法,請參閱運算子文章。