Salesforce

[세일즈포스] What is SOQL?( SOQL 사용법 및 예제)

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

💡 SOQL 쿼리란?

SOQL은 Salesforce Object Query Language의 약자!

SOQL을 사용해 조직의 데이터베이스에 저장되어 있는 정보를 읽을 수 있다.

세일즈포스는  SOQL을 이용해서 SQL의 기능을 한다.

SOQL의 구문은 SQL(Structured Query Language)과 유사하지만

그렇다고 SOQL이 SQL은 아니다.

 

사용할 때 주의!

단일 sObject에도 사용할 수 있긴하지만
System.QueryException: List has no rows for assignment to SObject
이 나타날 것이다.

쿼리가 실행될 때마다 단일 sObject가 반환된다는 것을 보장할 수 없는 경우 쿼리를 sObject 목록에 할당해야 함!

Player__c player = [SELECT Id from Player__c where Name = :username];
if (player != null)
 p = player.Id;

일치하는 사용자 이름을 가진 Player__c 레코드가 없으면 위의 코드는 실패!
null은 반환되지 않는다.

그렇기 때문에

Player__c[] players = [SELECT Id from Player__c where Name = :username];
if (players.size() > 0)
p = players[0].Id;

이렇게 적는게 더 안전하다.

단일쿼리 조회



public with sharing class SOQLQueriesInApex {
    public static List<Contact> searchForContacts(Id inputSearch) {

      // //0032w00000yTR43AAG
        List<Contact> contacts = [SELECT FirstName, LastName FROM Contact WHERE Id = :inputSearch];
        System.debug(contacts);
        return contacts;

    }
}

 

여러 쿼리 조회

public with sharing class SOQLSearchMultipleQueries {
    public static List<Contact> searchForContacts() {
        List<Contact> Contacts = [SELECT Id From Contact];

        System.debug('총' + Contacts.size());

        for (Contact c : Contacts) {
            System.debug(c);
        }

        return Contacts;
    }
}

 

Heap 크기 초과 방지하기 위한 방지

200개까지 가능!!!!

        for (List<Contact> Contacts : [SELECT Id From Contact]) {
            System.debug(Contacts);
            System.debug('총' + Contacts.size());
        }

-> 이렇게 쓰면 만약 220개 목록 반환한다면
첫번째 라인 200, 두번째 라인 20개

💡 일반 SQL과 차이점

- SELECT * 을 쓸 수 없다.

- 쿼리문만 지원한다( 일반 SOQL 처럼 스키마라든지, CRUD, 트랜잭션 등은 지원하지 않는다)

 

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

 

Apex 기본 및 데이터베이스

Apex를 사용하여 Salesforce에서 비즈니스 로직을 추가하고 데이터를 조작해 보세요.

trailhead.salesforce.com

 

사용방법

💡모든 계정 조회하기

 

1. 일단 계정을 추가

Account acct = new Account(
    Name='SFDC Computing',
    Phone='(415)555-1212',
    NumberOfEmployees=50,
    BillingCity='San Francisco');
insert acct;

ID acctID = acct.ID;

Contact con = new Contact(
    FirstName='Carol',
    LastName='Ruiz',
    Phone='(415)555-1212',
    Department='Wingo',
    AccountId=acctID); //acctID 여기에 넣겠다
insert con;

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;

 

2.

 click the Query Editor  tab.

SELECT Name,Phone FROM Account

이러면 이제 조회가 가능해진다!

 

 

💡조건으로 쿼리 결과 필터링

예1 )이름이 SFDC Computing이고 직원이 25명 이상인 모든 계정

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

 

 

예2) 모든 SFDC 컴퓨팅 계정 + 청구 도시가 로스앤젤레스이고 직원이 25명 이상인 모든 계정

 

SELECT Name,Phone

FROM Account

 WHERE (Name='SFDC Computing' OR (NumberOfEmployees>25 AND BillingCity='Los Angeles'))

 

 

💡반환되는 레코드 수 제한

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

-> 반환된 첫번째 계정을 검색

Limit  3이면 차례대로 3개 데이터만 보여주겠다.

SELECT 열명 FROM 테이블명 LIMIT 시작행, 개수

Limit 4, 4 -> 5 6 7 8

 

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

 

💡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.');
System.debug(accts);

 

💡SOQL 쿼리의 변수 액세스

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

 

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

System.debug(techContacts);

Int a =1; 일때 데이터 타입은 int로 바인딩, a라는  변수명이 바인딩, 1이라는 값이 바인딩

실행 이전에 값이 확정되면 정적 바인딩

실행 이후에 값이 확정되면 동적 바인딩

 

데이터타입 int ->컴파일 할 때 메모리에 할당되므로 정적 바인딩

a변수명 또한 메모리에 할당되므로 정적바인딩

 1은 실행시 할당되므로 동적바인딩이라고 한다.

 

자바는 메소드를 기본적으로 동적바인딩하기 때문에 메소드 오버라이딩이 가능

static또한 메모리를 한번밖에 할당하므로 컴파일시 메모리 할당 -> 정적 바인딩

 

정적바인딩 : 속도가 빨라서 효율적, 값이 변하지 않아 안정적

컴파일 시 이미값이 확정!

 

동적바인딩 : 값이 변할 수 있다. 들어올 값이 무엇인지 모르니 들어올 값보다 메모리공간을 차지하고 있어 메모리공간 낭비,,,,그래서 속도가 느려짐

 

 

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

 

 

💡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);

 

이름이 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);

 

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

10000개가 넘는 레코드에서 하나의 작업을 실행하는 유일한 방법은 Batch Apex 클래스를 작성