{"id":19776,"date":"2026-08-06T12:00:13","date_gmt":"2026-08-06T12:00:13","guid":{"rendered":"https:\/\/dianapps.com\/blog\/?p=19776"},"modified":"2026-08-09T15:27:10","modified_gmt":"2026-08-09T15:27:10","slug":"soql-and-sosl-in-salesforce","status":"publish","type":"post","link":"https:\/\/dianapps.com\/blog\/soql-and-sosl-in-salesforce\/","title":{"rendered":"SOQL and SOSL in Salesforce: Complete Guide With Examples"},"content":{"rendered":"<p><span style=\"font-weight: 400;\">A query that works is not the same as a query that scales. The trigger that queries inside a loop runs fine against ten test records and fails the moment someone imports fifty thousand.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">That gap between correct and production-ready is most of what separates developers who spend their weeks building from developers who spend them firefighting. This guide covers both query languages properly, including the modern SOQL features that most tutorials still haven\u2019t caught up with.<\/span><\/p>\n<blockquote><p><b>TL;DR<\/b><span style=\"font-weight: 400;\">: Use <\/span><b>SOQL<\/b><span style=\"font-weight: 400;\"> when you know the object and want records that match conditions. Use <\/span><b>SOSL<\/b><span style=\"font-weight: 400;\"> when you\u2019re searching text across objects you can\u2019t name in advance. SOQL allows 100 queries and 50,000 records per transaction; SOSL allows 20 searches and 2,000 records. Always bind variables, always filter on indexed fields, and never query inside a loop.<\/span><\/p><\/blockquote>\n<h2><b>SOQL vs SOSL: Which One Do You Need?<\/b><\/h2>\n<p><b>SOQL retrieves structured records from one object and its relationships. SOSL searches text across many objects at once.<\/b><span style=\"font-weight: 400;\"> They look similar and solve genuinely different problems.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-19777\" src=\"https:\/\/dianapps.com\/blog\/wp-content\/uploads\/2026\/08\/ChatGPT-Image-Aug-6-2026-03_16_26-PM.webp\" alt=\"Comparison of SOQL and SOSL in Salesforce showing when to use each, their scope and their governor limits\" width=\"1536\" height=\"1024\" srcset=\"https:\/\/dianapps.com\/blog\/wp-content\/uploads\/2026\/08\/ChatGPT-Image-Aug-6-2026-03_16_26-PM.webp 1536w, https:\/\/dianapps.com\/blog\/wp-content\/uploads\/2026\/08\/ChatGPT-Image-Aug-6-2026-03_16_26-PM-1024x683.webp 1024w, https:\/\/dianapps.com\/blog\/wp-content\/uploads\/2026\/08\/ChatGPT-Image-Aug-6-2026-03_16_26-PM-768x512.webp 768w, https:\/\/dianapps.com\/blog\/wp-content\/uploads\/2026\/08\/ChatGPT-Image-Aug-6-2026-03_16_26-PM-640x427.webp 640w, https:\/\/dianapps.com\/blog\/wp-content\/uploads\/2026\/08\/ChatGPT-Image-Aug-6-2026-03_16_26-PM-400x267.webp 400w\" sizes=\"auto, (max-width: 1536px) 100vw, 1536px\" \/><\/p>\n<p><i><span style=\"font-weight: 400;\">Comparison of SOQL and SOSL in Salesforce showing when to use each, their scope and their governor limits<\/span><\/i><\/p>\n<p><b>The practical test<\/b><span style=\"font-weight: 400;\">: <\/span><i><span style=\"font-weight: 400;\">do you know which object the data is in?<\/span><\/i><span style=\"font-weight: 400;\"> If yes, SOQL. If you\u2019re building a search box where the user might be looking for an account, a contact, or a case, SOSL.<\/span><\/p>\n<h2><b>SOQL Syntax Fundamentals<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">SOQL looks like SQL but has no manual joins relationships are built into the platform.<\/span><\/p>\n<pre class=\"theme:github nums:false lang:default decode:true \">SELECT Id, Name, Industry\r\nFROM \u00a0 Account\r\nWHERE\u00a0 Industry = 'Banking'\r\nORDER\u00a0 BY Name\r\nLIMIT\u00a0 10\r\n\r\nInside Apex you can inline it directly:\r\n\r\nList&lt;Account&gt; accounts = [\r\n\u00a0 \u00a0 SELECT Id, Name\r\n\u00a0 \u00a0 FROM \u00a0 Account\r\n\u00a0 \u00a0 WHERE\u00a0 Industry = 'Banking'\r\n];<\/pre>\n<p>&nbsp;<\/p>\n<p><b>Three rules that matter from day one:<\/b><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Select Only the Fields You Need:<\/b> <span style=\"font-weight: 400;\">SELECT *<\/span><span style=\"font-weight: 400;\"> doesn\u2019t exist in SOQL, and that\u2019s deliberate. Every extra field adds heap.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Always Filter:<\/b><span style=\"font-weight: 400;\"> An unfiltered query against a large object is the most common cause of a heap or row-limit failure.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Always Add a LIMIT:<\/b><span style=\"font-weight: 400;\"> When the result set could grow. Especially in anything user-facing.<\/span><\/li>\n<\/ul>\n<h2><b>Relationship Queries: Traversing Objects<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">This is where SOQL becomes genuinely useful and where most early mistakes happen.<\/span><\/p>\n<p><i><span style=\"font-weight: 400;\">Diagram showing child-to-parent dot notation queries and parent-to-child subqueries in SOQL, plus custom object relationship naming rules<\/span><\/i><\/p>\n<h3><b>Child-to-parent: dot notation<\/b><\/h3>\n<pre class=\"theme:github nums:false lang:default decode:true \">SELECT Id, LastName, Account.Name, Account.Owner.Email\r\nFROM \u00a0 Contact\r\nWHERE\u00a0 Account.Industry = 'Banking'<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400;\">You can traverse <\/span><b>up to five levels<\/b><span style=\"font-weight: 400;\"> upward. Note you can also filter on parent fields, which is often overlooked.<\/span><\/p>\n<h3><b>Parent to child: subquery<\/b><\/h3>\n<pre class=\"theme:github nums:false lang:default decode:true\">SELECT Name,\r\n\u00a0 \u00a0 \u00a0 (SELECT LastName, Email FROM Contacts WHERE Email != NULL)\r\nFROM \u00a0 Account<\/pre>\n<p><span style=\"font-weight: 400;\">Only <\/span><b>one level<\/b><span style=\"font-weight: 400;\"> downward, and the name in the subquery is the <\/span><i><span style=\"font-weight: 400;\">child relationship name<\/span><\/i><span style=\"font-weight: 400;\"> \u2014 which is plural and is not the object name.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Iterating both:<\/span><\/p>\n<pre class=\"theme:github nums:false lang:default decode:true \">for (Account acc : accountList) {\r\n\u00a0 \u00a0 System.debug('Account: ' + acc.Name);\r\n\u00a0 \u00a0 for (Contact con : acc.Contacts) {\r\n\u00a0 \u00a0 \u00a0 \u00a0 System.debug(' \u00a0 Contact: ' + con.LastName);\r\n\u00a0 \u00a0 }\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<h3><b>Custom objects: the naming trap<\/b><\/h3>\n<pre class=\"theme:github nums:false lang:default decode:true\">SELECT Name,\r\n\u00a0 \u00a0 \u00a0 (SELECT Name, Status__c FROM Tasks__r)\r\nFROM \u00a0 Project__c<\/pre>\n<p><span style=\"font-weight: 400;\">Objects and fields end <\/span><span style=\"font-weight: 400;\">__c<\/span><span style=\"font-weight: 400;\">. Relationship names end <\/span><span style=\"font-weight: 400;\">__r<\/span><span style=\"font-weight: 400;\"> and are usually plural.<\/span><\/p>\n<p><b>Never guess the relationship name<\/b><span style=\"font-weight: 400;\">; find it in Setup \u2192 Object Manager \u2192 child object \u2192 Fields &amp; Relationships \u2192 open the lookup or master-detail field \u2192 <\/span><i><span style=\"font-weight: 400;\">Child Relationship Name<\/span><\/i><span style=\"font-weight: 400;\">.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">That exact string is what SOQL expects.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Related: The Salesforce data model explained<\/span><\/p>\n<h2><b>Filtering, Ordering and Date Literals<\/b><\/h2>\n<pre class=\"theme:github nums:false lang:default decode:true\">WHERE Industry = 'Banking'\r\nWHERE AnnualRevenue &gt; 1000000\r\nWHERE Name LIKE 'Acme%'\r\nWHERE Id IN :accountIds\r\nWHERE Status__c IN ('Open', 'Pending')\r\nWHERE CloseDate = LAST_N_DAYS:30<\/pre>\n<p><b>Date literals<\/b><span style=\"font-weight: 400;\"> save a lot of clumsy date arithmetic:<\/span><\/p>\n\n<table id=\"tablepress-242\" class=\"tablepress tablepress-id-242\">\n<thead>\n<tr class=\"row-1\">\n\t<th class=\"column-1\">Literal<\/th><th class=\"column-2\">Returns<\/th>\n<\/tr>\n<\/thead>\n<tbody class=\"row-striping row-hover\">\n<tr class=\"row-2\">\n\t<td class=\"column-1\">TODAY \/ YESTERDAY \/ TOMORROW<\/td><td class=\"column-2\">Single day<\/td>\n<\/tr>\n<tr class=\"row-3\">\n\t<td class=\"column-1\">THIS_WEEK \/ THIS_MONTH \/ THIS_QUARTER \/ THIS_YEAR<\/td><td class=\"column-2\">Current period<\/td>\n<\/tr>\n<tr class=\"row-4\">\n\t<td class=\"column-1\">LAST_N_DAYS:30<\/td><td class=\"column-2\">Rolling 30-day window<\/td>\n<\/tr>\n<tr class=\"row-5\">\n\t<td class=\"column-1\">NEXT_N_MONTHS:3<\/td><td class=\"column-2\">Forward-looking window<\/td>\n<\/tr>\n<tr class=\"row-6\">\n\t<td class=\"column-1\">LAST_FISCAL_QUARTER<\/td><td class=\"column-2\">Fiscal, not calendar<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<!-- #tablepress-242 from cache -->\n<p><b>Ordering and paging:<\/b><\/p>\n<pre class=\"theme:github nums:false lang:default decode:true\">SELECT Name FROM Account\r\nORDER BY Name ASC NULLS LAST\r\nLIMIT 20 OFFSET 40<\/pre>\n<p><span style=\"font-weight: 400;\">OFFSET<\/span><span style=\"font-weight: 400;\"> caps at 2,000 rows. For anything deeper, page by the last record\u2019s sort value instead; offset paging degrades badly at scale.<\/span><\/p>\n<h2><b>Aggregate Functions and GROUP BY<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Aggregates return <\/span><span style=\"font-weight: 400;\">AggregateResult<\/span><span style=\"font-weight: 400;\">, not sObjects, which catches people out.<\/span><\/p>\n<pre class=\"theme:github nums:false lang:default decode:true\">SELECT StageName, COUNT(Id) dealCount, SUM(Amount) total\r\nFROM \u00a0 Opportunity\r\nWHERE\u00a0 CloseDate = THIS_YEAR\r\nGROUP\u00a0 BY StageName\r\nHAVING COUNT(Id) &gt; 5\r\n\r\nfor (AggregateResult ar : results) {\r\n\u00a0 \u00a0 String stage\u00a0 = (String) ar.get('StageName');\r\n\u00a0 \u00a0 Integer count = (Integer) ar.get('dealCount');\r\n\u00a0 \u00a0 Decimal total = (Decimal) ar.get('total');\r\n}<\/pre>\n<p><span style=\"font-weight: 400;\">Available: <\/span><span style=\"font-weight: 400;\">COUNT()<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">COUNT_DISTINCT()<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">SUM()<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">AVG()<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">MIN()<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">MAX()<\/span><span style=\"font-weight: 400;\">. Also <\/span><span style=\"font-weight: 400;\">GROUP BY ROLLUP<\/span><span style=\"font-weight: 400;\"> and <\/span><span style=\"font-weight: 400;\">GROUP BY CUBE<\/span><span style=\"font-weight: 400;\"> for subtotals.<\/span><\/p>\n<p><b>Alias Your Aggregates:<\/b><span style=\"font-weight: 400;\"> Without an alias, you\u2019re reaching for <\/span><span style=\"font-weight: 400;\">expr0<\/span><span style=\"font-weight: 400;\">, which is unreadable and breaks the moment someone adds a column.<\/span><\/p>\n<h2><b>Semi-Joins and Anti-Joins<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Two of the most useful patterns in SOQL and among the least used.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\/\/ Accounts that HAVE at least one contact<\/span><span style=\"font-weight: 400;\"><br \/>\n<\/span><\/p>\n<pre class=\"theme:github nums:false lang:default decode:true \">SELECT Name FROM Account\r\nWHERE Id IN (SELECT AccountId FROM Contact)<\/pre>\n<p><span style=\"font-weight: 400;\"><br \/>\n<\/span><span style=\"font-weight: 400;\">\/\/ Accounts with NO contacts \u2014 data-quality gold<\/span><span style=\"font-weight: 400;\"><br \/>\n<\/span><\/p>\n<pre class=\"theme:github nums:false lang:default decode:true\">SELECT Name FROM Account\r\nWHERE Id NOT IN (SELECT AccountId FROM Contact)<\/pre>\n<p><span style=\"font-weight: 400;\">Limits: one semi-join or anti-join per query in most contexts, and the inner query can\u2019t use <\/span><span style=\"font-weight: 400;\">ORDER BY<\/span><span style=\"font-weight: 400;\"> or <\/span><span style=\"font-weight: 400;\">LIMIT<\/span><span style=\"font-weight: 400;\">.<\/span><\/p>\n<h2><b>Polymorphic Relationships<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Some fields point at more than one object: <\/span><span style=\"font-weight: 400;\">Task.WhoId<\/span><span style=\"font-weight: 400;\"> can be a Lead or Contact, <\/span><span style=\"font-weight: 400;\">Task.WhatId<\/span><span style=\"font-weight: 400;\"> an Account, Opportunity or Case.<\/span><\/p>\n<pre class=\"theme:github nums:false lang:default decode:true\">SELECT Subject, Who.Name, What.Name,\r\n\u00a0 \u00a0 \u00a0 TYPEOF What\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 WHEN Opportunity THEN Amount, StageName\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 WHEN Account \u00a0 \u00a0 THEN Industry\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ELSE Name\r\n\u00a0 \u00a0 \u00a0 END\r\nFROM Task<\/pre>\n<p><span style=\"font-weight: 400;\">TYPEOF<\/span><span style=\"font-weight: 400;\"> lets you pull different fields depending on the object type, in a single query.<\/span><\/p>\n<h2><b>Modern SOQL Most Tutorials Miss<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Three features that are genuinely current and rarely covered.<\/span><\/p>\n<h3><b>FIELDS()<\/b><b>: stop listing every field<\/b><\/h3>\n<pre class=\"theme:github nums:false lang:default decode:true\">SELECT FIELDS(STANDARD) FROM Account LIMIT 200\r\nSELECT FIELDS(CUSTOM) \u00a0 FROM Account LIMIT 200\r\nSELECT FIELDS(ALL)\u00a0 \u00a0 \u00a0 FROM Account LIMIT 200<\/pre>\n<p><span style=\"font-weight: 400;\">FIELDS(ALL)<\/span><span style=\"font-weight: 400;\"> and <\/span><span style=\"font-weight: 400;\">FIELDS(CUSTOM)<\/span><span style=\"font-weight: 400;\"> require a <\/span><span style=\"font-weight: 400;\">LIMIT<\/span><span style=\"font-weight: 400;\"> of 200 or fewer and don\u2019t work in Apex-bound queries in every context, but for dynamic and API use they remove a lot of brittle field lists.<\/span><\/p>\n<h3><b>WITH USER_MODE<\/b><b>: security in one clause<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">This is the one to adopt. Historically, you enforced object and field permissions manually or with <\/span><span style=\"font-weight: 400;\">WITH SECURITY_ENFORCED<\/span><span style=\"font-weight: 400;\">. Now:<\/span><\/p>\n<pre class=\"theme:github nums:false lang:default decode:true\">List&lt;Account&gt; accts = [\r\n\u00a0 \u00a0 SELECT Id, Name, AnnualRevenue\r\n\u00a0 \u00a0 FROM \u00a0 Account\r\n\u00a0 \u00a0 WITH \u00a0 USER_MODE\r\n];<\/pre>\n<p><span style=\"font-weight: 400;\">USER_MODE<\/span><span style=\"font-weight: 400;\"> enforces object permissions, field-level security, <\/span><b>and<\/b><span style=\"font-weight: 400;\"> sharing rules. <\/span><span style=\"font-weight: 400;\">SYSTEM_MODE<\/span><span style=\"font-weight: 400;\"> is the explicit opposite. It\u2019s clearer than <\/span><span style=\"font-weight: 400;\">SECURITY_ENFORCED<\/span><span style=\"font-weight: 400;\">, which only covered CRUD and FLS and threw on the whole query.<\/span><\/p>\n<h3><b>Database.queryWithBinds<\/b><b>: safe dynamic SOQL<\/b><\/h3>\n<pre class=\"theme:github nums:false lang:default decode:true\">Map&lt;String, Object&gt; binds = new Map&lt;String, Object&gt;{ 'ind' =&gt; industryValue };\r\nList&lt;Account&gt; accts = Database.queryWithBinds(\r\n\u00a0 \u00a0 'SELECT Id, Name FROM Account WHERE Industry = :ind',\r\n\u00a0 \u00a0 binds,\r\n\u00a0 \u00a0 AccessLevel.USER_MODE\r\n);<\/pre>\n<p><span style=\"font-weight: 400;\">This replaced the old pattern where dynamic queries silently picked up local variables. Bind maps are explicit, and you set the access level in the same call.<\/span><\/p>\n<h2><b>Dynamic SOQL and Preventing SOQL Injection<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Dynamic SOQL is a query built from a string at runtime; it\u2019s necessary sometimes and dangerous when careless.<\/span><\/p>\n<p><b>Unsafe, never do this:<\/b><\/p>\n<pre class=\"theme:github nums:false lang:default decode:true\">String q = 'SELECT Id FROM Account WHERE Name = \\'' + userInput + '\\'';\r\nList&lt;Account&gt; a = Database.query(q);<\/pre>\n<p><b>Safe, bind the variable:<\/b><\/p>\n<pre class=\"theme:github nums:false lang:default decode:true\">List&lt;Account&gt; a = [SELECT Id FROM Account WHERE Name = :userInput];<\/pre>\n<p><b>Safe when it must be dynamic:<\/b><\/p>\n<pre class=\"theme:github nums:false lang:default decode:true\">Map&lt;String, Object&gt; binds = new Map&lt;String, Object&gt;{ 'nm' =&gt; userInput };\r\nList&lt;Account&gt; a = Database.queryWithBinds(\r\n\u00a0 \u00a0 'SELECT Id FROM Account WHERE Name = :nm', binds, AccessLevel.USER_MODE);<\/pre>\n<p><b>If you genuinely must concatenate<\/b><span style=\"font-weight: 400;\">, for a field or object name, which can\u2019t be bound, use <\/span><span style=\"font-weight: 400;\">String.escapeSingleQuotes()<\/span><span style=\"font-weight: 400;\"> and validate the input against a known allowlist of field names. Escaping alone doesn\u2019t protect object or field positions.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">More on secure Apex: <\/span><span style=\"font-weight: 400;\">Apex programming guide<\/span><\/p>\n<div style=\"background: #EEF2FE; border: 1px solid #DBE2FB; border-radius: 14px; padding: 28px 32px; margin: 38px 0;\">\n<h4 style=\"color: #1b3fae; font-size: 22px; line-height: 1.3; font-weight: bold; margin: 0 0 10px;\"><span style=\"font-weight: 400;\"><b>Inherited an org full of dynamic SOQL? <\/b><\/span><\/h4>\n<p style=\"color: #4b5563; font-size: 16px; line-height: 1.6; margin: 0 0 22px;\"><span style=\"font-weight: 400;\">Unbound dynamic queries are one of the most common findings in the org audits we run and one of the easiest to exploit.<\/span><\/p>\n<p><a style=\"display: inline-block; background: #2563EB; color: #ffffff; text-decoration: none; font-size: 15px; font-weight: 600; padding: 13px 26px; border-radius: 8px;\" href=\"https:\/\/dianapps.com\/salesforce-development-services?utm\\_source=blog\\&amp;utm\\_medium=cta\\&amp;utm\\_campaign=ai-dev-cost\\&amp;utm\\_content=cta5\">Talk to our Salesforce development team \u2192<\/a><\/p>\n<\/div>\n<p>&nbsp;<\/p>\n<h2><b>Query Performance, Selectivity and Indexes<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">A query is <\/span><b>selective<\/b><span style=\"font-weight: 400;\"> when its filters use an indexed field and return a small enough proportion of the object. Non-selective queries against large objects fail outright once you pass roughly a million records.<\/span><\/p>\n<p><b>Indexed By Default:<\/b> <span style=\"font-weight: 400;\">Id<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">Name<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">OwnerId<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">CreatedDate<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">SystemModstamp<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">RecordTypeId<\/span><span style=\"font-weight: 400;\">, master-detail and lookup fields, and any field marked External ID or Unique.<\/span><\/p>\n<p><b>What kills selectivity:<\/b><\/p>\n\n<table id=\"tablepress-243\" class=\"tablepress tablepress-id-243\">\n<thead>\n<tr class=\"row-1\">\n\t<th class=\"column-1\">Anti-pattern<\/th><th class=\"column-2\">Why it hurts<\/th><th class=\"column-3\">Do instead<\/th>\n<\/tr>\n<\/thead>\n<tbody class=\"row-striping row-hover\">\n<tr class=\"row-2\">\n\t<td class=\"column-1\">WHERE Name LIKE '%acme'<\/td><td class=\"column-2\">Leading wildcard can\u2019t use an index<\/td><td class=\"column-3\">Trailing wildcard or SOSL<\/td>\n<\/tr>\n<tr class=\"row-3\">\n\t<td class=\"column-1\">WHERE Status__c != 'Closed'<\/td><td class=\"column-2\">Negative filters aren\u2019t selective<\/td><td class=\"column-3\">Positive IN list<\/td>\n<\/tr>\n<tr class=\"row-4\">\n\t<td class=\"column-1\">WHERE Field__c = NULL<\/td><td class=\"column-2\">Nulls aren\u2019t indexed by default<\/td><td class=\"column-3\">Restructure or ask Support to index nulls<\/td>\n<\/tr>\n<tr class=\"row-5\">\n\t<td class=\"column-1\">Formula fields in WHERE<\/td><td class=\"column-2\">Usually not indexed<\/td><td class=\"column-3\">Store the value in a real field<\/td>\n<\/tr>\n<tr class=\"row-6\">\n\t<td class=\"column-1\">OR across different fields<\/td><td class=\"column-2\">Often forces a full scan<\/td><td class=\"column-3\">Split into two queries<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<!-- #tablepress-243 from cache -->\n<p><b>Use the Query Plan Tool:<\/b><span style=\"font-weight: 400;\"> In Developer Console, enable Query Plan under Help \u2192 Preferences, then run your query. A cost below 1.0 means the optimiser is using an index. Anything above that is a table scan waiting to become an incident.<\/span><\/p>\n<p><b>Custom Indexes:<\/b><span style=\"font-weight: 400;\"> Can be requested from Salesforce Support for fields you filter on constantly. <\/span><b>Skinny Tables<\/b><span style=\"font-weight: 400;\">: Are the next step for very large objects, also Support-provisioned.<\/span><\/p>\n<h2><b>Governor Limits on Queries<\/b><\/h2>\n<p><i><span style=\"font-weight: 400;\">Table of Salesforce query governor limits including 100 SOQL queries, 50000 records, 20 SOSL searches, 2000 SOSL records and relationship traversal depth<\/span><\/i><\/p>\n<h3><b>The mistake behind most limit failures<\/b><\/h3>\n<pre class=\"theme:github nums:false lang:default decode:true \">\/\/ \u2717 200 contacts = 200 queries = failure at 100\r\nfor (Contact c : contactList) {\r\n\u00a0 \u00a0 Account a = [SELECT Name FROM Account WHERE Id = :c.AccountId];\r\n}\r\n\r\n\/\/ \u2713 One query, any volume\r\nSet&lt;Id&gt; accountIds = new Set&lt;Id&gt;();\r\nfor (Contact c : contactList) {\r\n\u00a0 \u00a0 accountIds.add(c.AccountId);\r\n}\r\nMap&lt;Id, Account&gt; accountMap = new Map&lt;Id, Account&gt;([\r\n\u00a0 \u00a0 SELECT Id, Name FROM Account WHERE Id IN :accountIds\r\n]);<\/pre>\n<p>&nbsp;<\/p>\n<h3><b>Querying more than 50,000 records<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">A SOQL for-loop processes results in batches of 200 and keeps heap under control:<\/span><\/p>\n<pre class=\"theme:github nums:false lang:default decode:true\">for (List&lt;Account&gt; batch : [SELECT Id, Name FROM Account WHERE Industry = 'Banking']) {\r\n\u00a0 \u00a0 for (Account a : batch) {\r\n\u00a0 \u00a0 \u00a0 \u00a0 \/\/ process\r\n\u00a0 \u00a0 }\r\n}<\/pre>\n<p><span style=\"font-weight: 400;\">Beyond that, use Batch Apex with a <\/span><span style=\"font-weight: 400;\">QueryLocator<\/span><span style=\"font-weight: 400;\">, which handles up to 50 million records.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Queries aren\u2019t only in Apex.<\/span><\/p>\n<p><b>Get Records<\/b><span style=\"font-weight: 400;\"> elements in <\/span><span style=\"font-weight: 400;\">Salesforce Flow<\/span><span style=\"font-weight: 400;\"> issue SOQL too, and they draw on the same 100-query budget; a Flow and a trigger firing on the same record share one transaction. If you\u2019re weighing where logic should live, <\/span><span style=\"font-weight: 400;\">Flow vs Apex<\/span><span style=\"font-weight: 400;\"> covers the trade-off.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Full reference: <\/span><span style=\"font-weight: 400;\">Salesforce governor limits<\/span><\/p>\n<h2><b>SOSL: Searching Text Across Objects<\/b><\/h2>\n<pre class=\"theme:github nums:false lang:default decode:true\">FIND 'Acme' IN ALL FIELDS\r\nRETURNING Account(Id, Name),\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Contact(Id, FirstName, LastName),\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Case(Id, Subject)\r\nLIMIT 50\r\n\r\nIn Apex, results come back as a list of lists in the order you declared:\r\n\r\nList&lt;List&lt;SObject&gt;&gt; results = [\r\n\u00a0 \u00a0 FIND :searchTerm IN NAME FIELDS\r\n\u00a0 \u00a0 RETURNING Account(Id, Name), Contact(Id, Name)\r\n];\r\nList&lt;Account&gt; accounts = (List&lt;Account&gt;) results[0];\r\nList&lt;Contact&gt; contacts = (List&lt;Contact&gt;) results[1];<\/pre>\n<p><b>Search scopes<\/b><span style=\"font-weight: 400;\">\u00a0narrower is faster and more relevant:<\/span><\/p>\n\n<table id=\"tablepress-244\" class=\"tablepress tablepress-id-244\">\n<thead>\n<tr class=\"row-1\">\n\t<th class=\"column-1\">Scope<\/th><th class=\"column-2\">Searches<\/th>\n<\/tr>\n<\/thead>\n<tbody class=\"row-striping row-hover\">\n<tr class=\"row-2\">\n\t<td class=\"column-1\">IN ALL FIELDS<\/td><td class=\"column-2\">Every searchable field<\/td>\n<\/tr>\n<tr class=\"row-3\">\n\t<td class=\"column-1\">IN NAME FIELDS<\/td><td class=\"column-2\">Name fields only, usually what you want<\/td>\n<\/tr>\n<tr class=\"row-4\">\n\t<td class=\"column-1\">IN EMAIL FIELDS<\/td><td class=\"column-2\">Email fields<\/td>\n<\/tr>\n<tr class=\"row-5\">\n\t<td class=\"column-1\">IN PHONE FIELDS<\/td><td class=\"column-2\">Phone fields<\/td>\n<\/tr>\n<tr class=\"row-6\">\n\t<td class=\"column-1\">IN SIDEBAR FIELDS<\/td><td class=\"column-2\">Fields in the standard search sidebar<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<!-- #tablepress-244 from cache -->\n<p>&nbsp;<\/p>\n<p><b>Two behaviours that confuse people:<\/b><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>The Search Index Lags:<\/b><span style=\"font-weight: 400;\"> SOSL reads an index that updates shortly after a record changes, not instantly. A record created milliseconds earlier in a test may not be findable.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">This is expected; in test classes, use <\/span><span style=\"font-weight: 400;\">Test.setFixedSearchResults()<\/span><span style=\"font-weight: 400;\"> rather than relying on the index.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Wildcards Behave Differently:<\/b><span style=\"font-weight: 400;\"> SOSL supports <\/span><span style=\"font-weight: 400;\">*<\/span><span style=\"font-weight: 400;\"> and <\/span><span style=\"font-weight: 400;\">?,<\/span><span style=\"font-weight: 400;\"> and unlike SOQL\u2019s <\/span><span style=\"font-weight: 400;\">LIKE<\/span><span style=\"font-weight: 400;\">, a leading wildcard is workable because it\u2019s a text index rather than a database scan.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>When Not To Use SOSL:<\/b><span style=\"font-weight: 400;\"> you know the object, you need precise filtering, you need aggregates, or you need more than 2,000 results.<\/span><\/li>\n<\/ul>\n<h2><b>How to Test Queries<\/b><\/h2>\n<p><b>Developer Console \u2192 Query Editor<\/b><span style=\"font-weight: 400;\"> for quick iteration and the Query Plan tool.<\/span><\/p>\n<p><b>Anonymous Apex<\/b><span style=\"font-weight: 400;\"> when you need to see how results behave in code.<\/span><\/p>\n<p><b>Test classes<\/b><span style=\"font-weight: 400;\"> and the two rules that matter: use <\/span><span style=\"font-weight: 400;\">@testSetup<\/span><span style=\"font-weight: 400;\"> to build data once per class and never rely on org data. Tests run without seeing existing records unless annotated <\/span><span style=\"font-weight: 400;\">@isTest(SeeAllData=true)<\/span><span style=\"font-weight: 400;\">, which you should avoid.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">For SOSL in tests, the index doesn\u2019t run, so:<\/span><\/p>\n<pre class=\"theme:github nums:false lang:default decode:true \">Id[] fixedResults = new Id[]{ testAccount.Id };\r\nTest.setFixedSearchResults(fixedResults);<\/pre>\n<p><span style=\"font-weight: 400;\">Related: <\/span><span style=\"font-weight: 400;\">Apex testing and DevOps practices<\/span><\/p>\n<h2><b>Common SOQL and SOSL Mistakes<\/b><\/h2>\n<ol>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>SOQL inside a loop<\/b><span style=\"font-weight: 400;\">\u00a0the single most common cause of limit failures<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>No <\/b><b>WHERE<\/b><b> clause<\/b><span style=\"font-weight: 400;\"> on a large object<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Selecting fields you don\u2019t use;<\/b><span style=\"font-weight: 400;\">\u00a0heap you didn\u2019t need<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Guessing the child relationship name<\/b><span style=\"font-weight: 400;\"> instead of checking Object Manager<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>String concatenation in dynamic SOQL<\/b><span style=\"font-weight: 400;\"> instead of bind variables<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Leading wildcards<\/b><span style=\"font-weight: 400;\"> in <\/span><span style=\"font-weight: 400;\">LIKE<\/span><span style=\"font-weight: 400;\"> filters<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Assuming <\/b><b>SELECT<\/b><b> returns a list of one<\/b><span style=\"font-weight: 400;\">\u00a0<\/span><span style=\"font-weight: 400;\">Trigger.new[0]<\/span><span style=\"font-weight: 400;\"> thinking<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Ignoring FLS:<\/b><span style=\"font-weight: 400;\">\u00a0no <\/span><span style=\"font-weight: 400;\">USER_MODE<\/span><span style=\"font-weight: 400;\">, no manual enforcement<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Using SOSL where SOQL is correct<\/b><span style=\"font-weight: 400;\"> and hitting the 2,000 cap<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>OFFSET<\/b><b> for deep paging<\/b><span style=\"font-weight: 400;\"> rather than filtering on the last sort value<\/span><\/li>\n<\/ol>\n<h2><b>Practise These<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Work through these against a dev org; they cover most of what appears in real code and in interviews:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Opportunities grouped by stage with a total amount, filtered to this fiscal year<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Every account with no related contacts<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">A parent-to-child query on two custom objects, using the correct <\/span><span style=\"font-weight: 400;\">__r<\/span><span style=\"font-weight: 400;\"> name<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Rewrite an unsafe dynamic query using <\/span><span style=\"font-weight: 400;\">Database.queryWithBinds<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">A SOSL search across three objects, restricted to name fields<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">A query that returns more than 50,000 records without failing<\/span><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<style>.elementor-19779 .elementor-element.elementor-element-2932a52{text-align:left;}.elementor-19779 .elementor-element.elementor-element-2932a52 > .elementor-widget-container{margin:0px 0px 0px 0px;}.elementor-19779 .elementor-element.elementor-element-0b767d1 .elementor-tab-title{border-width:1px;border-color:#00000014;}.elementor-19779 .elementor-element.elementor-element-0b767d1 .elementor-tab-content{border-width:1px;border-bottom-color:#00000014;}.elementor-19779 .elementor-element.elementor-element-0b767d1 > .elementor-widget-container{margin:0px 0px 0px 0px;}<\/style><div class=\"porto-block elementor elementor-19779\">\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-27707ca elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"27707ca\" data-element_type=\"section\">\r\n\t\t\t\r\n\t\t\t\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\r\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-0163611\" data-id=\"0163611\" data-element_type=\"column\">\r\n\r\n\t\t\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\r\n\t\t\t\t\t\t\t\t<div class=\"elementor-element elementor-element-03a2969 elementor-widget elementor-widget-text-editor\" data-id=\"03a2969\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<style>\/*! elementor - v3.14.0 - 26-06-2023 *\/\n.elementor-widget-text-editor.elementor-drop-cap-view-stacked .elementor-drop-cap{background-color:#69727d;color:#fff}.elementor-widget-text-editor.elementor-drop-cap-view-framed .elementor-drop-cap{color:#69727d;border:3px solid;background-color:transparent}.elementor-widget-text-editor:not(.elementor-drop-cap-view-default) .elementor-drop-cap{margin-top:8px}.elementor-widget-text-editor:not(.elementor-drop-cap-view-default) .elementor-drop-cap-letter{width:1em;height:1em}.elementor-widget-text-editor .elementor-drop-cap{float:left;text-align:center;line-height:1;font-size:50px}.elementor-widget-text-editor .elementor-drop-cap-letter{display:inline-block}<\/style>\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2932a52 elementor-widget elementor-widget-heading\" data-id=\"2932a52\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<style>\/*! elementor - v3.14.0 - 26-06-2023 *\/\n.elementor-heading-title{padding:0;margin:0;line-height:1}.elementor-widget-heading .elementor-heading-title[class*=elementor-size-]>a{color:inherit;font-size:inherit;line-height:inherit}.elementor-widget-heading .elementor-heading-title.elementor-size-small{font-size:15px}.elementor-widget-heading .elementor-heading-title.elementor-size-medium{font-size:19px}.elementor-widget-heading .elementor-heading-title.elementor-size-large{font-size:29px}.elementor-widget-heading .elementor-heading-title.elementor-size-xl{font-size:39px}.elementor-widget-heading .elementor-heading-title.elementor-size-xxl{font-size:59px}<\/style><h2 class=\"elementor-heading-title elementor-size-large\">FAQs <\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-0b767d1 elementor-widget elementor-widget-toggle\" data-id=\"0b767d1\" data-element_type=\"widget\" data-widget_type=\"toggle.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<style>\/*! elementor - v3.14.0 - 26-06-2023 *\/\n.elementor-toggle{text-align:left}.elementor-toggle .elementor-tab-title{font-weight:700;line-height:1;margin:0;padding:15px;border-bottom:1px solid #d5d8dc;cursor:pointer;outline:none}.elementor-toggle .elementor-tab-title .elementor-toggle-icon{display:inline-block;width:1em}.elementor-toggle .elementor-tab-title .elementor-toggle-icon svg{-webkit-margin-start:-5px;margin-inline-start:-5px;width:1em;height:1em}.elementor-toggle .elementor-tab-title .elementor-toggle-icon.elementor-toggle-icon-right{float:right;text-align:right}.elementor-toggle .elementor-tab-title .elementor-toggle-icon.elementor-toggle-icon-left{float:left;text-align:left}.elementor-toggle .elementor-tab-title .elementor-toggle-icon .elementor-toggle-icon-closed{display:block}.elementor-toggle .elementor-tab-title .elementor-toggle-icon .elementor-toggle-icon-opened{display:none}.elementor-toggle .elementor-tab-title.elementor-active{border-bottom:none}.elementor-toggle .elementor-tab-title.elementor-active .elementor-toggle-icon-closed{display:none}.elementor-toggle .elementor-tab-title.elementor-active .elementor-toggle-icon-opened{display:block}.elementor-toggle .elementor-tab-content{padding:15px;border-bottom:1px solid #d5d8dc;display:none}@media (max-width:767px){.elementor-toggle .elementor-tab-title{padding:12px}.elementor-toggle .elementor-tab-content{padding:12px 10px}}.e-con-inner>.elementor-widget-toggle,.e-con>.elementor-widget-toggle{width:var(--container-widget-width);--flex-grow:var(--container-widget-flex-grow)}<\/style>\t\t<div class=\"elementor-toggle\">\n\t\t\t\t\t\t\t<div class=\"elementor-toggle-item\">\n\t\t\t\t\t<h3 id=\"elementor-tab-title-1201\" class=\"elementor-tab-title\" data-tab=\"1\" role=\"button\" aria-controls=\"elementor-tab-content-1201\" aria-expanded=\"false\">\n\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-toggle-icon elementor-toggle-icon-left\" aria-hidden=\"true\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-toggle-icon-closed\"><i class=\"fas fa-caret-right\"><\/i><\/span>\n\t\t\t\t\t\t\t\t<span class=\"elementor-toggle-icon-opened\"><i class=\"elementor-toggle-icon-opened fas fa-caret-up\"><\/i><\/span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t\t\t\t<a class=\"elementor-toggle-title\" tabindex=\"0\">What is the difference between SOQL and SOSL?<\/a>\n\t\t\t\t\t<\/h3>\n\n\t\t\t\t\t<div id=\"elementor-tab-content-1201\" class=\"elementor-tab-content elementor-clearfix\" data-tab=\"1\" role=\"region\" aria-labelledby=\"elementor-tab-title-1201\"><p><span style=\"font-weight: 400;\">SOQL retrieves structured records from a single object and its relationships, with precise filtering and aggregates. SOSL performs keyword text search across multiple objects at once. Use SOQL when you know the object; use SOSL when you\u2019re searching for text and don\u2019t.<\/span><\/p><\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t\t<div class=\"elementor-toggle-item\">\n\t\t\t\t\t<h3 id=\"elementor-tab-title-1202\" class=\"elementor-tab-title\" data-tab=\"2\" role=\"button\" aria-controls=\"elementor-tab-content-1202\" aria-expanded=\"false\">\n\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-toggle-icon elementor-toggle-icon-left\" aria-hidden=\"true\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-toggle-icon-closed\"><i class=\"fas fa-caret-right\"><\/i><\/span>\n\t\t\t\t\t\t\t\t<span class=\"elementor-toggle-icon-opened\"><i class=\"elementor-toggle-icon-opened fas fa-caret-up\"><\/i><\/span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t\t\t\t<a class=\"elementor-toggle-title\" tabindex=\"0\">Can SOQL update records?<\/a>\n\t\t\t\t\t<\/h3>\n\n\t\t\t\t\t<div id=\"elementor-tab-content-1202\" class=\"elementor-tab-content elementor-clearfix\" data-tab=\"2\" role=\"region\" aria-labelledby=\"elementor-tab-title-1202\"><p><span style=\"font-weight: 400;\">No, SOQL is read-only. Retrieve records with SOQL, then modify them with DML statements: <\/span><span style=\"font-weight: 400;\">insert<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">update<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">upsert<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">delete<\/span><span style=\"font-weight: 400;\">.<\/span><\/p><\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t\t<div class=\"elementor-toggle-item\">\n\t\t\t\t\t<h3 id=\"elementor-tab-title-1203\" class=\"elementor-tab-title\" data-tab=\"3\" role=\"button\" aria-controls=\"elementor-tab-content-1203\" aria-expanded=\"false\">\n\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-toggle-icon elementor-toggle-icon-left\" aria-hidden=\"true\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-toggle-icon-closed\"><i class=\"fas fa-caret-right\"><\/i><\/span>\n\t\t\t\t\t\t\t\t<span class=\"elementor-toggle-icon-opened\"><i class=\"elementor-toggle-icon-opened fas fa-caret-up\"><\/i><\/span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t\t\t\t<a class=\"elementor-toggle-title\" tabindex=\"0\">How many SOQL queries can you run in one transaction?<\/a>\n\t\t\t\t\t<\/h3>\n\n\t\t\t\t\t<div id=\"elementor-tab-content-1203\" class=\"elementor-tab-content elementor-clearfix\" data-tab=\"3\" role=\"region\" aria-labelledby=\"elementor-tab-title-1203\"><p><span style=\"font-weight: 400;\">100 in a synchronous transaction<\/span><span style=\"font-weight: 400;\"> and 200 in an asynchronous one, returning a maximum of 50,000 records. SOSL allows 20 searches returning up to 2,000 records.<\/span><\/p><\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t\t<div class=\"elementor-toggle-item\">\n\t\t\t\t\t<h3 id=\"elementor-tab-title-1204\" class=\"elementor-tab-title\" data-tab=\"4\" role=\"button\" aria-controls=\"elementor-tab-content-1204\" aria-expanded=\"false\">\n\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-toggle-icon elementor-toggle-icon-left\" aria-hidden=\"true\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-toggle-icon-closed\"><i class=\"fas fa-caret-right\"><\/i><\/span>\n\t\t\t\t\t\t\t\t<span class=\"elementor-toggle-icon-opened\"><i class=\"elementor-toggle-icon-opened fas fa-caret-up\"><\/i><\/span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t\t\t\t<a class=\"elementor-toggle-title\" tabindex=\"0\">How many relationship levels can SOQL traverse?<\/a>\n\t\t\t\t\t<\/h3>\n\n\t\t\t\t\t<div id=\"elementor-tab-content-1204\" class=\"elementor-tab-content elementor-clearfix\" data-tab=\"4\" role=\"region\" aria-labelledby=\"elementor-tab-title-1204\"><p><span style=\"font-weight: 400;\">Five levels from child to parent using dot notation and one level from parent to child using a subquery. You can include up to 20 subqueries in a single query.<\/span><\/p><\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t\t<div class=\"elementor-toggle-item\">\n\t\t\t\t\t<h3 id=\"elementor-tab-title-1205\" class=\"elementor-tab-title\" data-tab=\"5\" role=\"button\" aria-controls=\"elementor-tab-content-1205\" aria-expanded=\"false\">\n\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-toggle-icon elementor-toggle-icon-left\" aria-hidden=\"true\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-toggle-icon-closed\"><i class=\"fas fa-caret-right\"><\/i><\/span>\n\t\t\t\t\t\t\t\t<span class=\"elementor-toggle-icon-opened\"><i class=\"elementor-toggle-icon-opened fas fa-caret-up\"><\/i><\/span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t\t\t\t<a class=\"elementor-toggle-title\" tabindex=\"0\">How do you prevent SOQL injection?<\/a>\n\t\t\t\t\t<\/h3>\n\n\t\t\t\t\t<div id=\"elementor-tab-content-1205\" class=\"elementor-tab-content elementor-clearfix\" data-tab=\"5\" role=\"region\" aria-labelledby=\"elementor-tab-title-1205\"><p><span style=\"font-weight: 400;\">Use bind variables <\/span><span style=\"font-weight: 400;\">WHERE Name = :userInput,<\/span><span style=\"font-weight: 400;\"> which is the default in inline SOQL. For dynamic queries, use <\/span><span style=\"font-weight: 400;\">Database.queryWithBinds<\/span><span style=\"font-weight: 400;\"> with a bind map. If you must concatenate a field or object name, validate against an allowlist, because <\/span><span style=\"font-weight: 400;\">String.escapeSingleQuotes()<\/span><span style=\"font-weight: 400;\"> doesn\u2019t protect those positions.<\/span><\/p><\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t\t<div class=\"elementor-toggle-item\">\n\t\t\t\t\t<h3 id=\"elementor-tab-title-1206\" class=\"elementor-tab-title\" data-tab=\"6\" role=\"button\" aria-controls=\"elementor-tab-content-1206\" aria-expanded=\"false\">\n\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-toggle-icon elementor-toggle-icon-left\" aria-hidden=\"true\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-toggle-icon-closed\"><i class=\"fas fa-caret-right\"><\/i><\/span>\n\t\t\t\t\t\t\t\t<span class=\"elementor-toggle-icon-opened\"><i class=\"elementor-toggle-icon-opened fas fa-caret-up\"><\/i><\/span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t\t\t\t<a class=\"elementor-toggle-title\" tabindex=\"0\">What makes a SOQL query selective?<\/a>\n\t\t\t\t\t<\/h3>\n\n\t\t\t\t\t<div id=\"elementor-tab-content-1206\" class=\"elementor-tab-content elementor-clearfix\" data-tab=\"6\" role=\"region\" aria-labelledby=\"elementor-tab-title-1206\"><p><span style=\"font-weight: 400;\">Filtering on an indexed field that returns a small enough share of the object. <\/span><span style=\"font-weight: 400;\">Id<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">Name<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">OwnerId<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">CreatedDate<\/span><span style=\"font-weight: 400;\">, lookups, and External ID or Unique fields are indexed by default. Check with the Query Plan tool; a cost below 1.0 means an index is being used.<\/span><\/p><h3>\u00a0<\/h3><\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t\t<div class=\"elementor-toggle-item\">\n\t\t\t\t\t<h3 id=\"elementor-tab-title-1207\" class=\"elementor-tab-title\" data-tab=\"7\" role=\"button\" aria-controls=\"elementor-tab-content-1207\" aria-expanded=\"false\">\n\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-toggle-icon elementor-toggle-icon-left\" aria-hidden=\"true\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-toggle-icon-closed\"><i class=\"fas fa-caret-right\"><\/i><\/span>\n\t\t\t\t\t\t\t\t<span class=\"elementor-toggle-icon-opened\"><i class=\"elementor-toggle-icon-opened fas fa-caret-up\"><\/i><\/span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t\t\t\t<a class=\"elementor-toggle-title\" tabindex=\"0\">What is WITH USER_MODE in SOQL?<\/a>\n\t\t\t\t\t<\/h3>\n\n\t\t\t\t\t<div id=\"elementor-tab-content-1207\" class=\"elementor-tab-content elementor-clearfix\" data-tab=\"7\" role=\"region\" aria-labelledby=\"elementor-tab-title-1207\"><p><span style=\"font-weight: 400;\">A clause that enforces object permissions, field-level security, and sharing rules for the running user in one line. It replaces manual CRUD\/FLS checks and is clearer than the older <\/span><span style=\"font-weight: 400;\">WITH SECURITY_ENFORCED<\/span><span style=\"font-weight: 400;\">, which covered CRUD and FLS but not sharing.<\/span><\/p><\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t\t\t<script type=\"application\/ld+json\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@type\":\"FAQPage\",\"mainEntity\":[{\"@type\":\"Question\",\"name\":\"What is the difference between SOQL and SOSL?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"<p><span style=\\\"font-weight: 400;\\\">SOQL retrieves structured records from a single object and its relationships, with precise filtering and aggregates. SOSL performs keyword text search across multiple objects at once. Use SOQL when you know the object; use SOSL when you\\u2019re searching for text and don\\u2019t.<\\\/span><\\\/p>\"}},{\"@type\":\"Question\",\"name\":\"Can SOQL update records?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"<p><span style=\\\"font-weight: 400;\\\">No, SOQL is read-only. Retrieve records with SOQL, then modify them with DML statements: <\\\/span><span style=\\\"font-weight: 400;\\\">insert<\\\/span><span style=\\\"font-weight: 400;\\\">, <\\\/span><span style=\\\"font-weight: 400;\\\">update<\\\/span><span style=\\\"font-weight: 400;\\\">, <\\\/span><span style=\\\"font-weight: 400;\\\">upsert<\\\/span><span style=\\\"font-weight: 400;\\\">, <\\\/span><span style=\\\"font-weight: 400;\\\">delete<\\\/span><span style=\\\"font-weight: 400;\\\">.<\\\/span><\\\/p>\"}},{\"@type\":\"Question\",\"name\":\"How many SOQL queries can you run in one transaction?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"<p><span style=\\\"font-weight: 400;\\\">100 in a synchronous transaction<\\\/span><span style=\\\"font-weight: 400;\\\"> and 200 in an asynchronous one, returning a maximum of 50,000 records. SOSL allows 20 searches returning up to 2,000 records.<\\\/span><\\\/p>\"}},{\"@type\":\"Question\",\"name\":\"How many relationship levels can SOQL traverse?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"<p><span style=\\\"font-weight: 400;\\\">Five levels from child to parent using dot notation and one level from parent to child using a subquery. You can include up to 20 subqueries in a single query.<\\\/span><\\\/p>\"}},{\"@type\":\"Question\",\"name\":\"How do you prevent SOQL injection?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"<p><span style=\\\"font-weight: 400;\\\">Use bind variables <\\\/span><span style=\\\"font-weight: 400;\\\">WHERE Name = :userInput,<\\\/span><span style=\\\"font-weight: 400;\\\"> which is the default in inline SOQL. For dynamic queries, use <\\\/span><span style=\\\"font-weight: 400;\\\">Database.queryWithBinds<\\\/span><span style=\\\"font-weight: 400;\\\"> with a bind map. If you must concatenate a field or object name, validate against an allowlist, because <\\\/span><span style=\\\"font-weight: 400;\\\">String.escapeSingleQuotes()<\\\/span><span style=\\\"font-weight: 400;\\\"> doesn\\u2019t protect those positions.<\\\/span><\\\/p>\"}},{\"@type\":\"Question\",\"name\":\"What makes a SOQL query selective?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"<p><span style=\\\"font-weight: 400;\\\">Filtering on an indexed field that returns a small enough share of the object. <\\\/span><span style=\\\"font-weight: 400;\\\">Id<\\\/span><span style=\\\"font-weight: 400;\\\">, <\\\/span><span style=\\\"font-weight: 400;\\\">Name<\\\/span><span style=\\\"font-weight: 400;\\\">, <\\\/span><span style=\\\"font-weight: 400;\\\">OwnerId<\\\/span><span style=\\\"font-weight: 400;\\\">, <\\\/span><span style=\\\"font-weight: 400;\\\">CreatedDate<\\\/span><span style=\\\"font-weight: 400;\\\">, lookups, and External ID or Unique fields are indexed by default. Check with the Query Plan tool; a cost below 1.0 means an index is being used.<\\\/span><\\\/p><h3>\\u00a0<\\\/h3>\"}},{\"@type\":\"Question\",\"name\":\"What is WITH USER_MODE in SOQL?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"<p><span style=\\\"font-weight: 400;\\\">A clause that enforces object permissions, field-level security, and sharing rules for the running user in one line. It replaces manual CRUD\\\/FLS checks and is clearer than the older <\\\/span><span style=\\\"font-weight: 400;\\\">WITH SECURITY_ENFORCED<\\\/span><span style=\\\"font-weight: 400;\\\">, which covered CRUD and FLS but not sharing.<\\\/span><\\\/p>\"}}]}<\/script>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\r\n\t\t\t\t<\/div>\r\n\t\t\t\t\t\t<\/div>\r\n\t\t\t\t<\/section>\r\n\t\t<\/div>\n<p>&nbsp;<\/p>\n<h2><b>Where to Go Next<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">For the language SOQL runs inside, see the <\/span><span style=\"font-weight: 400;\">Apex programming guide<\/span><span style=\"font-weight: 400;\">. For the limits that shape every query decision, see <\/span><span style=\"font-weight: 400;\">governor limits<\/span><span style=\"font-weight: 400;\">. For how objects and relationships are structured in the first place, see <\/span><span style=\"font-weight: 400;\">the Salesforce data model<\/span><span style=\"font-weight: 400;\">.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">If you\u2019re calling SOQL from the front end, <\/span><span style=\"font-weight: 400;\">Lightning Web Components<\/span><span style=\"font-weight: 400;\"> covers the wire service. If you\u2019re querying from outside the platform, <\/span><span style=\"font-weight: 400;\">Salesforce API integration<\/span><span style=\"font-weight: 400;\"> covers REST, Bulk, and the Pub\/Sub API.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">For the wider picture, the <\/span><span style=\"font-weight: 400;\">complete <a href=\"https:\/\/dianapps.com\/blog\/salesforce-development-guide\/\">Salesforce development guide<\/a><\/span><span style=\"font-weight: 400;\"> is the hub for all of it.<\/span><\/p>\n<h2><b>When Queries Become an Architecture Problem<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Most query problems are fixable by one developer in an afternoon. Some aren\u2019t.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">If your org is hitting limit exceptions in production, if reports time out, or if nobody is certain which of your dynamic queries are safely bound, that\u2019s usually a symptom of something structural rather than a bad query.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">We\u2019re a certified Salesforce Consulting Partner, and our engineers spend a good deal of their time in orgs exactly like that, finding the non-selective queries, the unbound dynamic SOQL, and the triggers quietly querying inside loops.<\/span><\/p>\n<p><a href=\"https:\/\/dianapps.com\/salesforce-development-services\"><b>Explore our Salesforce development services \u2192<\/b><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A query that works is not the same as a query that scales. The trigger that queries inside a loop runs fine against ten test records and fails the moment someone imports fifty thousand. That gap between correct and production-ready is most of what separates developers who spend their weeks building from developers who spend [&hellip;]<\/p>\n","protected":false},"author":15,"featured_media":19792,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_yoast_wpseo_meta-robots-noindex":"","_yoast_wpseo_meta-robots-nofollow":"","_yoast_wpseo_canonical":"","_yoast_wpseo_opengraph-title":"","_yoast_wpseo_opengraph-description":"","_yoast_wpseo_opengraph-image":"","_yoast_wpseo_twitter-title":"","_yoast_wpseo_twitter-description":"","_yoast_wpseo_twitter-image":"","_wp_applaud_exclude":false,"footnotes":""},"categories":[85],"tags":[2570,133,2566,2567,2565,2560,2561,2571,2558,2557,2563,2568,2562,2559,2564,2569],"class_list":["post-19776","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-salesforce","tag-apex-soql","tag-salesforce-developer","tag-salesforce-governor-limits","tag-salesforce-query-language","tag-salesforce-relationship-queries","tag-salesforce-soql","tag-salesforce-sosl","tag-salesforce-tutorial","tag-soql","tag-soql-and-sosl-in-salesforce","tag-soql-query-examples","tag-soql-syntax","tag-soql-vs-sosl","tag-sosl","tag-sosl-query-examples","tag-sosl-syntax"],"featured_image_src":{"landsacpe":["https:\/\/dianapps.com\/blog\/wp-content\/uploads\/2026\/08\/Untitled-design-66-1140x445.webp",1140,445,true],"list":["https:\/\/dianapps.com\/blog\/wp-content\/uploads\/2026\/08\/Untitled-design-66-463x348.webp",463,348,true],"medium":["https:\/\/dianapps.com\/blog\/wp-content\/uploads\/2026\/08\/Untitled-design-66-300x169.webp",300,169,true],"full":["https:\/\/dianapps.com\/blog\/wp-content\/uploads\/2026\/08\/Untitled-design-66.webp",1536,864,false]},"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>SOQL and SOSL in Salesforce: Complete Guide With Examples<\/title>\n<meta name=\"description\" content=\"SOQL and SOSL in Salesforce explained with real-world examples, relationship queries, governor limits, and best practices to write efficient, high-performing Salesforce queries.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/dianapps.com\/blog\/soql-and-sosl-in-salesforce\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"SOQL and SOSL in Salesforce: Complete Guide With Examples\" \/>\n<meta property=\"og:description\" content=\"SOQL and SOSL in Salesforce explained with real-world examples, relationship queries, governor limits, and best practices to write efficient, high-performing Salesforce queries.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/dianapps.com\/blog\/soql-and-sosl-in-salesforce\/\" \/>\n<meta property=\"og:site_name\" content=\"Learn About Digital Transformation &amp; Development | DianApps Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-08-06T12:00:13+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-08-09T15:27:10+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/dianapps.com\/blog\/wp-content\/uploads\/2026\/08\/Untitled-design-66.webp\" \/>\n\t<meta property=\"og:image:width\" content=\"1536\" \/>\n\t<meta property=\"og:image:height\" content=\"864\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/webp\" \/>\n<meta name=\"author\" content=\"Vaibhav Sharma\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Vaibhav Sharma\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"SOQL and SOSL in Salesforce: Complete Guide With Examples","description":"SOQL and SOSL in Salesforce explained with real-world examples, relationship queries, governor limits, and best practices to write efficient, high-performing Salesforce queries.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/dianapps.com\/blog\/soql-and-sosl-in-salesforce\/","og_locale":"en_US","og_type":"article","og_title":"SOQL and SOSL in Salesforce: Complete Guide With Examples","og_description":"SOQL and SOSL in Salesforce explained with real-world examples, relationship queries, governor limits, and best practices to write efficient, high-performing Salesforce queries.","og_url":"https:\/\/dianapps.com\/blog\/soql-and-sosl-in-salesforce\/","og_site_name":"Learn About Digital Transformation &amp; Development | DianApps Blog","article_published_time":"2026-08-06T12:00:13+00:00","article_modified_time":"2026-08-09T15:27:10+00:00","og_image":[{"width":1536,"height":864,"url":"https:\/\/dianapps.com\/blog\/wp-content\/uploads\/2026\/08\/Untitled-design-66.webp","type":"image\/webp"}],"author":"Vaibhav Sharma","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Vaibhav Sharma","Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/dianapps.com\/blog\/soql-and-sosl-in-salesforce\/#article","isPartOf":{"@id":"https:\/\/dianapps.com\/blog\/soql-and-sosl-in-salesforce\/"},"author":{"name":"Vaibhav Sharma","@id":"https:\/\/dianapps.com\/blog\/#\/schema\/person\/e0ee1e2a6cfb8681a3cc69154f8d8bcf"},"headline":"SOQL and SOSL in Salesforce: Complete Guide With Examples","datePublished":"2026-08-06T12:00:13+00:00","dateModified":"2026-08-09T15:27:10+00:00","mainEntityOfPage":{"@id":"https:\/\/dianapps.com\/blog\/soql-and-sosl-in-salesforce\/"},"wordCount":1730,"commentCount":0,"image":{"@id":"https:\/\/dianapps.com\/blog\/soql-and-sosl-in-salesforce\/#primaryimage"},"thumbnailUrl":"https:\/\/dianapps.com\/blog\/wp-content\/uploads\/2026\/08\/Untitled-design-66.webp","keywords":["Apex SOQL","Salesforce Developer","Salesforce governor limits","Salesforce query language","Salesforce relationship queries","Salesforce SOQL","Salesforce SOSL","Salesforce tutorial","SOQL","SOQL and SOSL in Salesforce","SOQL query examples","SOQL syntax","SOQL vs SOSL","SOSL","SOSL query examples","SOSL syntax"],"articleSection":["Salesforce"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/dianapps.com\/blog\/soql-and-sosl-in-salesforce\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/dianapps.com\/blog\/soql-and-sosl-in-salesforce\/","url":"https:\/\/dianapps.com\/blog\/soql-and-sosl-in-salesforce\/","name":"SOQL and SOSL in Salesforce: Complete Guide With Examples","isPartOf":{"@id":"https:\/\/dianapps.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/dianapps.com\/blog\/soql-and-sosl-in-salesforce\/#primaryimage"},"image":{"@id":"https:\/\/dianapps.com\/blog\/soql-and-sosl-in-salesforce\/#primaryimage"},"thumbnailUrl":"https:\/\/dianapps.com\/blog\/wp-content\/uploads\/2026\/08\/Untitled-design-66.webp","datePublished":"2026-08-06T12:00:13+00:00","dateModified":"2026-08-09T15:27:10+00:00","author":{"@id":"https:\/\/dianapps.com\/blog\/#\/schema\/person\/e0ee1e2a6cfb8681a3cc69154f8d8bcf"},"description":"SOQL and SOSL in Salesforce explained with real-world examples, relationship queries, governor limits, and best practices to write efficient, high-performing Salesforce queries.","breadcrumb":{"@id":"https:\/\/dianapps.com\/blog\/soql-and-sosl-in-salesforce\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/dianapps.com\/blog\/soql-and-sosl-in-salesforce\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/dianapps.com\/blog\/soql-and-sosl-in-salesforce\/#primaryimage","url":"https:\/\/dianapps.com\/blog\/wp-content\/uploads\/2026\/08\/Untitled-design-66.webp","contentUrl":"https:\/\/dianapps.com\/blog\/wp-content\/uploads\/2026\/08\/Untitled-design-66.webp","width":1536,"height":864,"caption":"SOQL and SOSL in Salesforce: A Complete Guide With Examples"},{"@type":"BreadcrumbList","@id":"https:\/\/dianapps.com\/blog\/soql-and-sosl-in-salesforce\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/dianapps.com\/blog\/"},{"@type":"ListItem","position":2,"name":"SOQL and SOSL in Salesforce: Complete Guide With Examples"}]},{"@type":"WebSite","@id":"https:\/\/dianapps.com\/blog\/#website","url":"https:\/\/dianapps.com\/blog\/","name":"Learn About Digital Transformation &amp; Development | DianApps Blog","description":"Dianapps","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/dianapps.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/dianapps.com\/blog\/#\/schema\/person\/e0ee1e2a6cfb8681a3cc69154f8d8bcf","name":"Vaibhav Sharma","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/dianapps.com\/blog\/wp-content\/uploads\/2026\/07\/cropped-Vaibhav-Sharma-Salesforce-Specialist-96x96.jpg","url":"https:\/\/dianapps.com\/blog\/wp-content\/uploads\/2026\/07\/cropped-Vaibhav-Sharma-Salesforce-Specialist-96x96.jpg","contentUrl":"https:\/\/dianapps.com\/blog\/wp-content\/uploads\/2026\/07\/cropped-Vaibhav-Sharma-Salesforce-Specialist-96x96.jpg","caption":"Vaibhav Sharma"},"description":"A Salesforce specialist with over 15 years in the field, Vaibhav Sharma has built his career at the intersection of CRM strategy and enterprise transformation. As the driving force behind Salesforce innovation at DianApps, he architects solutions across Sales Cloud, Service Cloud, and Experience Cloud that turn fragmented customer data into unified growth engines. His work spans a 360-degree perspective in BFSI, healthcare, and retail, where he's known for engineering platforms that don't just go live, they move revenue and retention numbers. Vaibhav's edge lies in reading where Salesforce is headed next, from AI-powered automation, AgentExchange to Agentforce, and translating that foresight into roadmaps enterprise leaders can act on today.","url":"https:\/\/dianapps.com\/blog\/author\/vaibhav-sharma\/"}]}},"_links":{"self":[{"href":"https:\/\/dianapps.com\/blog\/wp-json\/wp\/v2\/posts\/19776","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dianapps.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dianapps.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dianapps.com\/blog\/wp-json\/wp\/v2\/users\/15"}],"replies":[{"embeddable":true,"href":"https:\/\/dianapps.com\/blog\/wp-json\/wp\/v2\/comments?post=19776"}],"version-history":[{"count":8,"href":"https:\/\/dianapps.com\/blog\/wp-json\/wp\/v2\/posts\/19776\/revisions"}],"predecessor-version":[{"id":19853,"href":"https:\/\/dianapps.com\/blog\/wp-json\/wp\/v2\/posts\/19776\/revisions\/19853"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/dianapps.com\/blog\/wp-json\/wp\/v2\/media\/19792"}],"wp:attachment":[{"href":"https:\/\/dianapps.com\/blog\/wp-json\/wp\/v2\/media?parent=19776"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dianapps.com\/blog\/wp-json\/wp\/v2\/categories?post=19776"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dianapps.com\/blog\/wp-json\/wp\/v2\/tags?post=19776"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}