1) 수식 필드 사용
(1) 수식 필드의 기능
- 코드에서 두 개의 숫자 필드를 가져와 백분율을 생성하기 위해 나누려 할 때,
- 레코드의 페이지 레이아웃에서 필드를 클릭 가능한 하이퍼링크로 바꾸려 할 때,
- 두 개의 날짜를 가져와서 두 날짜 간 일수를 계산하기
- ···
(2) 수식 필드 만들기
🖥️ Fomula 수식 필드 만들기

① 단순 편집기와 고급 편집기
- 고급 편집기를 사용하는 것이 좋으며, 유용한 수식을 만들 수 있는 더 많은 도구를 사용할 수 있다.
② Insert Field(필드 삽입) 버튼을 누르면 수식에 사용할 필드를 선택할 수 있는 메뉴가 뜬다.

③ Insert Operator(연산자 삽입) 버튼을 누르면 사용 가능한 수학 및 논리 연산자의 드롭다운 목록이 뜬다.


④ Functions(함수) 메뉴에서 수식 함수를 보고 삽입할 수 있다. (예: TODAY() 함수는 현재 날짜를 반환함) LEN(text) 함수는 매개변수로 입력한 텍스트 길이를 찾는다. 수식 LEN("Hello")은 값 5를 반환한다.
⑤ 텍스트 영역에서 수식을 입력. 수식을 작성할 때 다음 사항에 유의해야 한다.
- 공백은 중요하지 않다. 원하는 만큼 공백과 줄바꿈을 삽입할 수 있다.
- 수식은 대/소문자를 구분한다. 필드 및 개체 이름의 대문자 사용에 주의해야 한다.
- 숫자로 작업할 때 표준 작업 순서가 적용된다.
⑥ Check Syntax(구문 검사) 버튼을 사용하여 저장하기 전에 모든 항목이 제대로 작동하는지 확인한다. 수식에 문제가 있는 경우 구문 검사기가 특정 문제에 대해 경고한다.

| ABS | 숫자의 절대값을 계산합니다. 숫자의 절대값은 양수 또는 음수 부호가 없는 숫자. |
| ACOS | 주어진 숫자가 -1에서 1 사이인 경우 라디안 단위로 숫자의 호 코사인을 반환합니다. 그렇지 않으면 NULL을 반환합니다. |
| ADDMONTHS | 지정한 날짜 전후의 표시된 개월 수에 해당하는 날짜를 반환합니다. 지정한 날짜가 해당 월의 마지막 날인 경우 결과 날짜는 해당 월의 마지막 날이 됩니다. 그렇지 않으면 결과는 지정한 날짜와 동일한 날짜 구성 요소를 갖습니다. |
| DATE | 입력한 연도, 월 및 일 값에서 날짜 값을 반환합니다. 수식 필드의 DATE 함수 값이 윤년이 아닌 2월 29일과 같이 잘못된 날짜인 경우 Salesforce는 세부 정보 페이지에 오류를 표시합니다. |
| DATEVALUE | 날짜/시간 또는 텍스트 표현식에 대한 날짜 값을 반환합니다. |
| DATETIMEVALUE | 연도, 월, 일 및 GMT 시간 값을 반환합니다. |
| DAY | 1에서 31까지의 숫자 형태로 월별 날짜를 반환합니다. |
| DAYOFYEAR | 역년의 날짜를 1부터 366까지의 숫자 형태로 반환합니다. |
| NOW | 현재 순간을 나타내는 날짜/시간을 반환합니다. |
| LEN | 지정된 텍스트 문자열의 문자 수를 반환합니다. |
| TRUNC | 숫자를 지정된 자릿수로 잘라냅니다. |
등 더 많은 함수 기능의 대한 설명은 페이지 참고
(3) 수식 디버깅
⑥ Check Syntax(구문 검사) 버튼은 수식을 디버깅하는 중요한 도구
- Missing parentheses(괄호 누락) , 쉼표 누락

- Incorrect parameter type(잘못된 매개변수 유형) : 함수가 텍스트 유형이어야 할 때, 숫자 유형을 입력하면 나타나는 오류

- Incorrect number of parameters for function(함수에 대한 잘못된 매개변수 개수) : 너무 많거나 너무 적은 매개변수를 입력하면 해당 오류가 표시

- Formula result is incompatible with formula return type(수식 결과가 수식 반환 유형과 호환되지 않음) : 하나의 데이터 형식을 선택했지만 다른 데이터 형식을 반환하는 수식을 작성하면 나타나는 오류

- Field does not exist(필드가 존재하지 않음) : 개체가 지원하지 않는 필드가 수식에 포함된 경우,


텍스트 리터럴이나 하이퍼링크 앞뒤에 따옴표를 입력하지 않은 경우
- Unknown function(알 수 없는 함수) : 함수의 철자가 틀린 경우에도 이 오류가 발생
-

2) 롤업 요약 필드 구현
(1) 롤업 요약 필드란
- 하위 객체에서 마스터-세부 관계를 공유하는 상위 객체로 데이터를 집계하는 필드이다.
- 롤업 요약 필드에는 카운트, 합계, 최소 및 최대 함수를 사용할 수 있다.
- 예를 들어 롤업 요약 필드를 사용하여 관련 계정의 기회에 대한 총 가치(금액)를 표시할 수 있다.

- 롤업 요약 필드에 필터 기준을 설정할 수 있으므로 관련 계정의 당첨 기회에서 총 기회 가치를 표시하도록 선택할 수 있다.
*롤업 요약 필드는 마스터-세부 관계에 있는 개체에만 사용할 수 있으며 조회 관계에 있는 개체에는 사용할 수 없다.
3) 유효성 검사 규칙 만들기
(1) 유효성 검사 규칙
- 사용자가 레코드에 입력한 데이터가 저장하기 전에 지정한 표준을 충족하는지 확인한다.
사용자 입력 데이터: 사용자가 실수를 저지르기 쉬운 경우 또는 특정 형식의 데이터가 필요한 경우.
시스템 수정 기록: 가져오기, 자동화된 프로세스, 통합 시스템 등에 의해 트리거된 데이터 변경은 유효성 검사 규칙*을 준수해야 한다.
🖥️ Validation Rules : 계정 번호 5자여야 하는 규칙 만들기
- Setup(설정)에서 **Object Manager(개체 관리자)**로 이동하고 **Account(계정)**를 클릭.
- 왼쪽 사이드바에서 **Validation Rules(유효성 검사 규칙)**를 클릭.
- **New(새로 만들기)**를 클릭.
- 유효성 검사 규칙에 대해 다음 속성을 입력.
- Rule Name(규칙 이름): Account_Number_5_Characters
- Error Condition Formula(오류 조건 수식): LEN( AccountNumber) <> 5
- 오류 메시지: Account number must be 8 characters long.(계정 번호는 5자여야 합니다.)
- 수식에 오류가 있는지 확인하려면 **Check Syntax(구문 검사)**를 클릭.
- **Save(저장)**를 클릭하여 작업을 마치기.

(2) 유효성 검사 규칙 예
- 계정 번호 숫자 지정하기
Field(필드) Value(값) 설명 Account Number(계정 번호)가 공백이 아닌 경우 숫자인지 확인. 수식 AND(
NOT(ISBLANK(AccountNumber)),
NOT(ISNUMBER(AccountNumber))
)오류 메시지 계정 번호가 숫자가 아닙니다. 오류 위치 계정 번호 - 날짜 반드시 현재 연도로 지정하기
- YEAR( My_Date__c ) <> YEAR ( TODAY() )
- 급여 범위 $20,000 이내여야 하기. 급여 최댓값 또는 급여 최솟값을 조정
- (Salary_Max__c - Salary_Min__c) > 20000
- 웹 사이트에는 .com, .org 또는 .net 확장자가 있어야 하는 규칙
- AND( RIGHT( Web_Site__c, 4) <> ".COM", RIGHT( Web_Site__c, 4) <> ".com", RIGHT( Web_Site__c, 4) <> ".ORG", RIGHT( Web_Site__c, 4) <> ".org", RIGHT( Web_Site__c, 4) <> ".NET", RIGHT( Web_Site__c, 4) <> ".net" )
- 이 외에 청구지 국가 코드 예시는 페이지 참고
4. Apex 기본 및 데이터베이스
1) Apex 시작하기
시작하기 전에, Apex에 대한 첫 번째 학습인 경우 먼저 빠른 시작: Apex 프로젝트를 진행하는 것이 좋다.
vs code 프로그램과 라이트닝 스튜디오 프로그램에서도 Apex Class를 만들 수 있지만 Org 환경 내에서도 생성할 수 있다.
(1) Developer Console 에서 Apex Class 작성하기
🖥️ Developer Console 에서 Apex Class
톱니바퀴 아이콘에서 설정을 누르고, Developer Console 창에 들어가 Apex Class를 생성할 수 있다.
아래에는 실행된 Org에서 Log를 확인할 수 있으며, 여기서 Debug 오류 작업을 찾기도 한다.

생성된 코드 호출 테스트
Developer Console에서 Open Excute Anonymouse Window 클릭

이전에 만든 코드를 실행한다.
- Execute : 전체 실행
- Execute Highlighted : 실행할 부분만 드래그해서 실행 시킬 수 있음.
(2) Apex에 대해
Apex는 Java와 유사한 구문을 사용하고 데이터베이스 저장 프로시저와 같이 작동하는 프로그래밍 언어이다. Apex를 통해 개발자는 버튼 클릭, 관련 레코드 업데이트 및 Visualforce 페이지와 같은 시스템 이벤트에 비즈니스 로직을 추가할 수 있다.

|
호스팅형 (Hosted)
|
Apex는 서버인 Lightning 플랫폼에서 저장, 컴파일 및 실행된다.
|
|
객체 지향 (Object oriented)
|
Apex는 클래스, 인터페이스 및 상속을 지원
|
|
강력한 유형 지정 (Strongly typed)
|
Apex는 컴파일 시 객체에 대한 참조의 유효성을 검사
|
|
멀티테넌트 인식 (Multitenant aware)
|
Apex는 멀티테넌트 플랫폼에서 실행되므로 코드가 공유 리소스를 독점하지 못하도록 제한을 적용하여 런어웨이 코드를 면밀히 방지
|
|
데이터베이스와 통합 (Integrated with the database)
|
기록에 액세스하고 조작하는 것이 간단하다. Apex는 레코드 및 해당 필드에 직접 액세스할 수 있으며, 이러한 레코드를 조작할 수 있는 문과 쿼리 언어를 제공
|
|
데이터 중심 (Data focused)
|
Apex는 데이터베이스에 대한 트랜잭션 액세스를 제공하므로 작업을 롤백할 수 있다.
|
|
간편한 사용 (Easy to use)
|
Apex는 친숙한 Java 관용구를 기반이다.
|
|
간편한 테스트 (Easy to test)
|
Apex는 단위 테스트 생성, 실행 및 코드 커버리지에 대한 기본 지원을 제공합니다. Salesforce는 플랫폼 업그레이드 전에 모든 단위 테스트를 실행하여 모든 사용자 지정 Apex 코드가 예상대로 작동하도록 보장한다.
|
|
버전 관리 (Versioned)
|
사용자 지정 Apex 코드는 다양한 버전의 API에 대해 저장할 수 있다.
|
Apex 언어 하이라이트
다른 개체 지향 프로그래밍 언어와 마찬가지로 다음은 Apex가 지원하는 언어 구성 중 일부입니다.
- 클래스, 인터페이스, 속성 및 컬렉션(배열 포함)
- 개체 및 배열 표기법
- 표현식, 변수 및 상수
- 조건문(if-then-else) 및 제어 플로 문(for 루프 및 while 루프)
다른 객체 지향 프로그래밍 언어와 달리 Apex는 다음을 지원
- Apex로서의 클라우드 개발은 클라우드에서 저장, 컴파일 및 실행됨.
- 데이터베이스 시스템의 트리거와 유사한 트리거.
- 데이터를 쿼리하고 검색하기 위해 직접 데이터베이스 호출 및 쿼리 언어를 만들 수 있는 Database 문.
- 트랜잭션 및 롤백.
- public 수정자보다 권한이 더 있는 global 액세스 수정자로, 네임스페이스와 애플리케이션 전반에 걸쳐 액세스를 허용함.
- 사용자 정의 코드의 버전 관리.
- 또한 Apex는 대소문자를 구분하지 않는 언어
(3) 데이터 형식
Apex는 Salesforce에 특정한 데이터 형식인 sObject 데이터 형식을 포함하여 다양한 데이터 형식을 지원한다.
- Integer, Double, Long, Date, Datetime, String, ID, Boolean 등과 같은 프리미티브.
- 일반 sObject 또는 계정, 연락처 또는 MyCustomObject__c와 같은 특정 sObject로서의 sObject 등
- 다양한 컬렉션, 사용자 정의 개체 등
Primitive Data Types 에 대한 설명 가이드 링크
(4) Apex Collections
lists, sets, maps 등이 있다.
| Lists | 모든 유형의 데이터를 담을 수 있으며 가장 중요한 컬렉션 유형 중 하나이다. 목록은 원시 유형, 컬렉션, sObject, 사용자 정의 유형, 기본 제공 Apex 유형 등 모든 데이터 유형의 정렬된 컬렉션 |
| Sets | 정렬되지 않은 컬렉션이다. 중복이 없는 고유한 값 집합이다. 컬렉션에 중복이 없도록 하려면 이 컬렉션을 선택해야 한다. |
| Maps | 각 값의 고유 키를 포함하는 키-값 쌍이다. 무언가를 빠르게 찾아야 할 때 사용된다. |
💡 List 주요 기능
- 중복과 널이 허용
- 리스트 컬렉션을 선언하는 키워드
- 첫 번째 항목의 인덱스 위치는 항상 0(0) 이다.
- 시간이 지남에 따라 동적으로 확장할 수 있다.
- 데이터 유형은 primitive 와 비 non-primitive 가 모두 가능
- 정의하려면 키워드 뒤에 오는 데이터 유형을 <> 문자 안에 사용
- List<datatype> listName = new List<datatype>();
💡 Set 주요 기능
- 원시 데이터 유형 및 sObject와 같은 모든 데이터 유형이 허용
- 인덱스가 없다.
- 중복 또는 null 값이 포함되지 않는다.
- Salesforce Apex에서 널리 사용되지 않는다.
- 서로 중첩된 컬렉션을 포함할 수 있다.
- 선언하려면 집합 키워드 뒤에 <> 문자 안에 기본 데이터 유형 이름을 사용
- Set<datatype> setName = new Set<datatype>(); </aside>
셋은 중복을 허용하지 않는 데이터 집합을 저장할 때 사용합니다. 고유한 값들을 저장할 때 유용
💡 Map 주요 기능
- 키와 값 모두에 모든 데이터 유형을 사용할 수 있다.
- null 값은 맵 키에 저장할 수 있다.
- 문자열 유형의 키는 대소문자를 구분한다.
- 선언하려면 맵 키워드 뒤에 <>로 묶인 키 및 값 데이터 유형을 사용해야 한다.
- Map<datatype_key,datatype_value> mapName = new Map<datatype_key,datatype_value>(); </aside>
특정 키를 사용하여 값을 빠르게 찾을 수 있다.
자세한 내용 페이지 참고
Apex Collections : List
List<String> colors = new List<String>();
String[] colors = new List<String>();
// 두 선언은 동일하다. 두번째는 배열 표기법을 사용하여 리스트를 할당한다.
List.add() 메서드로 새로운 요소를 추가하여 컬렉션을 늘린다.
List<String> colors = new List<String> { 'red', 'green', 'blue' };
// Add elements to a list after it has been created
List<String> moreColors = new List<String>();
moreColors.add('orange');
moreColors.add('purple');
배열 요소와 마찬가지로 대괄호 사이에 인덱스를 지정하여 읽을 수 있다.
get() 메서드를 사용하여 목록 요소를 읽을 수 있다.
// Get elements from a list
String color1 = moreColors.get(0);
String color2 = moreColors[0];
System.assertEquals(color1, color2);
// Iterate over a list to read elements
for(Integer i=0;i<colors.size();i++) {
// Write value to the debug log
System.debug(colors[i]);
}
Apex 코드로 이메일 보내기


Learn Apex Programming Basics | Salesforce Trailhead
Learn about Apex programming language features, classes, triggers, data types, and more. Get started with Apex on the Salesforce Lightning Platform.
trailhead.salesforce.com
디버그 검사
if (res.isSuccess()) {
System.debug('Email sent successfully');
} else {
sendResult = false;
System.debug('The following errors occurred: ' + res.getErrors());
}


2) sObject 사용하기
(1) sObject 사용하기
- Apex는 다른 프로그래밍 언어와 달리 새 레코드를 삽입하기 위해 데이터베이스 연결을 할 필요가 없다.
- Apex는 데이터베이스와 긴밀하게 통합되어 있으므로 Apex에서 직접 Salesforce 레코드 및 해당 필드에 액세스할 수 있다.
- Salesforce의 모든 레코드는 기본적으로 삽입되기 전에 Apex에서 sObject로 표시된다.
- 예를 들어 Account acc = new Account(Name='DK');
- Account = sObject datatype
- acc = sObject 변수
- new = 새 sObject 인스턴스 생성을 위한 키워드
- Account() = sObject 인스턴스를 생성하는 생성자
- Name ='DK' = 계정 sObject의 Name 필드 값을 초기화
- 또는 점 표기법을 사용하여 sObject에 필드를 추가할 수 있다.
Account acct = new Account();
acct.Name = 'DK';
acct.Phone = '(415)555-1212';
acct.NumberOfEmployees = 300;

Book 이라는 커스텀 오브젝트를 생성했을 때,
sObject sobj1 = new Account(Name='Trailhead');
sObject sobj2 = new Book__c(Name='Workbook 1');
sObject 변수를 선언하고 계정과 책 개체로 선언할 수 있다.
특정 sObject 데이터 유형으로 선언된 변수는 동일한 유형의 Salesforce 레코드만 참조할 수 있다.
일반 sObject를 특정 sObject로 캐스트(Cast) 할 수 있다.
// Cast a generic sObject to an Account
Account acct = (Account)myGenericSObject;
// Now, you can use the dot notation to access fields on Account
String name = acct.Name;
String phone = acct.Phone;
- 장점 : acct.Name과 같이 .을 활용하여 개체의 필드값을 사용할 수 있게 한다.
- 일반 sObject에서는 점 표기법 사용하여 필드에 접근 불가능하다. → get(), put() 메서드 필요
- Cast
- 한 데이터 타입을 다른 데이터 타입으로 변환하는 것
3) DML로 레코드 조작하기
(1) DML로 레코드 조작하기
DML
- Data Manipulation Language 데이터 조작 언어의 약자로, Apex에서 레코드를 삽입, 업데이트, 삭제, 삭제 취소할 수 있다.
- DML을 사용하면 단일 sObject 레코드에 대한 작업을 수행하거나 sObject 레코드 목록에 대해 한 번에 대량으로 작업을 수행할 수 있다.
- 레코드 처리를 위해 sObjects 목록을 사용하는 것이 효율적이며, 거의 모든 비즈니스 사례에서 데이터베이스를 업데이트해야 하므로 DML은 Apex의 핵심 부분이다.
💡 DML 문
- insert
- update
- upsert
- delete
- undelete
- merge </aside>
Insert
// Create the account sObject
Account acct = new Account(Name='Acme', Phone='(415)555-1212', NumberOfEmployees=100);
// Insert the account by using DML
insert acct;
- 이 예에서는 Acme 계정을 Salesforce에 추가.
- 계정 sObject가 먼저 생성된 다음 인수를 Salesforce에서 레코드를 유지하는 문인 insert 문에 전달한다.
Update
- 데이터베이스에 저장된 기존 레코드를 업데이트하는 데 사용됩니다. 업데이트 작업을 수행하려면 데이터베이스에서 기존 레코드를 쿼리해야 한다.
Account accountRecord =[Select Id, Name from Account where Name = 'Test Account' LIMIT 1];
accountRecord.Name = ‘Updated Name’;
// updating the account record using DML
update accountRecord;
// To verify the account name whether it is updated or not
Account accountRecord =[Select Id, Name from Account where Name = 'Updated Name' LIMIT 1];
// Display the account record in the debug logs
system.debug(‘account afterUpdate::::’+accountRecord);

Delete
- 삭제된 레코드는 Salesforce에서 영구적으로 삭제되는 것이 아니라 휴지통에 15일 동안 저장되며 15일 이내에 복원할 수 있다.
// Querying the account record
Account accn =[Select Id, Name from Account where Name = ‘Updated Name’ LIMIT 1];
// Deleting the account record using DML
Delete accn;
Undelete
- 휴지통에 저장된 레코드가 15일이 지나면 영업팀에서 영구적으로 삭제된다. 휴지통에 있는 레코드 삭제를 취소 해야 할 때 사용하며, 휴지통에서 삭제된 레코드를 쿼리 하려면 Soql 쿼리에서 ALL ROWS 매개 변수를 사용해야 한다.
// Querying the account record
Account accn = [select Id, Name from Account where Name =’Updated Name’ ALL ROWS];
// Undeleting the account record using DML
Undelete accn ;
// To verify whether account record is restored or not
Account accn = [select Id, Name from Account where Name =’Updated Name’];
// Display the account record in the debug logs
system.debug(‘restored account record:::’+accn);
Upsert
- 한 번의 호출로 새 레코드를 삽입하거나 기존 레코드를 업데이트할 수 있다. Upsert 문은 레코드의 ID를 사용하여 레코드가 이미 존재하는지 여부를 확인한다.
// Querying the account records 'Updated Name'인 Account 레코드를 쿼리
Account[] acctsList = [SELECT Id, Name, BillingCity
FROM Account WHERE Name='Updated Name'];
// 쿼리된 레코드를 반복하면서 Salesforce account로 변경
for (Account a : acctsList) {
a.Name ='Salesforce account';
}
// 'SF Account'인 새로운 Account 레코드를 생성
Account newAcct = new Account(Name ='SF Account');
// 새로운 레코드를 리스트에 추가: 생성한 새로운 Account 레코드를 acctsList 리스트에 추가
acctsList.add(newAcct);
// DML을 사용하여 계정 리스트를 업서트(업데이트 또는 삽입) 한다.
Upsert acctsList;
DML 문 예외
- DML 작업이 실패하면 DmlException 유형의 예외가 반환된다. 코드에서 예외를 포착하여 오류 조건을 처리할 수 있다.
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());
}
- 필수인 이름 필드 없이 계정을 삽입하려고 시도하기 때문에 이 예는 DmlException을 생성한다. catch 블록에서 예외가 포착되며,

Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Name]: [Name]
이러한 오류가 뜬다.
(2) Database 메서드
DML 작업을 수행하고 DML 문 대응 항목을 미러링하는 메서드를 제공하는 기본 제공 Database 클래스가 포함되어 있다.
- Database.insert()
- Database.update()
- Database.upsert()
- Database.delete()
- Database.undelete()
- Database.merge()
- DML 문과 달리 Database 메서드에는 작업이 부분적으로 성공해야 하는지 여부를 지정할 수 있는 allOrNone 매개변수(선택 사항)가 있다.
- 이 매개변수가 false로 설정된 경우 일부 레코드 집합에서 오류가 발생하면 성공한 레코드가 커밋되고 실패한 레코드에 대해 오류가 반환된다. 또한 부분 성공 옵션에서는 예외가 발생하지 않는다.
allOrNone이 false로 설정된 insert 메서드를 호출하는 방식
Database.insert(recordList, false);
Database 메서드는 각 레코드에 대한 성공 또는 실패 정보가 포함된 결과 개체를 반환한다. 예를 들어 삽입 및 업데이트 작업은 각각 Database.SaveResult 개체의 배열을 반환한다.
Database.SaveResult[] results = Database.**insert**(recordList, false);
upsert는 Database.UpsertResult
delete는 Database.DeleteResult 개체를 반환.
기본적으로 allOrNone 매개변수는 true로, 이는 Database 메서드가 DML 문과 동일하게 동작하고 오류가 발생할 경우 예외를 출력한다는 것을 의미한다.
다음 두 가지 문은 insert recordList; 문과 같다.
Database.insert(recordList);
Database.insert(recordList, true);
DML 문 또는 Database 메서드를 언제 사용?
| DML Statements | Database Methods |
| 대량 DML 처리 중에 발생하는 오류가 제어 플로를 즉시 중단하는 Apex 예외로 출력되도록 하려면 DML 문을 사용합니다(try...catch 블록 사용). 이 동작은 대부분의 데이터베이스 절차 언어에서 예외가 처리되는 방식과 유사 | 대량 DML 작업의 부분적인 성공을 허용하려면 Database 클래스 메서드를 사용하세요. 레코드가 실패하더라도 나머지 DML 작업은 계속 성공할 수 있습니다 |
| 부분 업데이트는 허용되지 않는다. 예를 들어 목록에 100개의 레코드가 있는 경우 모든 레코드가 업데이트 되거나 아무것도 업데이트되지 않는다. | 부분 업데이트를 허용. 데이터베이스의 매개변수 메서드를 참 또는 거짓으로 지정할 수 있다. 이 매개 변수에 거짓을 지정하고 레코드가 실패해도 나머지 DML 작업은 계속 성공할 수 있다. |
| 성공 및 실패 기록 목록을 가져올 수 없다. | 성공 및 실패 기록 목록을 얻을 수 있다. |
| DML 문에서 ConvertLead를 사용할 수 없음 | ConvertLead 연산은 데이터베이스 클래스에서만 사용할 수 있다. |
| Example − insert accounts; | Example − Database.insert(listName, False), 여기서 false는 부분 업데이트가 허용됨을 나타낸다. |
4) SOQL 쿼리 작성하기
(1) SOQL 기본 구문
- Salesforce에서 레코드를 읽으려면 쿼리를 작성해야 한다.
- Salesforce는 저장된 레코드를 읽는 데 사용할 수 있는 SOQL(Salesforce Object Query Language)을 제공한다.
- SOQL은 표준 SQL 언어와 유사하지만 Lightning Platform에 맞게 맞춤화 된다.
- SOQL이 Apex에 내장된 경우 인라인 SOQL로 간주
기본 SOQL 구문
Name 및 Phone이라는 두 필드가 있는 모든 계정 레코드를 검색하고 계정 sObject의 배열을 반환
Account[] accts = [SELECT Name,Phone FROM Account];
쿼리 편집기 사용


이 방법 외에 Salesforce inspector 크롬 확장프로그램 사용

SELECT fields FROM ObjectName [WHERE Condition]
- WHERE 절은 선택 사항
조건으로 쿼리 결과 필터링
SELECT Name,Phone FROM Account WHERE Name='SFDC Computing'
- 이름이 SFDC Computing인 계정만 검색합니다. 문자열에 대한 비교는 대소문자를 구분하지 않는다.
SELECT Name,Phone FROM Account WHERE (Name='SFDC Computing' AND NumberOfEmployees>25)
- WHERE 절에는 논리 연산자(AND, OR)와 괄호를 사용하여 그룹화된 여러 조건이 포함될 수 있다.
- 이 쿼리는 이름이 SFDC Computing이고 직원이 25명 이상인 모든 계정을 반환한다.
SELECT Name,Phone FROM Account WHERE (Name='SFDC Computing' OR (NumberOfEmployees>25 AND BillingCity='Los Angeles'))
- 모든 SFDC 컴퓨팅 계정
- 청구 도시가 로스앤젤레스이고 직원이 25명 이상인 모든 계정
쿼리 결과 정렬
SELECT Name,Phone FROM Account ORDER BY Name // Name 을 기준으로 정렬
SELECT Name,Phone FROM Account ORDER BY Name ASC // 알파벳순, 오름차순으로 정렬, 위도 동일
SELECT Name,Phone FROM Account ORDER BY Name DESC // 내림차순으로 정렬
반환되는 레코드 수 제한
Account oneAccountOnly = [SELECT Name,Phone FROM Account LIMIT 1];
- LIMIT n 절을 추가하여 임의의 수로 반환되는 레코드 수를 제한
(2) 결합하기
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);
SELECT fields FROM ObjectName [WHERE Condition]
- WHERE 절은 선택 사항
조건으로 쿼리 결과 필터링
SELECT Name,Phone FROM Account WHERE Name='SFDC Computing'
- 이름이 SFDC Computing인 계정만 검색합니다. 문자열에 대한 비교는 대소문자를 구분하지 않는다.
SELECT Name,Phone FROM Account WHERE (Name='SFDC Computing' AND NumberOfEmployees>25)
- WHERE 절에는 논리 연산자(AND, OR)와 괄호를 사용하여 그룹화된 여러 조건이 포함될 수 있다.
- 이 쿼리는 이름이 SFDC Computing이고 직원이 25명 이상인 모든 계정을 반환한다.
SELECT Name,Phone FROM Account WHERE (Name='SFDC Computing' OR (NumberOfEmployees>25 AND BillingCity='Los Angeles'))
- 모든 SFDC 컴퓨팅 계정
- 청구 도시가 로스앤젤레스이고 직원이 25명 이상인 모든 계정
쿼리 결과 정렬
SELECT Name,Phone FROM Account ORDER BY Name // Name 을 기준으로 정렬
SELECT Name,Phone FROM Account ORDER BY Name ASC // 알파벳순, 오름차순으로 정렬, 위도 동일
SELECT Name,Phone FROM Account ORDER BY Name DESC // 내림차순으로 정렬
반환되는 레코드 수 제한
Account oneAccountOnly = [SELECT Name,Phone FROM Account LIMIT 1];
- LIMIT n 절을 추가하여 임의의 수로 반환되는 레코드 수를 제한
(2) 결합하기
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);

SOQL 쿼리의 변수 액세스
WHERE 절의 targetDepartment 변수를 사용하는 방법
String targetDepartment = 'Wingo';
Contact[] techContacts = [SELECT FirstName,LastName
FROM Contact WHERE Department=:targetDepartment];
관련 레코드 쿼리하기
상위 레코드와 관련된 하위 레코드를 가져오려면 하위 레코드에 대한 내부 쿼리를 추가
SELECT Name, (SELECT LastName FROM Contacts) FROM Account WHERE Name = 'SFDC Computing'
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);

점 표기법을 사용하여 하위 개체(연락처)에서 상위(Account.Name)의 필드로 관계를 전환할 수 있다.
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);

SOQL For Loops를 사용하여 일괄 레코드 쿼리
SOQL for loops는 SOQL 쿼리에서 반환된 모든 sObject 레코드를 반복
for (variable : [soql_query]) {
code_block
}
또는
for (variable_list : [soql_query]) {
code_block
}
variable 및 variable_list는 모두 soql_query에서 반환하는 sObject와 동일한 유형이어야 한다.
insert new Account[]{new Account(Name = 'for loop 1'),
new Account(Name = 'for loop 2'),
new Account(Name = 'for loop 3')};
// 반환된 배치당 한 번씩 for 루프를 실행하는 sObject 목록 형식
// 레코드의
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); // 목록에 다음 세 개의 계정이 포함되어 있어야 합니다.
// named 'yyy'
System.assertEquals(1, i); // 단일 배치에 최대 200개의 레코드를 저장할 수 있고,
// 레코드가 세 개만 반환되어야 한다면,
// 루프는 한 번만 실행되어야 합니다.
- 루프는 200개의 sObject 배치에 대해 한 번씩 실행되므로 SOQL for loop의 sObject 목록 형식을 사용하는 것이 좋다. 이렇게 하면 레코드 배치에서 작업하고 DML 작업을 배치로 수행할 수 있으므로 거버너 제한에 도달하는 것을 방지할 수 있다.
5) SOSL
(1) SOSL에 대해
- **SOSL(Salesforce Object Search Language)**은 레코드에서 텍스트 검색을 수행하는 데 사용되는 Salesforce 검색 언어이다.
- SOSL을 사용하여 Salesforce의 여러 표준 및 사용자 정의 개체 레코드에서 필드를 검색.
- SOSL은 Apache Lucene과 유사하다.
List<List<SObject>> searchList = [FIND 'SFDC' IN ALL FIELDS
RETURNING Account(Name), Contact(FirstName,LastName)];
SOQL과 SOSL의 차이점과 유사점
- 한 번에 하나의 표준 또는 사용자 정의 개체만 쿼리할 수 있는 SOQL과 달리 단일 SOSL 쿼리는 모든 개체를 검색할 수 있다.
예를 들어, SOSL에서 'Digital'을 검색하면 필드 값이 'Digital' 또는 'The Digital Company'인 레코드가 반환되지만 SOQL은 필드 값이 'Digital'인 레코드만 반환한다.
SOQL을 사용할지 SOSL을 사용할지는 검색하려는 개체나 필드를 알고 있는지 여부와 기타 고려 사항에 따라 달라진다.
| SOQL | SOSL |
| SOQL은 SELECT SQL 문을 실행하고 조직 데이터베이스를 검색한다. | SOSL은 검색 색인에 대해 텍스트 기반 검색을 수행하는 프로그래밍 방식이다. |
| 단일 개체 또는 서로 관련된 여러 개체에서 데이터를 검색한다. | 필드 내에 존재하는 것으로 알고 있는 특정 용어에 대한 데이터를 검색한다. 필드 내의 여러 용어를 토큰화하고 이를 통해 검색 색인을 구축할 수 있으므로 SOSL 검색은 더 빠르고 관련성 높은 결과를 반환할 수 있다. |
| 지정된 기준을 충족하는 레코드 수를 계산한다. | 개체가 서로 관련되거나 관련되지 않을 수 있는 여러 개체 및 필드를 효율적으로 검색한다. |
| 쿼리의 일부로 결과를 정렬한다. | 부서 기능을 사용하여 조직의 특정 부서에 대한 데이터를 검색한다. |
| 숫자, 날짜 또는 확인란 필드에서 데이터를 검색한다. | 중국어, 일본어, 한국어 또는 태국어로 된 데이터를 검색합니다. CJKT 용어의 형태학적 토큰화는 정확한 결과를 보장하는 데 도움이 된다. |
String soslFindClause = 'Wingo OR SFDC';
List<List<sObject>> searchList = [FIND :soslFindClause IN ALL FIELDS
RETURNING Account(Name),Contact(FirstName,LastName,Department)];
Account[] searchAccounts = (Account[])searchList[0];
Contact[] searchContacts = (Contact[])searchList[1];
System.debug('Found the following accounts.');
for (Account a : searchAccounts) {
System.debug(a.Name);
}
System.debug('Found the following contacts.');
for (Contact c : searchContacts) {
System.debug(c.LastName + ', ' + c.FirstName);
}
- “Wingo" 또는 "SFDC" 키워드를 사용하여 SOSL 검색을 수행
- **Account**와 Contact 객체의 모든 필드에서 검색합니다.
- 검색 결과는 두 개의 리스트로 나뉘며, 하나는 Account 객체, 다른 하나는 Contact 객체에 대한 것.
- 각 검색된 **Account**의 **Name**과 각 검색된 **Contact**의 LastName, **FirstName**을 로그로 출력한다.

| SOSL 절 | 설명 |
| IN | 이메일, 이름, 전화번호 등 검색할 필드 유형을 제한 |
| LIMIT | 반환할 최대 행 수를 지정 |
| OFFSET | 검색 결과를 여러 페이지에 걸쳐 표시 |
| RETURNING | 반환할 객체와 필드를 제한 |
| WITH DATA CATEGORY | 반환할 데이터 범주를 지정 |
| WITH DivisionFilter | 반환할 분할 필드를 지정 |
| WITH NETWORK | 반환할 Experience Cloud 사이트 ID를 지정 |
| WITH PricebookId | 반환할 가격 목록 ID를 지정 |
'Salesforce > 정리' 카테고리의 다른 글
| 개발자 초급 정리 (1. Salesforce 개발 시작하기, 2. 샘플 앱 설치) (0) | 2024.08.29 |
|---|---|
| Apex Integration Services - Apex REST 및 SOAP 서비스를 사용하여 외부 앱과 통합하기 (트레일) (0) | 2024.08.26 |
| Experience Cloud 회원가입 부분 (CommunitiesSelfReg 추가) (0) | 2024.08.19 |
| Experiences Cloud 부분 (외부 회원가입) (0) | 2024.08.08 |
댓글