Empiece a realizar un seguimiento de su progreso
Inicio de Trailhead
Inicio de Trailhead
Estimación de tiempo

Escribir consultas SOQL

Objetivos de aprendizaje

Después de completar esta unidad, podrá:
  • Escribir consultas SOQL en Apex.
  • Ejecutar consultas SOQL mediante el editor de consultas de la consola de desarrollador.
  • Ejecutar consultas SOQL insertadas en Apex mediante Apex anónimo.
  • Consultar registros relacionados.

Escribir consultas SOQL

Para leer un registro desde Salesforce, debe redactar una consulta. Salesforce proporciona un lenguaje de consulta de objetos (Salesforce Object Query Language o SOQL), el cual puede usar para leer los registros guardados. SOQL es similar al lenguaje SQL estándar, pero se ha personalizado para la Plataforma Lightning.

Dado que Apex tiene acceso directo a los registros de Salesforce almacenados en la base de datos, puede insertar consultas SOQL en el código Apex y obtener resultados de forma sencilla. La inserción de SOQL en Apex se llama SOQL en línea.

Para incluir consultas SOQL en su código Apex, incluya la instrucción SOQL entre corchetes y asigne el valor devuelto a un conjunto de sObjects. Por ejemplo, lo siguiente recupera todos los registros de cuenta con dos campos (Name y Phone) y devuelve un conjunto de sObjects de cuenta.

Account[] accts = [SELECT Name,Phone FROM Account];

Requisitos

En el caso de algunas consultas de esta unidad, se espera que la organización tenga cuentas y contactos. Antes de ejecutar las consultas, cree algunos datos de ejemplo.

  1. En la consola de desarrollador, abra la ventana de ejecución anónima desde el menú Debug (Depurar).
  2. Inserte el siguiente miniprograma en la ventana y haga clic en Execute (Ejecutar).
// Add account and related contact
Account acct = new Account(
    Name='SFDC Computing',
    Phone='(415)555-1212',
    NumberOfEmployees=50,
    BillingCity='San Francisco');
insert acct;

// Once the account is inserted, the sObject will be 
// populated with an ID.
// Get this ID.
ID acctID = acct.ID;

// Add a contact to this account.
Contact con = new Contact(
    FirstName='Carol',
    LastName='Ruiz',
    Phone='(415)555-1212',
    Department='Wingo',
    AccountId=acctID);
insert con;

// Add account with no contact
Account acct2 = new Account(
    Name='The SFDC Query Man',
    Phone='(310)555-1213',
    NumberOfEmployees=50,
    BillingCity='Los Angeles',
    Description='Expert in wing technologies.');
insert acct2;

Uso del editor de consultas

Developer Console incluye una consola de editor de consultas, la cual permite ejecutar consultas SOQL y ver los resultados. El editor de consultas es un método rápido para inspeccionar la base de datos. Además, es una buena forma de probar sus consultas SOQL antes de agregarlas al código Apex. Cando utilice el editor de consultas, debe proporcionar únicamente la instrucción SOQL sin el código de Apex que la rodea.

Vamos a intentar ejecutar el siguiente ejemplo de SOQL:

  1. En la consola de desarrollador, haga clic en la ficha Query Editor (Editor de consultas).
  2. Copie y pegue lo siguiente en el primer cuadro debajo del editor de consultas y, a continuación, haga clic en Execute (Ejecutar).
SELECT Name,Phone FROM Account

Todos los registros de cuenta de su organización se muestran en la sección de resultados de la consulta en forma de filas con campos.

Sintaxis de SOQL básica

Esta es la sintaxis de una consulta de SOQL básica:

SELECT fields FROM ObjectName [WHERE Condition]

La cláusula WHERE es opcional. Vamos a empezar con una consulta muy sencilla. Por ejemplo, la consulta siguiente recupera cuentas y obtiene los campos Nombre y Teléfono para cada cuenta.

SELECT Name,Phone FROM Account

La consulta consta de dos partes:

  1. SELECT Name,Phone: en esta parte se incluyen los campos que desea recuperar. Los campos se especifican después de la palabra clave SELECT en una lista delimitada por comas. O bien, puede especificar un solo campo, en cuyo caso no es necesario el uso de comas (por ejemplo, SELECT Phone).
  2. FROM Account: en esta parte se especifica el objeto estándar o personalizado que desea recuperar. En este ejemplo, es Account. En el caso de un objeto personalizado llamado Invoice_Statement, es Invoice_Statement__c.

Más allá de lo básico

A diferencia de otros lenguajes SQL, no puede especificar * para todos los campos. Debe especificar cada campo que desee obtener de forma explícita. Si intenta acceder a un campo que no ha especificado en la cláusula SELECT, obtendrá un error debido a que el campo no se ha recuperado.

No necesita especificar el campo Id en la consulta, ya que siempre se devuelve en las consultas de Apex con independencia de que se haya especificado o no en la consulta. Por ejemplo: SELECT Id,Phone FROM Account y SELECT Phone FROM Account son instrucciones equivalentes. La única ocasión en la que puede que desee especificar el campo Id es cuando se trata del único campo que va a recuperar debido a que tiene una lista de un campo como mínimo: SELECT Id FROM Account. Además, puede que desee especificar el campo Id al ejecutar una consulta en el editor de consultas, ya que el campo Id no se mostrará a menos que se especifique.

Filtrado de resultados de consulta con condiciones

Si tiene varias cuentas en la organización, se devolverán todas. Si desea limitar las cuentas devueltas a las cuentas que cumplen una condición determinada, puede agregar esta condición en la cláusula WHERE. En el siguiente ejemplo se recuperan solo las cuentas cuyos nombres son SFDC Computing. Observe que no se aplica la distinción entre mayúsculas y minúsculas a las comparaciones de las cadenas.

SELECT Name,Phone FROM Account WHERE Name='SFDC Computing'

La cláusula WHERE puede contener varias condiciones que se agrupan mediante operadores lógicos (AND, OR) y paréntesis. Por ejemplo, esta consulta devuelve todas las cuentas con el nombre SFDC Computing y más de 25 empleados:

SELECT Name,Phone FROM Account WHERE (Name='SFDC Computing' AND NumberOfEmployees>25)

Este es otro ejemplo con una condición más compleja. Esta consulta devuelve todas las cuentas SFDC Computing o todas las cuentas con más de 25 empleados cuya ciudad de facturación es Los Angeles.

SELECT Name,Phone FROM Account WHERE (Name='SFDC Computing' OR (NumberOfEmployees>25 AND BillingCity='Los Angeles'))

Más allá de lo básico

En lugar de usar el operador de igualdad (=) para la comparación, puede establecer coincidencias aproximadas mediante el operador LIKE. Por ejemplo, puede recuperar todas las cuentas cuyos nombres empiecen por SFDC mediante esta condición: WHERE Name LIKE 'SFDC%'. El carácter comodín % coincide con cualquier o ningún carácter. Por el contrario, el carácter _ se puede usar para establecer la coincidencia con tan solo un carácter.

Ordenación de resultados de consulta

Dado que cuando se ejecuta una consulta, devuelve registros de Salesforce sin ningún orden en concreto, no puede esperar que el orden de los registros del conjunto devuelto sea el mismo cada que vez que se ejecuta la consulta. No obstante, puede elegir el orden en el que se devuelve el conjunto de registros si agrega una cláusula ORDER BY y especifica el campo según el cual se va a ordenar el conjunto de registros. En este ejemplo se ordenan todas las cuentas recuperadas según el campo Name.

SELECT Name,Phone FROM Account ORDER BY Name

El orden predeterminado es el orden alfabético, el cual se especifica como ASC. La instrucción anterior es equivalente a:

SELECT Name,Phone FROM Account ORDER BY Name ASC

Para invertir el orden, use la palabra clave DESC para aplicar el orden descendente:

SELECT Name,Phone FROM Account ORDER BY Name DESC

Puede ordenar la mayoría de los campos, incluidos los campos numéricos y de texto. No puede ordenar campos de texto enriquecido ni listas de selección múltiple.

Pruebe estas instrucciones SOQL en el editor de consultas para ver cómo el orden de los registros devueltos cambia según el campo Name.

Limitación del número de registros devueltos

Para limitar el número de registros devueltos a número arbitrario, agregue la cláusula LIMIT n, donde n es el número de registro que desea devolver. La limitación del conjunto de resultados es de utilidad si no le importa qué registros se van a devolver, sino que solo desea trabajar con un subconjunto de registros. Por ejemplo, esta consulta recupera la primera cuenta devuelta. Observe que el valor devuelto es una sola cuenta y no un conjunto cuando se usa LIMIT 1.

Account oneAccountOnly = [SELECT Name,Phone FROM Account LIMIT 1];

Combinación de todos los elementos

Puede combinar las cláusulas opcionales en una sola consulta en el orden siguiente:

SELECT Name,Phone FROM Account 
                   WHERE (Name = 'SFDC Computing' AND NumberOfEmployees>25)
                   ORDER BY Name
                   LIMIT 10

Ejecute la siguiente consulta SOQL en Apex mediante la ventana de ejecución anónima de Developer Console. A continuación, inspeccione las instrucciones debug del registro de depuración. Se debe devolver una cuenta de ejemplo.

Account[] accts = [SELECT Name,Phone FROM Account 
                   WHERE (Name='SFDC Computing' AND NumberOfEmployees>25)
                   ORDER BY Name
                   LIMIT 10];
System.debug(accts.size() + ' account(s) returned.');
// Write all account array info
System.debug(accts);

Acceso a variables en consultas SOQL

Las instrucciones SOQL de Apex pueden hacer referencia a variables y expresiones de código Apex si van precedidas de dos puntos (:). El uso de una variable local en una instrucción SOQL se llama enlace.

En este ejemplo se muestra cómo usar la variable targetDepartment en la cláusula WHERE.

String targetDepartment = 'Wingo';
Contact[] techContacts = [SELECT FirstName,LastName 
                          FROM Contact WHERE Department=:targetDepartment];

Consulta de registros relacionados

Los registros de Salesforce se pueden vincular entre sí mediante relaciones (relaciones de búsqueda o relaciones principal-detalle). Por ejemplo, el contacto tiene una relación de búsqueda con la cuenta. Al crear o actualizar un contacto, puede asociarlo a una cuenta. Los contactos asociados a la misma cuenta se muestran en una lista relacionada en la página de la cuenta. Del mismo modo, puede ver los registros relacionados en la interfaz de usuario de Salesforce y puede consultar los registros relacionados en SOQL.

Para obtener registros secundarios relacionados con un registro principal, agregue una consulta interna para los registros secundarios. La cláusula FROM de la consulta interna se ejecuta según el nombre de la relación en lugar de un nombre de objeto de Salesforce. Este ejemplo incluye una consulta interna para obtener todos los contactos asociados a cada cuenta devuelta. La cláusula FROM especifica la relación Contacts, que es una relación predeterminada de la cuenta que vincula cuentas y contactos.

SELECT Name, (SELECT LastName FROM Contacts) FROM Account WHERE Name = 'SFDC Computing'

El siguiente es un ejemplo de consulta SOQL en Apex y en él se muestra cómo obtener registros secundarios del resultado de SOQL mediante el nombre de la relación Contacts en el sObject.

Account[] acctsWithContacts = [SELECT Name, (SELECT FirstName,LastName FROM Contacts)
                               FROM Account 
                               WHERE Name = 'SFDC Computing'];
// Get child records
Contact[] cts = acctsWithContacts[0].Contacts;
System.debug('Name of first associated contact: ' 
             + cts[0].FirstName + ', ' + cts[0].LastName);

Puede recorrer una relación desde un objeto secundario (contacto) hasta un campo de su objeto principal (Account.Name) mediante la notación de puntos. Por ejemplo, el siguiente miniprograma de Apex consulta los registros de contacto cuyo nombre es Carol y puede recuperar el nombre de la cuenta asociada de Carol mediante el recorrido de la relación entre cuentas y contactos.

Contact[] cts = [SELECT Account.Name FROM Contact 
                 WHERE FirstName = 'Carol' AND LastName='Ruiz'];
Contact carol = cts[0];
String acctName = carol.Account.Name;
System.debug('Carol\'s account name is ' + acctName);
Nota

Nota

Los ejemplos de esta sección se basan en objetos estándar. Los objetos personalizados se pueden vincular también mediante relaciones personalizadas. Los nombres de relaciones personalizadas terminan por el sufijo __r. Por ejemplo, las instrucciones de factura se vinculan a elementos de línea mediante la relación Line_Items__r del objeto personalizado Invoice_Statement__c.

Consulta de registros por lotes mediante SOQL para bucles

En el caso de un bucle for de SOQL, puede incluir una consulta SOQL en un bucle for. Los resultados de una consulta SOQL pueden iterar en el bucle. Los bucles for de SOQL usan un método distinto para recuperar registros (los registros se recuperan mediante la fragmentación eficiente con llamadas a la consulta y métodos queryMore de la API SOAP. Con los bucles for de SOQL, puede evitar alcanzar el límite de tamaño de la pila.

El bucle for de SOQL itera sobre todos los registros sObject devueltos por una consulta SOQL. La sintaxis de un bucle for de SOQL es:
for (variable : [soql_query]) {
    code_block
}
O bien:
for (variable_list : [soql_query]) {
    code_block
}

Tanto variable como variable_list deben ser del mismo tipo que los sObjects devueltos por soql_query.

Es preferible usar el formato de lista de sObjects del bucle for de SOQL, ya que el bucle for se ejecuta una vez para cada lote de 200 sObjects. Esto le permite trabajar con lotes de registros y realizar operaciones DML por lotes, lo que permite evitar alcanzar los límites regulados.

insert new Account[]{new Account(Name = 'for loop 1'), 
                     new Account(Name = 'for loop 2'), 
                     new Account(Name = 'for loop 3')};

// The sObject list format executes the for loop once per returned batch
// of records
Integer i=0;
Integer j=0;
for (Account[] tmp : [SELECT Id FROM Account WHERE Name LIKE 'for loop _']) {
    j = tmp.size();
    i++;
}
System.assertEquals(3, j); // The list should have contained the three accounts
                       // named 'yyy'
System.assertEquals(1, i); // Since a single batch can hold up to 200 records and,
                       // only three records should have been returned, the 
                       // loop should have executed only once