Run SOQL Query
Audience:
Low-code EngineersSkill Prerequisites:
Actions,Tokens,Connectors,SOQL
Runs a SOQL query in Salesforce and saves fields from the first record in tokens, so later actions can use them. It signs in with a Salesforce connector.
SOQL (Salesforce Object Query Language) is Salesforce's read-only query language, for example SELECT Id, Email FROM Lead WHERE Email = 'jane@example.com'. The action can't create, change or delete records.
This action is part of the Salesforce add-on (DnnSharp.Salesforce). The add-on is installed separately and needs the SALESFORCE feature in your license. If it isn't licensed, the action fails with a "not licensed" error. If you don't see the Salesforce actions, the add-on isn't installed.
Typical Use Cases
- Load a lead or contact by email to prefill a form
- Check if a record already exists before you create it, for example by reading its
Id - Read a single value, such as an account name or a count, to use in a condition or an email
Don't use it to
- Load many records to loop over. The action only reads the first record. To work with many records, call the Salesforce REST API with Server Request, then use Create List from JSON and Execute Actions for each List Entry.
- Create a record. Use Create a Salesforce Entity instead.
- Add a lead or contact to a campaign. Use Add to campaign instead.
- Check that a connector can sign in. Use Test Connector instead.
Related Actions
| Action Name | Description |
|---|---|
| Run SOQL Query (obsolete) | The older version of this action, with the login details in the action. |
| Add Salesforce Connector | Creates a Salesforce connector. |
| Update Salesforce Connector | Changes the details of a Salesforce connector. |
| Test Connector | Checks that a connector can sign in. |
| Create a Salesforce Entity | Creates a record in Salesforce using a connector. |
| Add to campaign | Adds a lead or contact to Salesforce campaigns using a connector. |
| Run SQL Query | Runs a SQL query against a database and saves the first row in tokens. |
Input Parameter Reference
| Parameter | Description | Supports Tokens | Default | Required |
|---|---|---|---|---|
| Connector | The Salesforce connector to sign in with. It holds the login URL, username, password and security token. See Add Salesforce Connector. In expression mode, the value must be a connector ID (a GUID). | Yes | empty | Yes |
| SOQL Query | The SOQL query to run, for example SELECT Id, FirstName FROM Lead WHERE Email = '[Email]' LIMIT 1. Tokens are replaced as plain text, with no escaping. See Tokens in the query. | Yes | empty string | Yes |
| On Error | Actions to run if the sign-in or the query fails. They can use the [ErrorMessage] token. See Errors. | No | empty | No |
Output Parameters Reference
| Parameter | Description | Supports Tokens | Default | Required |
|---|---|---|---|---|
| Extract Columns | Saves fields from the first record in tokens. Each row has a Column Name, the Salesforce field name as it's returned, for example Email, and a Store As token name, for example LeadEmail. Enter the token name without brackets. If this list is empty, the action does nothing. See Reading the result. | Yes | empty | Yes |
The action creates one token for each row in Extract Columns, for example [LeadEmail]. If the action fails, [ErrorMessage] contains the error.
Reading the result
- Only the first record is read. Use
ORDER BYandLIMIT 1in the query to decide which record that is. - No records means no tokens. If the query returns nothing, no token is set and there's no error. Tokens keep any value they had before. To check if a record was found, extract a field such as
Idinto a token, and test that token in a later condition. - Column Name is case-sensitive. Use the field's API name as Salesforce returns it, for example
FirstName, notfirstname. - Every column must be in the result. If a Column Name isn't one of the fields the query selects, the action fails.
- Empty fields give an empty token.
- Related fields use a dot, for example
Account.NameforSELECT Account.Name FROM Contact. If the related record is missing, the action fails. - Aliases work for aggregate queries. For
SELECT COUNT(Id) total FROM Lead, usetotalas the Column Name. A query withCOUNT()and no field returns no records, so there's nothing to extract, and the action fails. - Checkbox fields give
TrueorFalse. - Tokens in Extract Columns are replaced before the result is read, in both columns. You can build a Column Name or a Store As name from other tokens.
Tokens in the query
Tokens in SOQL Query are replaced with their values as plain text. Nothing is escaped, and you add the quotes around text values yourself, for example WHERE Email = '[Email]'.
Don't put user input straight into the query. A value with a quote, such as o'brien@example.com, breaks the query. A value written on purpose, such as ' OR Email != ', changes the query, so it can return a different record than you meant. Any fields you extract from it can then be shown to that user.
To stay safe:
- Only use values you control, such as IDs you saved yourself, where you can.
- Validate user input first, for example with field validation or a condition, and reject values that contain
'or\. - Sign in with a Salesforce user that can only see the objects and fields the app needs.
Errors
The action fails if it can't sign in to Salesforce, if Salesforce rejects the query, or if an extracted field isn't in the result. When it fails:
[ErrorMessage]is set to the error from Salesforce, for example an authentication or query error. When there's more than one error, they're joined with<br />.- The error is written to the DNN event log.
- If there are On Error actions, they run, and their result is used in place of this action's result.
- If there are no On Error actions, execution stops with the error
Failed to query salesforce: <error>. Its friendly message, for end users, isFailed to query salesforce.
Considerations
- Set up a connector first. Create it with Add Salesforce Connector, or on the connectors page, and check it with Test Connector.
- The action signs in on every run. Each run gets a new Salesforce session, which counts against your org's API limits.
- There's no timeout setting. A slow Salesforce response holds up the rest of the actions.
- Sandbox orgs need the sandbox login domain, for example
https://test.salesforce.com, in the connector'sLogin Url. - If the connector is missing, for example because it was deleted, the sign-in fails and the action reports an authentication error.
- A connector token that isn't a GUID makes the action fail with
Invalid credential entry id expression...before it runs, so On Error doesn't catch it.
Examples
To understand how to use the below examples, please see Running Examples.
1. Load a lead by email
This action finds the newest lead with the email in [Email] and saves its ID, name and status in tokens. Replace the connector ID with the ID of your Salesforce connector. The email should be validated before this action runs. See Tokens in the query.
{
"Title": "Run SOQL Query",
"ActionType": "RunSOQLWithCredentialStore",
"Description": "Load the lead with this email",
"Parameters": {
"Credentials": {
"Entry": "00000000-0000-0000-0000-000000000000"
},
"SOQLQuery": "SELECT Id, FirstName, LastName, Status FROM Lead WHERE Email = '[Email]' ORDER BY CreatedDate DESC LIMIT 1",
"ExtractColumns": [
{
"name": "Id",
"value": "LeadId"
},
{
"name": "FirstName",
"value": "LeadFirstName"
},
{
"name": "LastName",
"value": "LeadLastName"
},
{
"name": "Status",
"value": "LeadStatus"
}
],
"OnError": [
{
"Title": "Log Error",
"ActionType": "LogError",
"Parameters": {
"Message": "Salesforce lead lookup failed: [ErrorMessage]"
}
}
]
}
}
2. Count open cases for an account
This action counts the open cases of the account with the ID in [AccountId], using a connector ID saved in [SalesforceConnectorId]. The count is saved in [OpenCaseCount]. A later action can use it in a condition, for example [OpenCaseCount] == "0".
{
"Title": "Run SOQL Query",
"ActionType": "RunSOQLWithCredentialStore",
"Description": "Count the account's open cases",
"Parameters": {
"Credentials": {
"IsExpression": true,
"Entry": "[SalesforceConnectorId]"
},
"SOQLQuery": "SELECT COUNT(Id) total FROM Case WHERE AccountId = '[AccountId]' AND IsClosed = false",
"ExtractColumns": [
{
"name": "total",
"value": "OpenCaseCount"
}
]
}
}
Revised 09/27/2026