https://github.com/artysta/salesforce-notes
https://github.com/artysta/salesforce-notes
Last synced: 5 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/artysta/salesforce-notes
- Owner: artysta
- Created: 2021-09-20T08:29:06.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2022-05-19T18:52:56.000Z (about 4 years ago)
- Last Synced: 2024-12-29T10:43:01.521Z (over 1 year ago)
- Size: 318 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# #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:
```sql
SELECT Name, Phone, Account.Id, Account.Name FROM Contact
```
```sql
SELECT Name, Phone, Account.Id, Account.Name FROM Contact WHERE Account.Id = '0010900000iMM6GAAW'
```
Parent-to-child queries:
```sql
SELECT Id, Name, (SELECT Name, Phone FROM Contacts) FROM Account
```
```sql
SELECT Id, Name, (SELECT Name, Phone FROM Contacts) FROM Account WHERE Id = '0010900000iMM6DAAW'
```
### 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:
```sql
SELECT Name, Nationality__c, Vehicle__r.Id, Vehicle__r.Manufacturer__c FROM Driver__c
```
```sql
SELECT Name, Nationality__c, Vehicle__r.Id, Vehicle__r.Manufacturer__c FROM Driver__c WHERE Vehicle__r.Id = 'a000900000FThKjAAL'
```
Parent-to-child queries:
```sql
SELECT Id, Name, Manufacturer__c, (SELECT Name, Nationality__c FROM Drivers__r) FROM Vehicle__c
```
```sql
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:
```sql
SELECT Name, Status, Account.Id, Account.Name FROM Entitlement
```
```sql
SELECT Name, Status, Account.Id, Account.Name FROM Entitlement WHERE Account.Id = '0010900000g6FkaAAE'
```
Parent-to-child queries:
```sql
SELECT Id, Name, (SELECT Name, Status FROM Entitlements) FROM Account
```
```sql
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'.
```java
public class OpportunitiesCleanerBatch implements Database.Batchable {
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 opportunities) {
List opportunitiesToRemove = new List();
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.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:
```java
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.
```java
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.
```java
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:
```java
public class CasesBatch implements Database.Batchable {
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 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:
```java
Database.executeBatch(new CasesBatch());
```
We have got couple of logs:
```cmd
#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:
```java
public class CasesBatch implements Database.Batchable, 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 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:
```cmd
#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.
```java
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).
```java
DescribeFieldResult stageNameField = Opportunity.StageName.getDescribe();
for (Integer i = 0; i < stageNameField.getPicklistValues().size(); i++) {
System.debug(String.format(' StageName {0}: {1}', new List { String.valueOf(i), stageNameField.getPicklistValues()[i].value }));
}
```
- Run batch manually using Anonymous Apex.
```java
ExampleBatch batch = new ExampleBatch();
Database.executeBatch(batch);
```
- Schedule a job using Anonymous Apex.
```java
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.
```java
List opportunities = [SELECT Id, Name FROM Opportunity LIMIT 10];
Set opportunitiesIds = (new Map(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 Component: opportunitiesList.cmp
```html
Get Opportunities
Opportunities list:
- Id: {!opportunity.Id}, Name: {!opportunity.Name}, StageName: {!opportunity.StageName}
```
###### JavaScript Controller: opportunitiesListController.js
```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
```java
public with sharing class OpportunitiesController {
@AuraEnabled
public static List 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 Component: opportunitiesList.cmp
```html
```
###### JavaScript Controller: opportunitiesListController.js
```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
```java
public interface Tuningable {
// Interface methods cannot have a body.
void tuning();
}
```
###### Vehicle.cls
```java
// 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 { this.Color, this.Name });
}
}
```
###### BaseCar.cls
```java
// 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 { super.getInfo(), String.valueOf(this.MaxSpeed) });
}
}
```
###### SportsCar.cls
```java
// 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:
```java
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):
```java
// '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):
```java
// '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:
```java
// '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:
```java
// '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> sObjects = [FIND 'New' IN ALL FIELDS RETURNING Case(Status)];
}
}
```
Too many DML rows:
```java
// '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 cases = new List();
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.
```java
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.
```java
String currentUserId = UserInfo.getUserId();
// Get GroupMember records related to the current User (where the Group Type is Queue).
List groupMembers = [SELECT GroupId
FROM GroupMember
WHERE Group.Type = 'Queue'];
// Create set of the Queues Ids.
Set currentUserQueuesIds = new Set();
for (GroupMember member : groupMembers) {
currentUserQueuesIds.add(member.GroupId);
}
// Select records where the Queue related to the current User is the Owner.
List 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.
```java
Schema.DescribeTabSetResult[] results = Schema.describeTabs();
for (Schema.DescribeTabSetResult result : results) {
System.debug('Label: ' + result.getLabel());
}
```
```console
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.
```java
Map sObjectsMap = Schema.getGlobalDescribe();
for (String key : sObjectsMap.keySet()) {
Schema.DescribeSObjectResult result = sObjectsMap.get(key).getDescribe();
System.debug('SObject name: ' + result.getName());
}
```
```console
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.
```java
Schema.DescribeFieldResult describeFieldResult = Account.Industry.getDescribe();
List picklistEntries = describeFieldResult.getPicklistValues();
for (Schema.PicklistEntry picklistEntry : picklistEntries) {
System.debug('Picklist entry: ' + picklistEntry);
}
```
```console
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.
```java
Schema.DescribeSObjectResult describeResult = Account.sObjectType.getDescribe();
System.debug('SObject type: ' + describeResult.getSObjectType());
```
```console
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