适用于: 画布应用
Copilot Studio
Desktop 流
模型驱动应用
Power Platform CLI
Dataverse 函数
在数据源中修改或创建一条或多条记录,或者合并数据源外的记录。
使用 Patch 函数修改复杂情况下的记录,例如,执行不需要用户交互的更新或使用跨多个屏幕的表单时。
要更轻松地更新数据源中的记录以进行简单更改,请改用 Edit form 控件。 添加 Edit form 控件时,可以向用户提供要填写的窗体,然后将更改保存到数据源中。 有关详细信息,请参阅了解数据窗体。
观看此视频,了解如何使用函数 Patch :
概述
使用该 Patch 函数修改数据源的一个或多个记录。 可以在不影响其他属性的情况下修改特定字段的值。 例如,以下公式更改名为 Contoso 的客户的电话号码:
Patch( Customers, LookUp( Customers, Name = "Contoso" ), { Phone: "1-212-555-1234" } )
与 PatchDefaults 函数一起使用以创建记录。 可以利用此行为生成一个屏幕,以供创建和编辑记录。 例如,以下公式为名为 Contoso 的客户创建记录:
Patch( Customers, Defaults( Customers ), { Name: "Contoso" } )
注释
使用具有默认值的数据源中的记录修补集合时,修补作会使用指定的修补值和数据源中的默认值更新集合。 patch 语句的 DataSource 和 Defaults 函数的 DataSource 必须匹配才能创建新记录。
即使未使用数据源,也可以使用 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'
更新数据源时,可能会出现一个或多个问题。 将 IfError 和 IsError 与返回值 Patch 一起使用,以检测和响应错误,如 错误处理 所述。 您还可以使用 Errors 函数识别和检查问题,如使用数据源所述。
相关函数包括 Update 函数来替换整个记录,以及 Collect 函数来创建记录。 使用 UpdateIf 函数可以根据条件来修改多条记录的特定属性。
在数据源中修改或创建一组记录
Patch 还可以用于通过单个调用创建或修改多个记录。
它不是传递单条基本记录,而是在第二个参数中提供一个基本记录表。 更改记录也是通过表提供,并且与基本记录一一对应。 每个更改表中记录的数量必须与基本表中记录的数量完全相等。
以这种方式使用 Patch 时,返回值也是一个表,每个记录对应一对一的基记录和更改记录。
合并数据源外部的记录
指定一条或多条要合并的记录。 记录按照参数列表从头到尾的顺序进行处理,并且使用后者的属性值替换前者的属性值。
Patch 返回合并的记录,并且不会修改其任何数据源中的参数或记录。
语法
在数据源中修改或创建记录
Patch( DataSource、 BaseRecord、 ChangeRecord1 [、 ChangeRecord2、... ])
- DataSource – 必需。 包含要修改的记录或用于包含要创建的记录的数据源。
- BaseRecord –必需。 要修改或创建的记录。 如果记录来自数据源,则会找到记录并进行修改。 如果使用 Defaults 函数的结果,则会创建记录。 patch 语句的 DataSource 和 Defaults 函数的 DataSource 必须匹配才能创建新记录。
- ChangeRecords –必需。 一条或多条记录,其中包含要在 BaseRecord 中修改的属性。 更改记录按照参数列表从头到尾的顺序进行处理,并且使用后者的属性值替换前者的属性值。
在数据源中修改或创建一组记录
Patch( DataSource、 BaseRecordsTable、 ChangeRecordTable1 [、 ChangeRecordTable2、... ] )
- DataSource – 必需。 包含要修改的记录或用于包含要创建的记录的数据源。
- BaseRecordTable –必需。 要修改或创建的记录的表。 如果记录来自数据源,则会找到记录并进行修改。 如果使用 Defaults 函数的结果,则会创建记录。 patch 语句的 DataSource 和 Defaults 函数的 DataSource 必须匹配才能创建新记录。
- ChangeRecordTables –必需。 记录的一个或多个表,其中包含在 BaseRecordTable 中要修改的每条记录的属性。 更改记录按照参数列表从头到尾的顺序进行处理,并且使用后者的属性值替换前者的属性值。
合并记录
Patch(Record1,Record2 [,...] )
- 记录 - 必需。 至少要有两条要合并的记录。 记录按照参数列表从头到尾的顺序进行处理,并且使用后者的属性值替换前者的属性值。
示例
修改或创建记录(在数据源中)
在以下示例中,您会在名为 IceCream 的数据源中修改或创建一条记录,该数据源包含此表中的数据,并且会在 ID列中自动生成相应的值:
| 公式 | 描述 | 结果 |
|---|---|---|
|
Patch(IceCream, LookUp(IceCream, Flavor = “Chocolate” ), { Quantity: 400 } ) |
修改 IceCream 数据源中的记录:
|
{ ID: 1, 风格: “Chocolate”, Quantity: 400 } 已修改 IceCream 数据源中的 Chocolate 条目。 |
| Patch(IceCream, Defaults( IceCream), { Flavor: “草莓” } ) | 在 IceCream 数据源中创建一条记录。
|
{ ID: 3, 风格: “草莓”, 数量: 0 } 已在 IceCream 数据源中创建 Strawberry 条目。 |
对上面的公式进行计算后,数据源最终会产生以下值:
合并记录(数据源外部)
| 公式 | 描述 | 结果 |
|---|---|---|
| Patch( { Name: “James”, Score: 90 }, { Name: “Jim”, Passed: true } ) | 合并数据源外的两条记录:
|
{ Name: “Jim”, Score: 90, Passed: true } |
使用 As 或 ThisRecord
在公式中使用 As 或 ThisRecord 关键字可避免不明确的计算上下文。
在下面的示例中,请考虑 If 语句中的第一个查找。
(OrderID = A[@OrderID]) 应将 OrderId the in the lookup scope 与 OrderId the A collection in the scope 进行比较 ForAll 。 在此情况下,您可能希望 A[@OrderId] 解析为本地参数。 但这并不明确。
Power Apps 目前将左侧 OrderId 和右侧 A[@OrderId] 都解释为查找范围中的字段。 因此,查找时总是会在 [dbo].[Orders1] 中查找第一行,因为条件始终为真(也就是说,任何行的 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"
}
)
)
)
使用 As 或 ThisRecord
只要有可能,请使用 As 运算符或 ThisRecord 来消除左侧的歧义。 对于 上述场景,建议这样做。
当您的公式在同一个数据源或表上对 ForAll、Filter 和 Lookup 使用多个范围时,范围参数可能会与其他地方的相同字段发生冲突。 因此,建议使用 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 的用法,请参阅运算符文章。