Manipular registros con DML
Objetivos de aprendizaje
- 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
// 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
(alterar) -
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 masivo
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 de Apex. Este límite se establece para garantizar un correcto acceso a los recursos compartidos en la Plataforma Lightning. 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 la consola de desarrollador 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
.
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 del contacto o usuario tiene la propiedad idLookup establecida. Para comprobar la propiedad de un campo, consulte Referencia de objetos para Salesforce y Plataforma Lightning.
Sintaxis de upsert
upsert sObject | sObject[]
upsert sObject | sObject[]
field
(campo)
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 la consola de desarrollador.
// 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 en 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 email y, a continuación, se llama a upsert
para actualizar el contacto mediante el campo Email para determinar la coincidencia.
- Ejecute este miniprograma en la ventana de ejecución anónima de la consola de desarrollador.
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 Plataforma Lightning, 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 la consola de desarrollador 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 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
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);
Y:
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 la consola de desarrollador.
// 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.
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