Manipular registros con DML
Objetivos de aprendizaje
Después de completar esta unidad, podrá:
- Usar DML para insertar, actualizar y eliminar registros.
- Realizar declaraciones DML de forma masiva.
- Usar la alteración para insertar o actualizar un registro.
- Capturar una excepción DML.
- Usar un método de base de datos para insertar registros nuevos con la opción de validez parcial y procesar los resultados.
- Saber cuándo usar declaraciones DML y cuándo usar métodos de base de datos.
- Realizar operaciones DML en registros relacionados.
Manipular registros con DML
Cree y modifique registros en Salesforce mediante el uso del lenguaje de manipulación de datos (DML, Data Manipulation Language). DML es un método sencillo para gestionar registros mediante una serie de declaraciones simples para insertar, actualizar, combinar, eliminar y restaurar registros.
Dado que Apex es un lenguaje centrado en los datos y se guarda en Lightning Platform, tiene acceso directo a sus datos en Salesforce. A diferencia de otros lenguajes de programación que requieren una configuración adicional para la conexión con fuentes de datos, en el caso de DML de Apex, se simplifica la gestión de registros. Al llamar a declaraciones DML, puede realizar operaciones rápidas en sus registros de Salesforce. En este ejemplo se agrega la cuenta de Acme a Salesforce. En primer lugar, se crea una cuenta sObject y, a continuación, se pasa como un argumento a la declaración insert, lo que tiene como resultado la persistencia del registro en Salesforce.
// Create the account sObject Account acct = new Account(Name='Acme', Phone='(415)555-1212', NumberOfEmployees=100); // Insert the account by using DML insert acct;
Declaraciones DML
Están disponibles las siguientes declaraciones DML.
insert
(insertar)update
(actualizar)upsert
(insertar o actualizar)delete
(eliminar)undelete
(recuperar)merge
combinar)
Cada declaración DML acepta un único sObject o una lista (o conjunto) de sObjects. La realización de operaciones en una lista de sObjects es un método más eficiente para procesar los registros.
Todas estas declaraciones, a excepción de un par, son operaciones de base de datos conocidas. Las declaraciones upsert
y merge
son específicas de Salesforce y pueden ser de gran utilidad.
La operación DML upsert
crea registros y actualiza los registros de sObject en una sola declaración mediante un campo especificado para determinar la presencia de objetos existentes o el campo de Id. si no se especifica ningún campo.
La declaración merge
combina hasta tres registros del mismo tipo de sObject en uno de los registros mediante la eliminación de los demás y la reorganización jerárquica de todos los registros relacionados.
Asignación automática de campos de Id. a registros nuevos
Al insertar registros, el sistema asigna un Id. a cada registro. Además de garantizar la persistencia del valor de Id. en la base de datos, el valor de Id. se completa automáticamente en la variable de sObject usada como argumento en la llamada a DML.
En este ejemplo se muestra cómo obtener el Id. en el sObject correspondiente a la cuenta insertada.
// Create the account sObject Account acct = new Account(Name='Acme', Phone='(415)555-1212', NumberOfEmployees=100); // Insert the account by using DML insert acct; // Get the new ID on the inserted sObject argument ID acctID = acct.Id; // Display this ID in the debug log System.debug('ID = ' + acctID); // Debug log result (the ID will be different in your case) // DEBUG|ID = 001D000000JmKkeIAF
DML masiva
Puede realizar operaciones DML en un solo sObject o bien de forma masiva en una lista de sObjects. Se recomienda realizar operaciones DML masivas, ya que ayuda a evitar alcanzar los límites reguladores, como el límite de DML de 150 declaraciones por transacción Apex. Este límite se establece para garantizar un correcto acceso a los recursos compartidos en Lightning Platform. La realización de una operación DML en una lista de sObjects se corresponde con una sola declaración DML, no como una única declaración para cada sObject.
En este ejemplo se insertan contactos de forma masiva mediante la inserción de una lista de contactos en una sola llamada. A continuación, estos contactos también se actualizan de forma masiva.
- Ejecute este miniprograma en Developer Console mediante Apex anónimo.
// Create a list of contacts List<Contact> conList = new List<Contact> { new Contact(FirstName='Joe',LastName='Smith',Department='Finance'), new Contact(FirstName='Kathy',LastName='Smith',Department='Technology'), new Contact(FirstName='Caroline',LastName='Roth',Department='Finance'), new Contact(FirstName='Kim',LastName='Shain',Department='Education')}; // Bulk insert all contacts with one DML call insert conList; // List to hold the new contacts to update List<Contact> listToUpdate = new List<Contact>(); // Iterate through the list and add a title only // if the department is Finance for(Contact con : conList) { if (con.Department == 'Finance') { con.Title = 'Financial analyst'; // Add updated contact sObject to the list. listToUpdate.add(con); } } // Bulk update all contacts with one DML call update listToUpdate;
- Inspeccione los contactos recién creados en su organización.
Dos de los contactos del departamento de finanzas deben tener sus puestos de trabajo completados conFinancial analyst
(Analista de finanzas).
Alteración de registros
Si tiene una lista con una combinación de registros nuevos y existentes, puede procesar inserciones y actualizaciones para todos los registros de la lista mediante la declaración upsert
. La alteración permite evitar la creación de registros duplicados y ahorrar tiempo, ya que no necesita determinar qué registro existe primero.
La declaración upsert
determina la coincidencia de los sObjects y los registros existentes mediante la comparación de los valores de un solo campo. Si no especifica ningún campo al llamar a esta declaración, la declaración upsert
usa el Id. de sObject para determinar la coincidencia de sObject y los registros existentes de Salesforce. De forma alternativa, puede especificar un campo para la coincidencia. En el caso de los objetos personalizados, especifique un campo personalizado marcado como Id. externo. En el caso de los objetos estándar, puede especificar cualquier campo con la propiedad idLookup establecida como verdadera. Por ejemplo, el campo Email (Correo electrónico) del contacto o usuario tiene la propiedad idLookup establecida. Para comprobar la propiedad de un campo, consulte Referencia de objetos para Salesforce y Lightning Platform.
Sintaxis de upsert
upsert sObject | sObject[] upsert sObject | sObject[] field
El campo opcional es un token de campo. Por ejemplo, para especificar el campo MyExternalID, la declaración es:
upsert sObjectList Account.Fields.MyExternalId;
En el caso de upsert, se usan la clave principal del registro de sObject (Id.), un campo idLookup o un campo de Id. externo para determinar si se debe crear un registro nuevo o actualizar uno existente:
- Si la clave no coincide, se crea un registro de objeto.
- Si la clave coincide una vez, se actualiza el registro de objeto existente.
- Si la clave coincide varias veces, se genera un error y el registro de objeto no se inserta ni actualiza.
En este ejemplo se muestra cómo upsert actualiza un registro de contacto existente e inserta un contacto nuevo en una sola llamada. Esta llamada a upsert actualiza el contacto Josh existente e inserta el contacto nuevo Kathy.
- Ejecute este miniprograma en la ventana de ejecución anónima de Developer Console.
// Insert the Josh contact Contact josh = new Contact(FirstName='Josh',LastName='Kaplan',Department='Finance'); insert josh; // Josh's record has been inserted // so the variable josh has now an ID // which will be used to match the records by upsert josh.Description = 'Josh\'s record has been updated by the upsert operation.'; // Create the Kathy contact, but don't persist it in the database Contact kathy = new Contact(FirstName='Kathy',LastName='Brown',Department='Technology'); // List to hold the new contacts to upsert List<Contact> contacts = new List<Contact> { josh, kathy }; // Call upsert upsert contacts; // Result: Josh is updated and Kathy is created.
- Inspeccione todos los contactos de su organización.
Su organización tendrá un solo registro Josh Kaplan y no dos, ya que la operación de alteración (upsert) ha detectado y actualizado el registro existente en lugar de crear un registro de contacto. Además, se incluirá un registro de contacto Kathy Brown.
De forma alternativa, puede especificar un campo para los registros coincidentes. Este ejemplo utiliza el campo Email (Correo electrónico) en Contact (Contacto) porque tiene la propiedad idLookup establecida. En el ejemplo se inserta el contacto Jane Smith y se crea un segundo sObject de contacto, se completa con el mismo correo electrónico y, a continuación, se llama a upsert
para actualizar el contacto mediante el campo Correo electrónico para determinar la coincidencia.
- Ejecute este miniprograma en la ventana de ejecución anónima de Developer Console.
Contact jane = new Contact(FirstName='Jane', LastName='Smith', Email='jane.smith@example.com', Description='Contact of the day'); insert jane; // 1. Upsert using an idLookup field // Create a second sObject variable. // This variable doesn’t have any ID set. Contact jane2 = new Contact(FirstName='Jane', LastName='Smith', Email='jane.smith@example.com', Description='Prefers to be contacted by email.'); // Upsert the contact by using the idLookup field for matching. upsert jane2 Contact.fields.Email; // Verify that the contact has been updated System.assertEquals('Prefers to be contacted by email.', [SELECT Description FROM Contact WHERE Id=:jane.Id].Description);
- Inspeccione todos los contactos de su organización.
Su organización solo tendrá un contacto Jane Smith con la descripción actualizada.
Eliminar registros
Puede eliminar registros persistentes mediante la declaración delete
. Los registros eliminados no se eliminan de forma permanente de Lightning Platform, sino que se envían a la papelera de reciclaje durante 15 días y se pueden restaurar desde ahí.
En este ejemplo se muestra cómo eliminar todos los contactos con el apellido Smith. Si realiza las acciones del ejemplo en el caso de DML masivo, su organización ya debería tener dos contactos con el apellido Smith. Ejecute este miniprograma en Developer Console mediante Apex anónimo y, a continuación, verifique que ya no hay contactos con el apellido Smith.
Contact[] contactsDel = [SELECT Id FROM Contact WHERE LastName='Smith']; delete contactsDel;
Excepciones de declaraciones DML
Si una operación DML genera un error, devuelve una excepción del tipo DmlException
. Puede capturar las excepciones del código para controlar los errores.
En este ejemplo se produce una excepción del tipo DmlException
porque se intenta insertar una cuenta sin el campo Name (Nombre) obligatorio. La excepción se captura en un bloque de captura.
try { // This causes an exception because // the required Name field is not provided. Account acct = new Account(); // Insert the account insert acct; } catch (DmlException e) { System.debug('A DML exception has occurred: ' + e.getMessage()); }
Métodos de base de datos
Apex contiene la clase de base de datos integrada, lo que proporciona métodos para realizar operaciones DML y reflejar homólogos de declaraciones DML.
Estos métodos de base de datos son estáticos y se llama a ellos en el nombre de clase.
Database.insert()
Database.update()
Database.upsert()
Database.delete()
Database.undelete()
Database.merge()
A diferencia de las declaraciones DML, los métodos de base de datos incluyen un parámetro allOrNone opcional que permite especificar si la operación debe ser correcta parcialmente. Cuando este parámetro se establece en false
, si se produce un error en un conjunto parcial de registros, los registros correctos se confirman y los errores se devuelven para los registros incorrectos. Además, no se producen excepciones con la opción de validez parcial.
De este modo, llama al método insert
con allOrNone establecido en false
.
Database.insert(recordList, false);
Los métodos de base de datos devuelven objetos de resultados que contienen información de validez o error para cada registro. Por ejemplo, las operaciones de inserción y actualización devuelven en cada caso un conjunto de objetos Database.SaveResult
.
Database.SaveResult[] results = Database.insert(recordList, false);
De forma predeterminada, el parámetro allOrNone es true
, lo que significa que el método de base de datos se comporta como su homólogo de declaración DML y producirá una excepción si se detecta un error.
Las dos declaraciones siguientes son equivalentes a la declaración insert recordList;
.
Database.insert(recordList);
AND
Database.insert(recordList, true);
Ejemplo: Inserción de registros de validez parcial
Vamos a examinar un ejemplo en el que se usan métodos de base de datos. Este ejemplo se basa en el ejemplo de DML masivo, pero sustituye a la declaración DML con un método de base de datos. El método Database.insert()
se llama con la opción de validez parcial. Un contacto de la lista no tiene ningún campo a propósito y producirá un error dado que el contacto no se puede guardar sin el campo obligatorio LastName. Se confirman tres contactos y el contacto sin ningún campo genera un error. La última parte de este ejemplo es iterativa en los resultados devueltos y escribe mensajes de depuración en el registro de depuración.
- Ejecute este ejemplo en la ventana de ejecución anónima de Developer Console.
// Create a list of contacts List<Contact> conList = new List<Contact> { new Contact(FirstName='Joe',LastName='Smith',Department='Finance'), new Contact(FirstName='Kathy',LastName='Smith',Department='Technology'), new Contact(FirstName='Caroline',LastName='Roth',Department='Finance'), new Contact()}; // Bulk insert all contacts with one DML call Database.SaveResult[] srList = Database.insert(conList, false); // Iterate through each returned result for (Database.SaveResult sr : srList) { if (sr.isSuccess()) { // Operation was successful, so get the ID of the record that was processed System.debug('Successfully inserted contact. Contact ID: ' + sr.getId()); } else { // Operation failed, so get all errors for(Database.Error err : sr.getErrors()) { System.debug('The following error has occurred.'); System.debug(err.getStatusCode() + ': ' + err.getMessage()); System.debug('Contact fields that affected this error: ' + err.getFields()); } } }
- Compruebe los mensajes de depuración (use la palabra clave DEBUG para el filtro).
Se debe indicar un error y se deben haber insertado tres contactos.
¿Debe usar declaraciones DML o métodos de base de datos?
- Use las declaraciones DML si desea que cualquier error que se produzca durante el procesamiento masivo de DML se genere como una excepción de Apex que interrumpa de inmediato el flujo del control (mediante el uso de bloques
try...catch
). Este comportamiento es similar al modo en el que se controlan las excepciones en la mayoría de los lenguajes de procedimientos de base de datos.
- Use métodos de clase de base de datos si desea permitir la validez parcial de una operación DML masiva (si un registro genera un error, el resto de la operación DML aún puede ser válida). A continuación, su aplicación puede inspeccionar los registros rechazados y posiblemente volver a intentar la operación. Si usa este método, puede escribir código que nunca genere errores de excepción DML. Por el contrario, su código puede usar el conjunto de resultados correspondiente para valorar la validez o los errores. Tenga en cuenta que los métodos de base de datos incluyen además una sintaxis que admite las excepciones producidas de forma similar a las declaraciones DML.
Trabajo con registros relacionados
Cree y gestione registros relacionados entre sí mediante relaciones.
Inserción de registros relacionados
Puede insertar registros relacionados con los registros existentes si ya se ha definido una relación entre los dos objetos, como una búsqueda o una relación principal-detalle. Un registro se asocia a un registro relacionado mediante un Id. de clave externa. Por ejemplo, si va a insertar un contacto nuevo, puede especificar el registro de cuenta relacionado del contacto mediante la configuración del valor del campo AccountId
.
En este ejemplo se muestra cómo agregar un contacto a una cuenta (registro relacionado) mediante la configuración del campo AccountId
del contacto. El contacto y la cuenta están vinculados mediante una relación de búsqueda.
- Ejecute este miniprograma en la ventana de código Apex anónimo de Developer Console.
Account acct = new Account(Name='SFDC Account'); 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 mario = new Contact( FirstName='Mario', LastName='Ruiz', Phone='415.555.1212', AccountId=acctID); insert mario;
- Inspeccione los contactos de su organización.
Se ha creado una cuenta (SFDC Account) que incluye el contacto Mario Ruiz en la lista relacionada de contactos de la cuenta.
Actualización de registros relacionados
Los campos de los registros relacionados no se pueden actualizar con la misma llamada a la operación DML y requieren una llamada a DML independiente. Por ejemplo, si va a insertar un contacto nuevo, puede especificar el registro de cuenta relacionado del contacto mediante la configuración del valor del campo AccountId
. No obstante, no puede cambiar el nombre de la cuenta sin actualizar la cuenta mediante una llamada a DML independiente. De forma similar, al actualizar un contacto, si desea además actualizar la cuenta relacionada del contacto, debe hacer dos llamadas a DML. En el ejemplo siguiente, se actualizan un contacto y su cuenta relacionada mediante dos declaraciones update
(actualizar).
// Query for the contact, which has been associated with an account. Contact queriedContact = [SELECT Account.Name FROM Contact WHERE FirstName = 'Mario' AND LastName='Ruiz' LIMIT 1]; // Update the contact's phone number queriedContact.Phone = '(415)555-1213'; // Update the related account industry queriedContact.Account.Industry = 'Technology'; // Make two separate calls // 1. This call is to update the contact's phone. update queriedContact; // 2. This call is to update the related account's Industry field. update queriedContact.Account;
Eliminación de registros relacionados
La operación delete
admite eliminaciones en cascada. Si elimina un objeto principal, elimina también automáticamente los secundarios siempre que cada registro secundario se pueda eliminar.
Por ejemplo, la eliminación de la cuenta creada anteriormente (SFDC Account) eliminará también su contacto relacionado.
- Ejecute este miniprograma en la ventana de código Apex anónimo de Developer Console.
Account[] queriedAccounts = [SELECT Id FROM Account WHERE Name='SFDC Account']; delete queriedAccounts;
- Compruebe las cuentas y los contactos de su organización.
Verá que se han eliminado tanto la cuenta como su contacto relacionado.
Acerca de las transacciones
Las operaciones DML se ejecutan en una transacción. Todas las operaciones DML de una transacción se completan correctamente o, si se produce un error en una operación, se revierte toda la transacción y no se confirma ningún dato para la base de datos. El límite de una transacción puede ser un desencadenador, un método de clase, un bloque anónimo de código, una página de Apex o un método de servicio web personalizado. Por ejemplo, si un desencadenador o una clase crean dos cuentas y actualizan un contacto, y la actualización del contacto es incorrecta debido a un error de regla de validación, se revierte toda la transacción y ninguna de las cuentas persiste en Salesforce.
Recursos
- Guía del desarrollador de Apex
- Guía del desarrollador de Apex: Trabajo con datos en Apex
- Guía del desarrollador de Apex: Agregar y recuperar datos con DML
- Guía del desarrollador de Apex: Clase de base de datos
- Guía del desarrollador de Apex: Declaraciones de excepción