How can I initialise an apex Set<String>, Set<Id> or Set<Date> from SOQL in Apex Code?
No it is not possible except for Set<Id>
. With other types, you need a for
loop:
Set<String> names = new Set<String>();
for (MyObject__c record : [SELECT Name FROM MyObject__c])
names.add(record.Name);
The special case is that with a record's own Id, you can use this Map constructor:
Set<Id> ids = new Map<Id, SObject>([/*query*/]).keySet();
You can abuse this shortcut and field alias functionality in aggregate queries to get a collection of parent Ids also.
Set<Id> parentIds = new Map<Id, SObject>([
SELECT Parent__c Id FROM MyObject__c GROUP BY Parent__c
// ^^ you can now call .get('Id') on a result record
]).keySet();
You can do it fairly easily for the Set of Id use case by passing the SOQL to the constructor of an Id to Sobject Map and then grabbing the keyset from this;-
Set<Id> Ids = new Map<Id, Sobject>([SELECT Id FROM SObject]).keySet();
Other than that though there isn't a direct way to do it for non-Id fields. Your best bet would probably to create a reusable worker method to handle this.
Depending on what you need this for aggregate SOQL functions may help as they will produce a list of all unique values for the aggregated field.
Set<String> titles = new Set<String>();
for(AggregateResult ar : [SELECT Title FROM SObject GROUP BY Title]){
titles.add((String)ar.get('Title'));
}
Expanding on Adrian's answer of using the aggregate field alias to unpack a parent Id into a Set.
Adrian's version:
Set<Id> parentIds = new Map<Id, SObject>([
SELECT Parent__c Id FROM MyObject__c GROUP BY Parent__c
// ^^ you can now call .get('Id') on a result record
]).keySet();
I came across this expanded version by @bigassforce - Building a Set from any field
Matt's version:
Set<String> names = new Map<String,SObject>([
SELECT Name Id
FROM User
GROUP BY Name
]).keySet();
The key different being that the aliased field doesn't actually have to be an Id
. It could be a String
, or Date
. You just need to be able to GROUP BY it and adjust the map key accordingly.
As noted by the current Apex PM Chris Peterson, if you use this in production ensure that it is covered by Apex test cases that the hammer tests will see.