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'

데이터 원본을 업데이트할 때 하나 이상의 문제가 발생할 수 있습니다. 오류 처리에 설명된 대로 IfErrorIsErrorPatch의 반환 값과 함께 사용하여 오류를 감지하고 대응합니다. 또한 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) – 필수 항목입니다. 병합할 둘 이상의 레코드입니다. 레코드는 인수 목록의 처음부터 끝까지 순서대로 처리되며, 이후 속성 값이 이전 속성 값보다 우선합니다.

예제

데이터 원본의 레코드 수정 또는 만들기

이 예제에서는 이 테이블의 데이터를 포함하고 IDcolumn에 값을 자동으로 생성하는 IceCream이라는 데이터 소스의 레코드를 수정하거나 생성합니다.

예제 icecream.

수식 Description 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 열에는 Defaults 함수가 지정한 대로 IceCream 데이터 원본의 해당 열에 대한 기본값인 0이 있습니다.
  • Flavor 열에는 Strawberry라는 값이 있습니다.
{ ID: 3, Flavor: "Strawberry", Quantity: 0 }

IceCream 데이터 원본에 Strawberry 항목이 생성되었습니다.

이전 수식이 계산된 후 데이터 원본은 다음 값으로 끝납니다.

IceCream 이후 예.

데이터 원본 외부에서 레코드 병합

수식 설명 결과
Patch( { Name: "James", Score: 90 }, { Name: "Jim", Passed: true } ) 데이터 원본 외부의 두 레코드를 병합합니다.
  • 각 레코드의 Name 열 값은 일치하지 않습니다. 결과에는 인수 목록의 시작에 더 가까운 레코드의 값(James) 대신 인수 목록의 끝에 더 가까운 레코드의 값(Jim)이 포함됩니다.
  • 첫 번째 레코드에 두 번째 레코드에 없는 열(Score)이 포함되어 있습니다. 결과에는 이 열이 해당하는 값(90)과 함께 포함됩니다.
  • 두 번째 레코드에 첫 번째 레코드에 없는 열(Passed)이 포함되어 있습니다. 결과에는 이 열이 해당하는 값(true)과 함께 포함됩니다.
{ Name: "Jim", Score: 90, Passed: true }

As 또는 ThisRecord 사용

수식에서 As 또는 ThisRecord 키워드를 사용하면 모호한 평가 컨텍스트를 방지합니다.

아래 예에서 If 문의 첫 번째 조회를 생각해 봅니다. (OrderID = A[@OrderID])는 조회 범위의 OrderIdForAll 범위에 있는 컬렉션 AOrderId를 비교할 것으로 예상됩니다. 이 경우 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를 사용하여 왼쪽을 명확하게 합니다. As는 위의 시나리오에서 권장됩니다.

수식이 동일한 데이터 원본 또는 테이블에서 ForAll, FilterLookup이 있는 여러 범위를 사용하는 경우 범위 매개 변수가 다른 위치의 동일한 필드와 충돌할 수 있습니다. 따라서 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 사용법에 대해 자세히 알아보려면 연산자 문서를 참조하세요.