Skip to content

artysta/salesforce-notes

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 

Repository files navigation

#1 Relationships & relationship SOQL queries examples.

There are two main relationship types in Salesforce Lookup Relationship and Master-Detail relationships. There are some differences betweent these relationships:

Lookup Relationship Master-Detail Relationship
up to 25 per one object up to 2 per one object
parent is not a required field parent field on a child is required
deleting a parent does not delete a child deleting a parent automatically deletes a child
can be multiple layers deep a child of one master detail relationship cannot be the parent of another one
no impact on a security and access access to a parent determines access to a children
- the standard object cannot be on the detail side of a relationship with a custom object

Lookup relationships:

Standard objects:

Account (Parent), Contact (Child) - Lookup field is on the Contact standard object | One Account can have 0 or many Contacts | One Contact can have 0 or one Account.

Child-to-parent queries:

SELECT Name, Phone, Account.Id, Account.Name FROM Contact

screen-1.png

SELECT Name, Phone, Account.Id, Account.Name FROM Contact WHERE Account.Id = '0010900000iMM6GAAW'

screen-2.png

Parent-to-child queries:

SELECT Id, Name, (SELECT Name, Phone FROM Contacts) FROM Account

screen-3.png

SELECT Id, Name, (SELECT Name, Phone FROM Contacts) FROM Account WHERE Id = '0010900000iMM6DAAW'

screen-4.png

Custom objects:

Vehicle (Parent), Driver (Child) - Lookup field is on the Driver custom object | One Vehicle can have 0 or many Drivers | One Driver can have 0 or one Vehicle

Child-to-parent queries:

SELECT Name, Nationality__c, Vehicle__r.Id, Vehicle__r.Manufacturer__c FROM Driver__c
SELECT Name, Nationality__c, Vehicle__r.Id, Vehicle__r.Manufacturer__c FROM Driver__c WHERE Vehicle__r.Id = 'a000900000FThKjAAL'

Parent-to-child queries:

SELECT Id, Name, Manufacturer__c, (SELECT Name, Nationality__c FROM Drivers__r) FROM Vehicle__c
SELECT Id, Name, Manufacturer__c, (SELECT Name, Nationality__c FROM Drivers__r) FROM Vehicle__c WHERE Id = 'a000900000FThKjAAL'

Notice that it is pretty important to use __c suffix when you are using/querying custom object and __r suffix when you want to query fields of realated object. Also remember to use plural form in the second SELECT statement when you use parent-to-child queries.

Master-Detail relationships:

The Master-Detail queries look exactly the same as for the Lookup.

Standard objects:

Account (Parent/Master), Entitlement (Child/Detail) - Master-detail field is on the Entitlement standard object | One Account can have 0 or many Entitlements | One Entitlement must have exactly one Account.

Child-to-parent queries:

SELECT Name, Status, Account.Id, Account.Name FROM Entitlement
SELECT Name, Status, Account.Id, Account.Name FROM Entitlement WHERE Account.Id = '0010900000g6FkaAAE'

Parent-to-child queries:

SELECT Id, Name, (SELECT Name, Status FROM Entitlements) FROM Account
SELECT Id, Name, (SELECT Name, Status FROM Entitlements) FROM Account WHERE Id = '0010900000iMM6FAAW'

#2 Batches, Scheduled Jobs & state.

The idea of Apex batch jobs is to work on the huge number (thousands / millions) of records. Apex Batch class has to implement Database.Batchable interface and its 3 methods:

  • start (pre-processing operations) - here the records are being collected
  • execute - here some operations are performed on the provided records
  • finish (post-processing operations) - this method is called once all operations are done

Here is a pretty simple implementation of this interface. This batch just deletes every Opportunity with the stage name 'Closed Won' or 'Closed Lost'.

public class OpportunitiesCleanerBatch implements Database.Batchable<sObject> {
    public Database.QueryLocator start(Database.BatchableContext context) {
        System.debug('Job started!');
        return Database.getQueryLocator([SELECT StageName FROM Opportunity]);
    }
    
    public void execute(Database.BatchableContext context, List<Opportunity> opportunities) {
        List<Opportunity> opportunitiesToRemove = new List<Opportunity>();
        
        for (Opportunity o : opportunities) {
            if (o.StageName == 'Closed Won' || o.StageName == 'Closed Lost') {
                opportunitiesToRemove.add(o);
            }
        }
        
        delete opportunitiesToRemove;

        System.debug(
            String.format(
                '{0} opportunities with the \"{1}\" or \"{2}\" stage name have been deleted.',
                new List<String> { String.valueOf(opportunitiesToRemove.size()), 'Closed Won', 'Closed Lost' }
            )
        );
    }
    
    public void finish(Database.BatchableContext context) {
        System.debug('Job finished!');
    }
}

Here is the code that allows to run the batch above from Developer Console or within another class:

OpportunitiesCleanerBatch oppCleanerBatch = new OpportunitiesCleanerBatch();
Database.executeBatch(oppCleanerBatch);

The interface, that works really good with batches is Schedulable interface. It allows to schedule an instance of the Apex class to run at a specific time.

Here is implementation of Schedulable interface that runs OpportunitiesCleanerBatch.

public class OpportunitiesCleanerBatchSchedule implements Schedulable {
    public void execute(SchedulableContext context) {
        OpportunitiesCleanerBatch oppCleanerBatch = new OpportunitiesCleanerBatch();
        Database.executeBatch(oppCleanerBatch);
    }
}

There are two possibilities to schedule a job. Obviously you can run the code from the Developer Console or within another class.

OpportunitiesCleanerBatchSchedule scheduledBatch = new OpportunitiesCleanerBatchSchedule();
// String sch = 'SECONDS MINUTES HOURS DAY_OF_MONTH MONTH DAY_OF_WEEK OPTIONAL_YEAR';
String sch = '00 45 6-22 ? * * *';
System.schedule('Opportunities Cleaner Batch', sch, scheduledBatch);

You can also use UI to do this: Setup -> Apex Jobs -> Apex Classes -> Schedule Apex. There you have to add job name, select proper class and choose specific time and how often you want the job to run.


As the Salesforce documentation says:

Each execution of a batch Apex job is considered a discrete transaction.

Implementing Database.Stateful interface in the case of the batches allows to maintain state across the transactions.

Example:

Lets say that we have 1028 Case records in our Salesforce database. We have written a simple batch (this batch does nothing - I just want this example to be as simple as possible). This is how does it looks like:

public class CasesBatch implements Database.Batchable<sObject> {
    private Integer count = 0;    
    
    public Database.QueryLocator start(Database.BatchableContext context){
        System.debug('count (start): ' + count);
        String exampleQuery = 'SELECT Id FROM Case';
        return Database.getQueryLocator(exampleQuery);
    }
    
    public void execute(Database.BatchableContext context, List<sObject> scope){
		this.count++;
        System.debug('scope.size(): ' + scope.size());
        System.debug('count (execute): ' + count);
    }
    
    public void finish(Database.BatchableContext BC){
        System.debug('count (finish): ' + count);
    }
}

Lest run our batch using the code below:

Database.executeBatch(new CasesBatch());

We have got couple of logs:

#1
19:29:03:020 USER_DEBUG [5]|DEBUG|count (start): 0

#2
19:29:03:001 USER_DEBUG [12]|DEBUG|scope.size(): 200
19:29:03:001 USER_DEBUG [13]|DEBUG|count (execute): 1

#3
19:29:03:002 USER_DEBUG [12]|DEBUG|scope.size(): 200
19:29:03:002 USER_DEBUG [13]|DEBUG|count (execute): 1

#4
19:29:04:001 USER_DEBUG [12]|DEBUG|scope.size(): 200
19:29:04:001 USER_DEBUG [13]|DEBUG|count (execute): 1

#5
19:29:04:001 USER_DEBUG [12]|DEBUG|scope.size(): 200
19:29:04:001 USER_DEBUG [13]|DEBUG|count (execute): 1

#6
19:29:04:001 USER_DEBUG [12]|DEBUG|scope.size(): 200
19:29:04:001 USER_DEBUG [13]|DEBUG|count (execute): 1

#7
19:29:04:001 USER_DEBUG [12]|DEBUG|scope.size(): 28
19:29:04:001 USER_DEBUG [13]|DEBUG|count (execute): 1

#8
19:29:04:025 USER_DEBUG [17]|DEBUG|count (finish): 0

Lets implement Database.Stateful interface now:

public class CasesBatch implements Database.Batchable<sObject>, Database.Stateful {
    private Integer count = 0;    
    
    public Database.QueryLocator start(Database.BatchableContext context){
        System.debug('count (start): ' + count);
        String exampleQuery = 'SELECT Id FROM Case';
        return Database.getQueryLocator(exampleQuery);
    }
    
    public void execute(Database.BatchableContext context, List<sObject> scope){
		this.count++;
        System.debug('scope.size(): ' + scope.size());
        System.debug('count (execute): ' + count);
    }
    
    public void finish(Database.BatchableContext BC){
        System.debug('count (finish): ' + count);
    }
}

Lets run the batch again and check the logs:

#1
19:35:15:019 USER_DEBUG [5]|DEBUG|count (start): 0

#2
19:35:16:002 USER_DEBUG [12]|DEBUG|scope.size(): 200
19:35:16:002 USER_DEBUG [13]|DEBUG|count (execute): 1

#3
19:35:16:001 USER_DEBUG [12]|DEBUG|scope.size(): 200
19:35:16:001 USER_DEBUG [13]|DEBUG|count (execute): 2

#4
19:35:16:001 USER_DEBUG [12]|DEBUG|scope.size(): 200
19:35:16:001 USER_DEBUG [13]|DEBUG|count (execute): 3

#5
19:35:16:001 USER_DEBUG [12]|DEBUG|scope.size(): 200
19:35:16:001 USER_DEBUG [13]|DEBUG|count (execute): 4

#6
19:35:16:001 USER_DEBUG [12]|DEBUG|scope.size(): 200
19:35:16:001 USER_DEBUG [13]|DEBUG|count (execute): 5

#7
19:35:16:001 USER_DEBUG [12]|DEBUG|scope.size(): 28
19:35:16:001 USER_DEBUG [13]|DEBUG|count (execute): 6

#8
19:35:16:020 USER_DEBUG [17]|DEBUG|count (finish): 6

#3 Some useful Apex code snippets.

  • Send an email + debug.
String subject = 'Email Subject.';
String body = 'Email Body.';
String[] addresses = new String[] { 'test@mail.com' };

Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();

mail.setToAddresses(addresses);
mail.setSubject(subject);
mail.setPlainTextBody(body);

Messaging.SendEmailResult[] results = Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });

for (Messaging.SendEmailResult r : results) {
    System.debug(r);
}
  • Get picklist values for picklist field (StageName field values of Opportunity standard object in this case).
DescribeFieldResult stageNameField = Opportunity.StageName.getDescribe();

for (Integer i = 0; i < stageNameField.getPicklistValues().size(); i++) {
    System.debug(String.format(' StageName {0}: {1}', new List<String> { String.valueOf(i), stageNameField.getPicklistValues()[i].value }));
}
  • Run batch manually using Anonymous Apex.
ExampleBatch batch = new ExampleBatch();
Database.executeBatch(batch);
  • Schedule a job using Anonymous Apex.
ExampleBatchSchedule scheduledBatch = new ExampleBatchSchedule();
// String sch = 'SECONDS MINUTES HOURS DAY_OF_MONTH MONTH DAY_OF_WEEK OPTIONAL_YEAR';
String sch = '00 45 6-22 ? * * *';
System.schedule('Example Batch', sch, scheduledBatch);
  • Easy way to get set of object Ids.
List<SObject> opportunities = [SELECT Id, Name FROM Opportunity LIMIT 10];
Set<Id> opportunitiesIds = (new Map<Id, SObject>(opportunities)).keySet();	

#4 Aura Components + Apex Controllers.

Below you can find an Aura Component which is using Apex Controller to read and display data. It doesn't look so good, but it is one of the simplest examples. In this case data loads after clicking the Get Opportunities button.

aura-1.png

Aura Component: opportunitiesList.cmp
<aura:component implements="flexipage:availableForAllPageTypes" controller="OpportunitiesController">
    <aura:attribute name="opportunities" type="Opportunity[]"/>
    <!-- We are calling component controller method here (NOT Apex method!) -->
    <button onclick="{!c.getOpportunities}">Get Opportunities</button>
    <p>Opportunities list:</p>
    <ul>
        <aura:iteration var="opportunity" items="{!v.opportunities}">
            <li>Id: {!opportunity.Id}, Name: {!opportunity.Name}, StageName: {!opportunity.StageName}</li>
        </aura:iteration>
    </ul>
</aura:component>
JavaScript Controller: opportunitiesListController.js
({
    getOpportunities: function(component, event, helper){
        // We are calling Apex controller method here.
        var action = component.get("c.getOpportunitiesList");
        action.setCallback(this, function(response){
            var state = response.getState();
            if (state === "SUCCESS") {
                component.set("v.opportunities", response.getReturnValue());
            }
        });
        $A.enqueueAction(action);
    }
})
Apex Controller: OpportunitiesController.cls
public with sharing class OpportunitiesController {
    @AuraEnabled
    public static List<Opportunity> getOpportunitiesList() {
        return [SELECT Id, Name, StageName, CreatedDate
                FROM Opportunity
                ORDER BY CreatedDate DESC
                LIMIT 10];
    }
}

Of course we can use datatable to achieve much better appearance. In this case there is no need to click the button to load data.

aura-2.png

Aura Component: opportunitiesList.cmp
<aura:component implements="flexipage:availableForAllPageTypes,force:hasRecordId" controller="OpportunitiesController" access="global">
    <aura:attribute name="columns" type="list"/>
    <aura:attribute name="opportunities" type="Opportunity[]"/>
    <!-- We are calling component controller method here (NOT Apex method!) -->
    <aura:handler name='init' action="{!c.getOpportunities}" value="{!this}"/>
    <!-- <button onclick="{!c.getOpportunities}">Get Opportunities</button> -->
    <lightning:card title="Opportunities List">
        <lightning:datatable keyField="id"
                             data="{!v.opportunities}"
                             columns="{!v.columns}"
                             hideCheckboxColumn="true"
                             maxColumnWidth="1000"
                             minColumnWidth="150"/>
    </lightning:card>
</aura:component>
JavaScript Controller: opportunitiesListController.js
({
    getOpportunities: function (component, event, helper) {
        component.set('v.columns', [
            {label: 'Id', fieldName: 'Id', type: 'text'},
            {label: 'Name', fieldName: 'Name', type: 'text'},
            {label: 'Stage Name', fieldName: 'StageName', type: 'text'},
            {label: 'Creation Date', fieldName: 'CreatedDate', type: 'date'},
        ]);
            
        // We are calling Apex controller method here.
        var action = component.get("c.getOpportunitiesList");
        action.setCallback(this, function(response){
            var state = response.getState();
            if (state === "SUCCESS") {
                component.set("v.opportunities", response.getReturnValue());
            }
        });
        $A.enqueueAction(action);
    }
})

#5 Object Oriented Programming in Apex.

What is Apex?

As the Salesforce documentation says:

Apex is a strongly typed, object-oriented programming language that allows developers to execute flow and transaction control statements on Salesforce servers in conjunction with calls to the API

It is just an OOP language that is pretty similar to Java or C#.

Below you can find some informations about classes and interfaces:

Virtual Abstract Interface
implementation full class implementation partial class implementation it's just a "contract"
keyword extends extends implements
can have variables and properties yes yes no
can have defined methods yes yes no
can be instantiated (directly) yes no no
can have abstract methods no yes yes

Here is really simple example, how this all works together in Apex:

Tuningable.cls
public interface Tuningable {
    // Interface methods cannot have a body.
    void tuning();
}
Vehicle.cls
// This class is abstract so it cannot be instantiated. It can be extended.
public abstract class Vehicle {
    // Automatic property - like in C#.
    public String Name { get; set; }
    public String Color { get; set; }
    
    public Vehicle(String name, String color) {
        this.Name = name;
        this.Color = color;
    }
    
    // Abstract method that has to be implemented by the subclass. Abstract methods have no body.
    public abstract Integer getMaxSpeed();
    
    // Virtual method can (but not has to) be overridden by the subclass.
    public virtual String getInfo() {
        return String.format('I am a {0} {1}.', new List<String> { this.Color, this.Name });
    }
}
BaseCar.cls
// This is a virtual class so it can be extended by other classes. It also can be instantiated.
public class BaseCar extends Vehicle {
    public Integer MaxSpeed { get; set; }
    
    // We can call super class constructor by using 'super' keyword - like in Java.
    public BaseCar(String name, String color, Integer maxSpeed) {
        super(name, color);
        this.MaxSpeed = maxSpeed;
    }
    
    public override Integer getMaxSpeed() {
        return this.MaxSpeed;
    }
    
    // We can call super class method by using 'super' keyword - like in Java.
    // We have to use 'override' keyword if we want to override superclass method.
    public override String getInfo() {
        return String.format('{0} My max speed is {1} km/h.',
                             new List<String> { super.getInfo(), String.valueOf(this.MaxSpeed) });
    }
}
SportsCar.cls
// We cannot extend this class. We can extend class only if it is abstract or virtual.
public class SportsCar extends BaseCar implements Tuningable {
    public Boolean HasTurbo { get; set; }
    
    public SportsCar(String name, String color, Integer maxSpeed) {
        super(name, color, maxSpeed);
    }
    
    // We can call another constructor by using 'this' keyword - like in Java.
    public SportsCar(String name, String color, Integer maxSpeed, Boolean hasTurbo) {
        this(name, color, maxSpeed);
        this.hasTurbo = hasTurbo;
    }
    
    // We do not have to (and even cannot) use 'override' keyword if we are implementing interface method.
    public void tuning() {
        maxSpeed += 10;
    }
}
Example:
SportsCar car = new SportsCar('Nissan', 'Blue', 100, true);
car.tuning();
System.debug(car.getInfo()); // 20:48:36:017 USER_DEBUG [70]|DEBUG|I am a Blue Nissan. My max speed is 110 km/h.

#5 Apex Governor Limits.

What are the Apex Governor Limits?

As the Salesforce documentation says:

Because Apex runs in a multitenant environment, the Apex runtime engine strictly enforces limits so that runaway Apex code or processes don’t monopolize shared resources.

Below you can find one of the most common limits in Salesforce (the table is not complete):

Description Synchronous Limit Asynchronous Limit
number of SOQL queries 100 200
number of records retrieved by SOQL queries 50,000 50,000
number of records retrieved by Database.getQueryLocator 10,000 10,000
number of SOSL queries 20 20
number of records retrieved by a single SOSL query 2,000 2,000
number of DML statements issued 150 150
number of records processed as a result of DML statements 10,000 10,000
heap size 6 MB 12 MB
maximum CPU time on the Salesforce servers 10,000 ms 60,000 ms

Exceeding the limit will cause an exceptions to occur. Some of examples:

Too many SOQL queries (synchronous limit):

// 'System.LimitException: Too many SOQL queries: 101' will be thrown because max number of (synchronous) SOQL queries is equal to 100.
static void queryCases() {
    for (Integer i = 0; i < 101; i++) {
        Case c = [SELECT Id FROM Case];
    }
}

Too many SOQL queries (asynchronous limit):

// 'System.LimitException: Too many SOQL queries: 201' will be thrown because max number of (asynchronous) SOQL queries is equal to 200.
@future
static void queryCases() {
    for (Integer i = 0; i < 201; i++) {
        Case c = [SELECT Id FROM Case];
    }
}

Too many DML statements:

// 'System.LimitException: Too many DML statements: 151' will be thrown because max number of DML statements is equal to 150.
static void insertCases() {
    for (Integer i = 0; i < 151; i++) {
        insert new Case();
    }
}

Too many SOSL queries:

// 'System.LimitException: Too many SOSL queries: 21' will be thrown because max number of SOSL queries is equal to 20.
static void queryCases() {
    for (Integer i = 0; i < 21; i++) {
        List<List<sObject>> sObjects = [FIND 'New' IN ALL FIELDS RETURNING Case(Status)];
    }
}

Too many DML rows:

// 'System.LimitException: Too many DML rows: 10001' will be thrown because max number of records processed as a result of DML statements is equal to 10 000.
static void insertCases() {
    List<Case> cases = new List<Case>();
    
    for (Integer i = 0; i < 10001; i++) {
        cases.add(new Case());
    }
    
    insert cases;
}

#6 Apex Triggers.

Apex Trigger is a code that executes before or after any operations are performed on the specific record.

Below you can find an example of pretty simple trigger that updates Vehicle name by appending current user name to it.

trigger VehicleTrigger on Vehicle__c (before insert) {
    for (Vehicle__c vehicle : Trigger.New) {
        vehicle.Name += ' of ' +  System.UserInfo.getUserName();
    }
}

Possibly types of operations are:

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

There are some Trigger context variables that allow you to check which operation fired the trigger or if it was fired before or after the records were saved:

Variable Returns
isInsert true if the trigger was fired due to an insert operation
isUpdate true if the trigger was fired due to an update operation
isDelete true if the trigger was fired due to a delete operation
isUndelete true if the trigger was fired after a record is recovered from the Recycle Bin
isBefore true if the trigger was fired before any record was saved
isAfter true if this trigger was fired after all records were saved

There are also some variables, that allow you to access the records:

Variable Returns Records available in
new a list of the new versions of the sObject records insert, update, undelete (and can be modified only before)
newMap a map of IDs to the new versions of the sObject records before update, after insert, after update, after undelete
old a list of the old versions of the sObject records update, delete
oldMap a map of IDs to the old versions of the sObject records update and delete

#7 Queues

Since Queues can be the owners of the records, we can take advantage of this fact and only search for records that are owned by the Queue to which the user is assigned.

String currentUserId = UserInfo.getUserId();

// Get GroupMember records related to the current User (where the Group Type is Queue).
List<GroupMember> groupMembers = [SELECT GroupId
                                  FROM GroupMember
                                  WHERE Group.Type = 'Queue'];

// Create set of the Queues Ids.
Set<Id> currentUserQueuesIds = new Set<Id>();

for (GroupMember member : groupMembers) {
    currentUserQueuesIds.add(member.GroupId);
}

// Select records where the Queue related to the current User is the Owner.
List<Case> cases = [SELECT Id, Owner.Name
                    FROM Case
                    WHERE OwnerId IN :currentUserQueuesIds];

#8 Schema class

As the Salesforce documentation says Schema class:

Contains methods for obtaining schema describe information.

Useful examples:

Get metadata information about custom apps.

Schema.DescribeTabSetResult[] results = Schema.describeTabs();

for (Schema.DescribeTabSetResult result : results) {
    System.debug('Label: ' + result.getLabel());
}
03:36:27:072 USER_DEBUG [4]|DEBUG|Label: Sales
03:36:27:072 USER_DEBUG [4]|DEBUG|Label: Service
03:36:27:072 USER_DEBUG [4]|DEBUG|Label: Marketing

Get sObjects names.

Map<String, Schema.SObjectType> sObjectsMap = Schema.getGlobalDescribe();

for (String key : sObjectsMap.keySet()) {
	Schema.DescribeSObjectResult result = sObjectsMap.get(key).getDescribe();
	System.debug('SObject name: ' + result.getName());
}
04:05:09:071 USER_DEBUG [5]|DEBUG|SObject name: OpportunityStage
04:05:09:071 USER_DEBUG [5]|DEBUG|SObject name: LeadStatus
04:05:09:072 USER_DEBUG [5]|DEBUG|SObject name: CaseStatus

Get picklist entries.

Schema.DescribeFieldResult describeFieldResult = Account.Industry.getDescribe();
List<Schema.PicklistEntry> picklistEntries = describeFieldResult.getPicklistValues();

for (Schema.PicklistEntry picklistEntry : picklistEntries) {
    System.debug('Picklist entry: ' + picklistEntry);
}
10:38:41:007 USER_DEBUG [5]|DEBUG|Picklist entry: Schema.PicklistEntry[getLabel=Consulting;getValue=Consulting;isActive=true;isDefaultValue=false;]
10:38:41:007 USER_DEBUG [5]|DEBUG|Picklist entry: Schema.PicklistEntry[getLabel=Education;getValue=Education;isActive=true;isDefaultValue=false;]
10:38:41:007 USER_DEBUG [5]|DEBUG|Picklist entry: Schema.PicklistEntry[getLabel=Electronics;getValue=Electronics;isActive=true;isDefaultValue=false;]

Get type of sObject.

Schema.DescribeSObjectResult describeResult = Account.sObjectType.getDescribe();
System.debug('SObject type: ' + describeResult.getSObjectType());
11:08:36:015 USER_DEBUG [2]|DEBUG|SObject type: Account

#8 Apex data types.

Primitive data types in Apex.

Data Type Description Usage example
Blob - String myString = 'StringToBlob'; Blob myBlob = Blob.valueof(myString); System.assertEquals('StringToBlob', myBlob.toString());
Boolean - Boolean isValid = true;
Date - Date myDate = Date.newInstance(2022, 2, 18); // 2022-02-18 00:00:00
DateTime - DateTime myDateTime = DateTime.newInstance(1999, 2, 11, 8, 6, 16); // 2022-02-18 13:29:15
Decimal - Decimal phi = 1.618033;
Double - Double pi = 3.14159;
Id - 0017Q000008Yo6JQAS
Integer - Integer count = 15;
Long - Long amount = 1337;
Object - Object color = 'Red';
String - String name = 'Adrian';
Time - Time myTime = Time.newInstance(13, 47, 35, 570); // 13:47:35.570Z

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors