Skip to main content

SOQL 쿼리 작성하기

학습 목표

이 유닛을 완료하면 다음을 수행할 수 있습니다.
  • Apex에서 SOQL 쿼리를 작성할 수 있습니다.
  • Developer Console에서 쿼리 편집기를 사용하여 SOQL 쿼리를 실행할 수 있습니다.
  • 익명 Apex를 사용하여 Apex에 포함된 SOQL 쿼리를 실행할 수 있습니다.
  • 관련 레코드를 조회할 수 있습니다.
참고

참고

한국어로 학습하시겠어요? 이 배지에서는 Trailhead 실습과제 검증이 영어로 진행됩니다. 참조용 번역이 괄호로 제공됩니다. Trailhead Playground에서 (1) 로캘을 미국으로 바꾸고 (2) 언어를 영어로 바꾼 후 (3) 영문으로 표시된 값을 복사해 붙여 넣으세요. 여기에 나와 있는 지침을 따르세요.

원하는 언어로 Trailhead 사용하기 배지를 확인해 현지화된 Trailhead 경험을 활용하는 방법에 대해 자세히 알아보세요.

SOQL 시작하기

Salesforce에서 레코드를 읽으려면 쿼리를 작성해야 합니다. Salesforce는 저장된 레코드를 읽는 데 사용할 수 있는 SOQL(Salesforce Object Query Language)을 제공합니다. SOQL은 표준 SQL 언어와 유사하지만 Lightning Platform에 맞게 맞춤화됩니다.

Apex는 데이터베이스에 저장된 Salesforce 레코드에 직접 액세스할 수 있으므로 Apex 코드에 SOQL 쿼리를 포함하고 간단한 방식으로 결과를 얻을 수 있습니다. SOQL이 Apex에 내장된 경우 인라인 SOQL로 간주합니다.

Apex 코드에 SOQL 쿼리를 포함하려면 SOQL 문을 대괄호로 묶고 반환값을 sObject 배열에 할당합니다. 예를 들어 다음은 Name 및 Phone이라는 두 필드가 있는 모든 계정 레코드를 검색하고 계정 sObject의 배열을 반환합니다.
Account[] accts = [SELECT Name,Phone FROM Account];

전제 조건

이 유닛의 일부 쿼리는 조직에 계정과 연락처가 있을 것으로 예상합니다. 쿼리를 실행하기 전에 몇 가지 샘플 데이터를 만듭니다.

  1. Developer Console의 Debug(디버그) 메뉴에서 Execute Anonymous(익명 실행) 창을 엽니다.
  2. 창에 아래 코드 조각을 삽입하고 Execute(실행)를 클릭합니다.
// 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;
참고

Contact sObject의 Name(이름) 필드는 복합 필드입니다. 이는 연락처의 FirstName, LastName, MiddleName, Suffix 필드를 연결한 것입니다. 설정의 개체 관리자에는 복합 이름 필드만이 나타납니다. 하지만 이번 유닛의 샘플 Apex 코드는 복합 필드를 구성하는 개별 필드를 참조합니다.

쿼리 편집기 사용

Developer Console은 SOQL 쿼리를 실행하고 결과를 볼 수 있는 쿼리 편집기 콘솔을 제공합니다. 쿼리 편집기는 데이터베이스를 검사하는 빠른 방법을 제공합니다. SOQL 쿼리를 Apex 코드에 추가하기 전에 테스트하는 좋은 방법입니다. 쿼리 편집기를 사용하는 경우 SOQL 문을 둘러싸는 Apex 코드 없이 SOQL 문만 제공해야 합니다.

다음 SOQL 예제를 실행해 보겠습니다.

  1. Developer Console에서 Query Editor(쿼리 편집기) 탭을 클릭합니다.
  2. 쿼리 편집기 아래의 첫 번째 상자에 다음을 복사하여 붙여넣은 다음 Execute(실행)를 클릭합니다.
SELECT Name,Phone FROM Account

조직의 모든 계정 레코드는 쿼리 결과 섹션에 필드가 있는 행으로 나타납니다.

기본 SOQL 구문

다음은 기본 SOQL 쿼리의 구문입니다.

SELECT fields FROM ObjectName [WHERE Condition]

WHERE 절은 선택 사항입니다. 아주 간단한 쿼리부터 시작하겠습니다. 예를 들어 다음 쿼리는 계정을 검색하고 각 계정에 대한 이름 및 전화 필드를 가져옵니다.

SELECT Name,Phone FROM Account

쿼리는 두 부분으로 구성됩니다.

  1. SELECT Name,Phone: 이 부분은 검색할 필드를 나열합니다. 필드는 쉼표로 구분된 목록에서 SELECT 키워드 뒤에 지정됩니다. 또는 쉼표가 필요하지 않은 경우 필드를 하나만 지정할 수 있습니다(예: SELECT Phone).
  2. FROM Account: 이 부분은 검색하려는 표준 또는 맞춤형 객체를 지정합니다. 이 예에서는 계정입니다. Invoice_Statement라는 맞춤형 객체의 경우 Invoice_Statement__c입니다.
참고

추가 기본 정보

다른 SQL 언어와 달리 모든 필드에 *를 지정할 수는 없습니다. 명시적으로 가져오려는 모든 필드를 지정해야 합니다. SELECT 절에 지정하지 않은 필드에 액세스하려고 하면 해당 필드가 검색되지 않았기 때문에 오류가 발생합니다.

쿼리에 Id 필드가 지정되었는지 여부에 관계없이 Apex 쿼리에 항상 반환되기 때문에 쿼리에 Id 필드를 지정할 필요가 없습니다. 예를 들어 SELECT Id,Phone FROM AccountSELECT Phone FROM Account는 동일 문입니다. 최소한 하나의 필드 SELECT Id FROM Account를 나열해야 하므로 검색하는 유일한 필드일 때 Id 필드를 지정할 수 있는 유일한 경우입니다. 지정하지 않으면 ID 필드가 표시되지 않으므로 쿼리 편집기에서 쿼리를 실행할 때도 ID 필드를 지정할 수 있습니다.

조건으로 쿼리 결과 필터링

조직에 둘 이상의 계정이 있는 경우 모두 반환됩니다. 특정 조건을 충족하는 계정으로 반환되는 계정을 제한하려면 WHERE 절 안에 이 조건을 추가할 수 있습니다. 다음 예에서는 이름이 SFDC Computing인 계정만 검색합니다. 문자열에 대한 비교는 대소문자를 구분하지 않습니다.

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

WHERE 절에는 논리 연산자(AND, OR)와 괄호를 사용하여 그룹화된 여러 조건이 포함될 수 있습니다. 예를 들어, 이 쿼리는 이름이 SFDC Computing이고 직원이 25명 이상인 모든 계정을 반환합니다.

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

이는 더 복잡한 조건을 가진 또 다른 예입니다. 이 쿼리는 다음의 모든 레코드를 반환합니다.

  • 모든 SFDC 컴퓨팅 계정
  • 청구 도시가 로스앤젤레스이고 직원이 25명 이상인 모든 계정
SELECT Name,Phone FROM Account WHERE (Name='SFDC Computing' OR (NumberOfEmployees>25 AND BillingCity='Los Angeles'))
참고

추가 기본 정보

등호 연산자(=) 비교를 위해 LIKE 연산자를 사용하여 퍼지 일치를 수행할 수 있습니다. 예를 들어 조건 WHERE Name LIKE 'SFDC%’를 사용하여 이름이 SFDC로 시작하는 모든 계정을 검색할 수 있습니다. % 와일드카드 문자는 임의의 문자와 일치하거나 일치하지 않습니다. 대조적으로 _ 문자는 하나의 문자만 일치시키는 데 사용할 수 있습니다.

쿼리 결과 정렬

쿼리가 실행되면 특정 순서 없이 Salesforce에서 레코드를 반환하므로 쿼리가 실행될 때마다 반환된 배열의 레코드 순서가 동일하다고 신뢰할 수 없습니다. 그러나 ORDER BY 절을 추가하고 레코드 집합을 정렬할 필드를 지정하여 반환된 레코드 집합을 정렬하도록 선택할 수 있습니다. 이 예에서는 이름 필드를 기준으로 검색된 모든 계정을 정렬합니다.

SELECT Name,Phone FROM Account ORDER BY Name

기본 정렬 순서는 알파벳순으로 ASC로 지정됩니다. 이전 문은 다음과 같습니다.

SELECT Name,Phone FROM Account ORDER BY Name ASC

순서를 반대로 하려면 다음과 같이 내림차순으로 DESC 키워드를 사용하세요.

SELECT Name,Phone FROM Account ORDER BY Name DESC

숫자 및 텍스트 필드를 포함한 대부분의 필드에서 정렬할 수 있습니다. 서식 있는 텍스트 및 다중 선택 선택 목록과 같은 필드는 정렬할 수 없습니다.

쿼리 편집기에서 이러한 SOQL 문을 시도하고 이름 필드에 따라 반환된 레코드의 순서가 어떻게 변경되는지 확인합니다.

반환되는 레코드 수 제한

LIMIT n 절을 추가하여 임의의 수로 반환되는 레코드 수를 제한할 수 있습니다. 여기서 n은 반환할 레코드 수입니다. 결과 집합을 제한하는 것은 반환되는 레코드에 신경 쓰지 않고 레코드의 하위 집합으로 작업하려는 경우에 편리합니다. 예를 들어, 이 쿼리는 반환된 첫 번째 계정을 검색합니다. LIMIT 1을 사용할 때 반환된 값은 하나의 계정이며 배열이 아닙니다.

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

모든 조각을 함께 결합하기

다음 순서로 하나의 쿼리에서 선택적 절을 결합할 수 있습니다.

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

Developer Console의 Execute Anonymous(익명 실행) 창을 사용하여 Apex에서 다음 SOQL 쿼리를 실행합니다. 그런 다음 디버그 로그에서 디버그 문을 검사합니다. 하나의 샘플 계정을 반환해야 합니다.

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 쿼리의 변수 액세스

Apex의 SOQL 문은 앞에 콜론(:)이 있는 경우 Apex 코드 변수 및 표현식을 참조할 수 있습니다. SOQL 문 내에서 지역 변수를 사용하는 것을 bind라고 합니다.

이 예는 WHERE 절의 targetDepartment 변수를 사용하는 방법을 보여줍니다.

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

관련 레코드 쿼리

Salesforce의 레코드는 조회 관계 또는 마스터-디테일 관계와 같은 관계를 통해 서로 연결할 수 있습니다. 예를 들어 연락처는 계정에 대한 조회 관계가 있습니다. 연락처를 만들거나 업데이트할 때 계정과 연결할 수 있습니다. 동일한 계정과 연결된 연락처가 계정 페이지의 관련 목록에 나타납니다. Salesforce 사용자 인터페이스에서 관련 레코드를 볼 수 있는 것과 같은 방식으로 SOQL에서 관련 레코드를 쿼리할 수 있습니다.

상위 레코드와 관련된 하위 레코드를 가져오려면 하위 레코드에 대한 내부 쿼리를 추가하세요. 내부 쿼리의 FROM 절은 Salesforce 개체 이름이 아닌 관계 이름에 대해 실행됩니다. 이 예에는 반환된 각 계정과 연결된 모든 연락처를 가져오는 내부 쿼리가 포함되어 있습니다. FROM 절은 계정과 연락처를 연결하는 계정의 기본 관계인 연락처 관계를 지정합니다.

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

다음 예는 Apex에 예제 SOQL 쿼리를 포함하고 sObject에서 연락처 관계 이름을 사용하여 SOQL 결과에서 하위 레코드를 가져오는 방법을 보여줍니다.

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)의 필드로 관계를 전환할 수 있습니다. 예를 들어 다음 Apex 코드 조각은 이름이 Carol인 연락처 레코드를 쿼리하고 계정과 연락처 간의 관계를 탐색하여 Carol과 연결된 계정의 이름을 검색할 수 있습니다.

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);
참고

참고

이 섹션의 예제는 표준 개체를 기반으로 합니다. 맞춤형 관계를 사용하여 맞춤형 객체를 함께 연결할 수도 있습니다. 맞춤형 관계 이름은 __r 접미사로 끝납니다. 예를 들어 인보이스 명세서는 Invoice_Statement__c 맞춤형 객체의 Line_Items__r 관계를 통해 개별 항목에 연결됩니다.

SOQL For Loops를 사용하여 일괄 레코드 쿼리

SOQL for loop를 사용하면 for 루프 내부에 SOQL 쿼리를 포함할 수 있습니다. SOQL 쿼리의 결과는 루프 내에서 반복될 수 있습니다. SOQL for loop는 레코드 검색을 위해 다른 방법을 사용하며 즉, SOAP API의 query 및 queryMore 메서드를 호출하여 효율적인 청킹을 사용하여 레코드를 검색합니다. SOQL for loop를 사용하면 heap 크기 제한에 도달하는 것을 방지할 수 있습니다.

SOQL for loops는 SOQL 쿼리에서 반환된 모든 sObject 레코드를 반복합니다. SOQL for loop의 구문은 다음 중 하나입니다.
for (variable : [soql_query]) {
    code_block
}
또는
for (variable_list : [soql_query]) {
    code_block
}

variablevariable_list는 모두 soql_query에서 반환하는 sObject와 동일한 유형이어야 합니다.

루프는 200개의 sObject 배치에 대해 한 번씩 실행되므로 SOQL for loop의 sObject 목록 형식을 사용하는 것이 좋습니다. 이렇게 하면 레코드 배치에서 작업하고 DML 작업을 배치로 수행할 수 있으므로 거버너 제한에 도달하는 것을 방지할 수 있습니다.

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
계속해서 무료로 학습하세요!
계속 진행하려면 계정을 가입하세요.
얻을 수 있는 이점
  • 커리어 목표에 대한 개인화된 권장 사항 제공받기
  • 실습 과제 및 퀴즈를 통해 스킬 연습
  • 진행 상황을 추적하고 고용주에게 공유
  • 멘토십과 커리어 기회에 연결