Salesforce

[Apex Basics & Database] - Manipulate Records with DML(DML로 레코드 조작하기) 세일즈포스 DML 레코드 조작

송테이토 2023. 2. 10. 10:23

https://trailhead.salesforce.com/ko/content/learn/modules/apex_database/apex_database_dml

 

Manipulate Records with DML

 

 

과제

YOUR CHALLENGE

Create a method for inserting accounts.

To pass this challenge, create an Apex class that inserts a new account named after an incoming parameter. If the account is successfully inserted, the method should return the account record. If a DML exception occurs, the method should return null.

  • The Apex class must be called AccountHandler and be in the public scope
  • The Apex class must have a public static method called insertNewAccount
public class AccountHandler { //called AccountHandler and be in the public scope
    // public static method called insertNewAccount
    //string as a parameter, which will be used to create the Account name
    public static Account insertNewAccount(String AccountName){ 
     //insert the account into the system and then return the record
        try {
    		Account acct = new Account(Name=AccountName);
    		insert acct;
            return acct;
	    } catch (DmlException e) { //catch the failed DML and then return null
    		 System.debug('A DML exception has occurred: ' + e.getMessage());
             return  null;
			}
    }
}
AccountHandler.insertNewAccount('TestAccount');

 

---

 

Data Manipulation Language (DML)

DML로 레코드조작하기

 

DML

  • insert
  • update
  • upsert
  • delete
  • undelete
  • merge

 

ID Field Auto-Assigned to New Records

// 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

 

Bulk DML

여러 개 만들어놓고 그냥 한번의 DML문으로 한번에 다 가능

//conList 생성
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')};
insert conList; //한번의 Insert로 대량 레코드 삽입이 가능
// 업데이트할 새연락처를 보유할 listToUpdate 
List<Contact> listToUpdate = new List<Contact>();
//conList 목록을 반복하고
for(Contact con : conList) {
    if (con.Department == 'Finance') { //만약 부서이름이 '재무'라면?
        con.Title = 'Financial analyst';  //'Financial analyst'로 제목 바꿔주기
        
        listToUpdate.add(con);
    }
}
update listToUpdate; //마찬가지로 한번으로 업데이트 가능

Upsert Records

Upsert helps avoid the creation of duplicate records and can save you time as you don’t have to determine which records exist first.

-> 필드의 값을 비교해 기존 sObject를 기존 레코드와 일치시킴.

 

Upsert Syntax

upsert sObject | sObject[]

upsert sObject | sObject[] field           

 For example, to specify the MyExternalID field, the statement is:

 

upsert sObjectList Account.Fields.MyExternalId;

 

 

upsert는 레코드 기본키(ID), idLookup필드 또는 외부 ID필드를 사용해 새 레코드를 생성해야하는지 아니면 기존 레코드를 업데이트 해야하는지 결정

  • If the key is not matched, a new object record is created.
  • If the key is matched once, the existing object record is updated.
  • If the key is matched multiple times, an error is generated and the object record is neither inserted or updated.

 

 how upsert updates an existing contact record and inserts a new contact in one call

// Josh의 Contact 삽입
Contact josh = new Contact(FirstName='Josh',LastName='Kaplan',Department='Finance');       
insert josh;
//변수 josh는 이제 upsert에 의해 레코드를 일치시키는 데 사용될 ID를 갖습니다.
josh.Description = 'Josh\'s record has been updated by the upsert operation.';
// Kathy contact 생성
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 };
//여기서 upsert 호출해주면
upsert contacts;
// Result: Josh 는 업데이트! Kathy는 생성!

결국  조직에는 Josh연락처는 한 개만 존재! 마찬가지로 케이시 연락처 레코드 한개있다

 

Jane Smith 연락처를 삽입하고 두 번째 연락처 sObject를 만들고 동일한 이메일로 채운 다음 upsert를 호출하여 일치를 위해 이메일 필드를 사용하여 연락처를 업데이트합니다.

 

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.');
// 일치를 위해 idLookup 필드를 사용하여 연락처를 Upsert합니다.
// 이메일이 같으니 이걸로 연결해서 upsert!
// 여기서 Insert를 하면 중복된 계정이 2개가 생겨버림!
upsert jane2 Contact.fields.Email;
System.assertEquals('Prefers to be contacted by email.',
                   [SELECT Description FROM Contact WHERE Id=:jane.Id].Description);

Jane Smith 연락처가 하나만 있습니다

 

질문!

그러면 Jane2  계정은 사라지고 Jane 레코드만 업데이트 되는건지

만약 이름이 다르면 어느계정  것이 더 우선이 되는지?

먼저 Insert한 순???

 

-> 이거 그냥 새로운 정보만 추가 업데이트 하는 것임!!!

 

Delete Records

바로 삭제되는건 아니고 15일동안 휴지통에서 보관!

 

Delete all contacts whose last name is Smith.

Contact[] contactsDel = [SELECT Id FROM Contact WHERE LastName='Smith']; 
delete contactsDel;

 

DML Statement Exceptions

예외처리는 언제나 중요하다!

DmlException 방지

try {
    Account acct = new Account();
    insert acct;
} catch (DmlException e) {
    System.debug('A DML exception has occurred: ' +
                e.getMessage());
}

 

Database Methods

 Database methods are static and are called on the class name.

  • Database.insert()
  • Database.update()
  • Database.upsert()
  • Database.delete()
  • Database.undelete()
  • Database.merge()

 

Unlike DML statements, Database methods have an optional allOrNone parameter

 

디폴트값이 ture

Database.insert(recordList);
Database.insert(recordList, true);

 

false일때만 insert 메서드 호출!

Database.insert(recordList, false);

 

삽입하기

Database.SaveResult[] results = Database.insert(recordList, false);

 

Example: Insert Records with Partial Success

의도적으로 필드가 없고,  LastName 필드 없이 연락처를 저장할 수 없음@@

 

// 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()) { //성공이면 ID값 반환
        System.debug('Successfully inserted contact. Contact ID: ' + sr.getId());
    } else {
        // 아니면 에러 가져오기
        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());
	 }
    }
}

Debug 결과

3개는 insert가 되었지만 하나는 Last Name 없다고 오류가 뜸!!

 

DML VS Database Method

DML : Apex 예외처리 원할 때

Database Method : 부분적인 성공을 허용하고 싶을 때,

 

 

Work with Related Records


Insert Related Records

You can insert records related to existing records if a relationship has already been defined between the two objects, such as a lookup or master-detail relationship

 

AccountId 필드를 설정하여 계정(관련 레코드)에 연락처를 추가하는 방법

 

//새 계정 SFDC Account 생성
Account acct = new Account(Name='SFDC Account');
insert acct;
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;

è 새 계정(SFDC 계정)을 만들었으며 계정의 연락처 관련 목록에 Mario Ruiz 연락처가 있습니다

 

Update Related Records

관련 레코드의 필드는 DML 작업에 대한 동일한 호출로 업데이트 할 수 없으며 별도의 DML 호출이 필요함!!

// 거래처와 연결된 연락처를 쿼리로
Contact queriedContact = [SELECT Account.Name 
                          FROM Contact 
                          WHERE FirstName = 'Mario' AND LastName='Ruiz'
                          LIMIT 1]; // Limit 숫자1만큼 행출력
// Update the contact's phone number
queriedContact.Phone = '(415)555-1213';
// Update the related account industry
queriedContact.Account.Industry = 'Technologys';
// Make two separate call
// 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;

즉 계정 자체를 업데이트하지 않고는 계정 이름 변경 불가!

연락처를 업데이트 ->연락처의 관련된 계정도 업데이트 -> DML 호출 두 번!

LIMIT 숫자 : 출력할 행의 수

OFFSET 숫자 : 몇번째 row부터 출력할 지. (1번째 row 0)

 

Delete Related Records

Account[] queriedAccounts = [SELECT Id FROM Account WHERE Name='SFDC Account'];
delete queriedAccounts;

상위 개체를 삭제하면 자동으로 하위개체도 다 삭제된다.

 

---