Lookup Columns in Power Apps: Create, Display, and Patch Without the Guesswork
Lookups are how Dataverse tables relate to each other, and they're the column type that causes the most confusion in Power Apps. Here's how to set them up and work with them in canvas apps.
Lookup columns in Dataverse are foreign keys. They connect one table to another — a Contact to an Account, an Order to a Customer, a Task to a Project. If you’ve worked with relational databases, you already know the concept. The tricky part is how Power Apps handles them.
Creating a Lookup Column
- Open your table.
- Click New column.
- Set the data type to Lookup.
- Choose the Related table — this is the table the lookup points to.
- Save.
This creates a many-to-one relationship: many records in your current table can point to one record in the related table. For example, many Contacts can point to one Account.
The lookup column stores the GUID of the related record. Dataverse automatically creates a relationship and adds a navigation property that you can use in queries.
Many-to-One vs Many-to-Many
Many-to-one (Lookup): One side has a lookup column. A Contact has a lookup to Account. Simple, direct.
Many-to-many (N:N): Neither table has a lookup column. Instead, there’s a hidden intersection table. A User can belong to many Teams. A Team can have many Users. You create these through the Relationships section, not through a column.
In canvas apps, many-to-many relationships are harder to work with. You can’t patch them directly — you need to use the Relate() and Unrelate() functions.
Displaying Lookup Values in a Gallery
When you connect a gallery to a Dataverse table, lookup columns show as records, not text. To display the name of the related record:
ThisItem.'Company Name'.'Account Name'
The first part ('Company Name') is the lookup column on your current table. The second part ('Account Name') is the display column on the related table.
For a label in a gallery connected to Contacts:
| What You Want | Formula |
|---|---|
| Parent account name | ThisItem.'Company Name'.'Account Name' |
| Parent account phone | ThisItem.'Company Name'.'Main Phone' |
| Owner’s full name | ThisItem.Owner.'Full Name' |
Patching a Lookup Column
This is where most people hit a wall. You can’t just pass a GUID or a name. You need to pass a record from the related table.
Using LookUp to Find the Record
Patch(
Contacts,
Defaults(Contacts),
{
'First Name': "Jane",
'Last Name': "Doe",
'Company Name': LookUp(Accounts, 'Account Name' = "Contoso Ltd")
}
)
Using a Gallery Selection
If the user selected an account from a gallery or dropdown:
Patch(
Contacts,
Defaults(Contacts),
{
'First Name': "Jane",
'Last Name': "Doe",
'Company Name': drpAccounts.Selected
}
)
Using a Variable That Holds a Record
Set(varSelectedAccount, LookUp(Accounts, 'Account Name' = "Contoso Ltd"));
Patch(
Contacts,
Defaults(Contacts),
{
'First Name': "Jane",
'Last Name': "Doe",
'Company Name': varSelectedAccount
}
)
Clearing a Lookup
Patch(
Contacts,
ThisItem,
{
'Company Name': Blank()
}
)
Filtering Lookups in a Dropdown or Combo Box
A common requirement: show only accounts from a specific city in a lookup dropdown.
Set the Items property of your Combo Box or Dropdown to a filtered table:
Filter(Accounts, 'Address 1: City' = "Seattle")
For a cascading lookup (second dropdown depends on first):
// Dropdown 1: Select a Country
Items: Distinct(Accounts, 'Address 1: Country')
// Dropdown 2: Show only cities in the selected country
Items: Filter(
Accounts,
'Address 1: Country' = drpCountry.Selected.Value
)
Displaying the Lookup in a Form
If you’re using an Edit Form control, lookup columns automatically show as searchable dropdowns. You don’t need custom code for basic functionality.
To customize what the dropdown shows, select the DataCard for the lookup field and modify the DisplayFields and SearchField properties of the ComboBox inside it.
Using Lookup Values in Filters
To filter a gallery by a lookup value:
// Show contacts that belong to the selected account
Filter(
Contacts,
'Company Name'.'Account Name' = Gallery_Accounts.Selected.'Account Name'
)
Or more efficiently using the primary key:
Filter(
Contacts,
'Company Name'.Account = Gallery_Accounts.Selected.Account
)
Filtering by GUID (the .Account field is the primary key) is more reliable and delegation-friendly than filtering by name.
Common Mistakes and How to Fix Them
”The specified column does not exist” When Patching
You’re using the wrong column name. Lookup columns in Power Apps use the display name, not the schema name. Check the column’s display name in the table designer. It’s case-sensitive.
Patch Succeeds But Lookup Is Blank
You’re passing the name (a string) instead of the record. This is the most common lookup mistake:
// Wrong: passing a text value
{ 'Company Name': "Contoso Ltd" }
// Right: passing a record
{ 'Company Name': LookUp(Accounts, 'Account Name' = "Contoso Ltd") }
Dropdown Shows GUIDs Instead of Names
Your Combo Box or Dropdown’s DisplayFields property isn’t set correctly. Set it to the display column of the related table:
["cr5e8_name"] // schema name of the display column
Or in newer controls, just set the Value property to the display field.
Lookup Filter Causes Delegation Warning
Filtering a lookup table using Filter() with non-delegable functions (like Search() or in on text columns with some connectors) triggers the yellow delegation warning. For large tables, make sure your filter uses columns and operators that Dataverse supports for delegation — =, <>, StartsWith, and column comparisons.
Can’t Patch a Many-to-Many Relationship
You can’t use Patch() for N:N relationships. Use Relate() and Unrelate() instead:
// Associate a contact with a team
Relate(
Teams,
LookUp(Teams, 'Team Name' = "Sales Team"),
ThisItem
)
These functions work on the N:N relationship, not on individual columns.
Related articles
Cascading Dropdowns in Canvas Apps (Yes, It's Harder Than It Should Be)
A parent dropdown for Country, a child dropdown for City that only shows cities in the selected country. Here's the pattern, the delegation-safe version, and the reset behavior that catches everyone.
Get the Current User in Power Apps
The User() function gets you started, but most real scenarios need more. Here's how to get the current user's details from Dataverse, including Business Unit, Team membership, and security role.
Patching Records in Canvas Apps: Creates, Updates, and the Errors You'll Get
The Patch function is how you create and update records in canvas apps. Here's the syntax for every column type, including lookups and choices, plus fixes for the errors you'll definitely hit.