您可以评估 Salesforce 对象查询语言 (SOQL) 或 Salesforce 对象搜索 语言 (SOSL) 语句在 Apex 中动态,方法是将语句括在正方形中 括弧。
SOQL 语句
SOQL 语句的计算结果为方法查询的 sObjects、单个 sObject 或 Integer 列表。count例如,您可以检索名为 顶点:
List<Account> aa = [SELECT Id, Name FROM Account WHERE Name = 'Acme'];
从 此列表,您可以访问个人 元素:
if (!aa.isEmpty()) {
// Execute commands
}
您还可以从现有对象的 SOQL 查询创建新对象。这个例子 为第一个客户创建一个新联系人,其员工数量较多 比 10.
Contact c = new Contact(Account = [SELECT Name FROM Account
WHERE NumberOfEmployees > 10 LIMIT 1]);
c.FirstName = 'James';
c.LastName = 'Yoyce';
这 新创建的对象包含其字段的 NULL 值,必须设置这些值。该方法可用于返回 查询返回的行数。以下示例返回总数 姓氏为 魏斯曼:
count
Integer i = [SELECT COUNT() FROM Contact WHERE LastName = 'Weissman'];
你 也可以使用标准对结果进行操作 算术:
Integer j = 5 * [SELECT COUNT() FROM Account];
执行 SOQL 查询时适用 SOQL 限制。请参阅执行调控器和限制。
有关 SOQL 查询语法的完整说明,请参阅 Salesforce SOQL 和 SOSL 参考 指南。
SOSL 声明
SOSL 语句的计算结果为 sObject 列表,其中每个列表都包含 特定 sObject 类型的搜索结果。始终返回结果列表 其顺序与在 SOSL 查询中指定的顺序相同。如果 SOSL 查询没有 返回指定 sObject 类型的任何记录,搜索结果中包括一个空的 该 sObject 的列表。例如,您可以返回客户、联系人、商机和潜在顾客的列表 以短语开头 地图:
List<List<SObject>> searchList = [FIND 'map*' IN ALL FIELDS RETURNING Account (Id, Name), Contact, Opportunity, Lead];
注意Apex 中子句的语法不同于 SOAP API 和 REST API 中子句的语法:
FINDFIND
- 在 Apex 中,子句的值用单引号分隔。为 例:FIND
FIND 'map*' IN ALL FIELDS RETURNING Account (Id, Name), Contact, Opportunity, Lead
注意 - 在 API 中,子句的值用大括号分隔。为 例:FIND
FIND {map*} IN ALL FIELDS RETURNING Account (Id, Name), Contact, Opportunity, Lead
顶点 在系统模式下运行会忽略字段级安全性,而 使用 扫描匹配项。IN ALL FIELDS从 中,您可以为 每个对象 返回:
searchList
Account [] accounts = ((List<Account>)searchList[0]);
Contact [] contacts = ((List<Contact>)searchList[1]);
Opportunity [] opportunities = ((List<Opportunity>)searchList[2]);
Lead [] leads = ((List<Lead>)searchList[3]);
执行 SOSL 查询时适用 SOSL 限制。请参阅执行调控器和限制。
有关 SOSL 查询语法的完整说明,请参阅 Salesforce SOQL 和 SOSL 参考 指南。
- 使用 SOQL 和 SOSL 查询结果
- 通过关系访问 sObject 字段
- 了解外键和父子关系 SOQL 查询
- 使用 SOQL 聚合函数
- 使用非常大的 SOQL 查询
- 使用返回一条记录的 SOQL 查询
- 通过避免 null 值来提高性能
- 在 SOQL 查询
中使用多态关系 多态关系是对象之间的关系,其中引用的对象可以是几种不同类型的类型之一。例如,任务的关系字段可以是联系人或潜在顾客。Who - 在 SOQL 和 SOSL 查询中使用 Apex 变量
- 使用 SOQL 语句查询所有记录
使用 SOQL 和 SOSL 查询结果
SOQL 和 SOSL 查询仅返回 sObject 字段的数据 在原始查询中被选中。如果您尝试访问的字段 未在 SOQL 或 SOSL 查询中选择(ID 除外),您会收到 运行时错误,即使该字段包含数据库中的值也是如此。 下面的代码示例会导致运行时错误:
insert new Account(Name = 'Singha');
Account acc = [SELECT Id FROM Account WHERE Name = 'Singha' LIMIT 1];
// Note that name is not selected
String name = [SELECT Id FROM Account WHERE Name = 'Singha' LIMIT 1].Name;
以下是重写的相同代码示例,因此它不会 产生运行时错误。请注意,已作为 select 语句的一部分添加在 之后。NameId
insert new Account(Name = 'Singha');
Account acc = [SELECT Id FROM Account WHERE Name = 'Singha' LIMIT 1];
// Note that name is now selected
String name = [SELECT Id, Name FROM Account WHERE Name = 'Singha' LIMIT 1].Name;
即使只选择了一个 sObject 字段,SOQL 或 SOSL 查询 始终将数据作为完整记录返回。因此,您必须取消引用 该字段以访问它。例如,此代码检索 带有 SOQL 查询的数据库中的 sObject 列表,访问 列表中的第一个客户记录,然后取消引用记录的字段:AnnualRevenue
Double rev = [SELECT AnnualRevenue FROM Account
WHERE Name = 'Acme'][0].AnnualRevenue;
// When only one result is returned in a SOQL query, it is not necessary
// to include the list's index.
Double rev2 = [SELECT AnnualRevenue FROM Account
WHERE Name = 'Acme' LIMIT 1].AnnualRevenue;
唯一没有必要取消引用的情况 SOQL 查询结果中的 sObject 字段,是当查询 返回一个 Integer 作为操作的结果:COUNT
Integer i = [SELECT COUNT() FROM Account];
SOSL 查询返回的记录中的字段必须始终取消引用。
另请注意,包含公式的 sObject 字段在 发出了 SOQL 或 SOSL 查询。对公式中使用的其他字段所做的任何更改都不会 反映在公式字段值中,直到记录在 Apex 中保存并重新查询。喜欢 其他只读 sObject 字段,则公式字段本身的值不能在 顶点。
通过关系访问 sObject 字段
sObject 记录表示与其他记录的关系,具有两个字段:ID 和 地址,指向关联 sObject 的表示形式。例如, Contact sObject 具有 键入 ID 和 Account 类型的字段 指向关联的 sObject 记录本身。AccountIdAccount
ID 字段可用于更改与联系人关联的帐户, 而 sObject 引用字段可用于访问帐户中的数据。这 reference 字段仅作为 SOQL 或 SOSL 查询的结果进行填充(请参阅注释)。
例如,以下 Apex 代码显示了如何关联客户和联系人 ,然后如何使用联系人来修改 帐户:
注意
为了提供最完整的示例,此代码使用了一些描述的元素 本指南后面部分:
- 有关 和 的信息,请参见 Insert 语句和 Update 语句。insertupdate
Account a = new Account(Name = 'Acme');
insert a; // Inserting the record automatically assigns a
// value to its ID field
Contact c = new Contact(LastName = 'Weissman');
c.AccountId = a.Id;
// The new contact now points at the new account
insert c;
// A SOQL query accesses data for the inserted contact,
// including a populated c.account field
c = [SELECT Account.Name FROM Contact WHERE Id = :c.Id];
// Now fields in both records can be changed through the contact
c.Account.Name = 'salesforce.com';
c.LastName = 'Roth';
// To update the database, the two types of records must be
// updated separately
update c; // This only changes the contact's last name
update c.Account; // This updates the account name
注意
表达式 ,以及任何其他 遍历关系的表达式,显示略有不同的特征 当它被读取为一个值时,而不是当它被修改时:c.Account.Name
- 当作为值读取时,如果为 null,则计算结果为 ,但不生成 .此设计允许开发人员导航 多个关系,无需检查 null 的乏味 值。c.Accountc.Account.NamenullNullPointerException
- 修改时,如果是 null,则生成一个 .c.Accountc.Account.NameNullPointerException
在 SOSL 中,您可以以与 SELECT 类似的方式访问插入的联系人的数据 上一个 SOQL 中使用的语句 例。
List<List<SObject>> searchList = [FIND 'Acme' IN ALL FIELDS RETURNING Contact(id,Account.Name)]
此外,sObject 字段键可以与 、 一起使用,也可以通过外部 ID 解析外键。为 例:insertupdateupsert
Account refAcct = new Account(externalId__c = '12345');
Contact c = new Contact(Account = refAcct, LastName = 'Kay');
insert c;
这将插入一个具有相等的新联系人,以等于的帐户 到“12345”。如果没有此类帐户,则插入失败。AccountIdexternal_id
提示
以下代码等效于上面的代码。但是,因为它使用 SOQL 查询,效率不高。如果多次调用此代码,它可以 达到最大 SOQL 查询数的执行限制。查看更多 有关执行限制的信息,请参阅执行调控器和限制。
Account refAcct = [SELECT Id FROM Account WHERE externalId__c='12345'];
Contact c = new Contact(Account = refAcct.Id);
insert c;
了解外键和父子 关系 SOQL 查询
声明 SOQL 查询可以是任何有效的 SOQL 语句,包括外键 和父子记录联接。如果包含外键联接, 生成的 sObject 可以使用正态字段表示法进行引用。 例如:SELECT
System.debug([SELECT Account.Name FROM Contact
WHERE FirstName = 'Caroline'].Account.Name);
此外,sObject 中的父子关系充当 SOQL 查询也是如此。例如:
for (Account a : [SELECT Id, Name, (SELECT LastName FROM Contacts)
FROM Account
WHERE Name = 'Acme']) {
Contact[] cons = a.Contacts;
}
//The following example also works because we limit to only 1 contact
for (Account a : [SELECT Id, Name, (SELECT LastName FROM Contacts LIMIT 1)
FROM Account
WHERE Name = 'testAgg']) {
Contact c = a.Contacts;
}
使用 SOQL 聚合函数
SOQL 中的聚合函数(如 和 )允许您在查询中汇总和汇总数据。 有关聚合函数的详细信息,请参阅 Salesforce SOQL 和 SOSL 中的聚合函数 参考指南。SUM()MAX()
您可以在不使用子句的情况下使用聚合函数。例如,您可以使用聚合 函数来查找所有机会的平均金额。GROUP BYAVG()
AggregateResult[] groupedResults
= [SELECT AVG(Amount)aver FROM Opportunity];
Object avgAmount = groupedResults[0].get('aver');
请注意,任何包含聚合函数的查询都会以 AggregateResult 对象。AggregateResult 是只读 sObject,仅用于查询 结果。
当您将聚合函数与子句一起使用时,它们将成为生成报告的更强大的工具。例如,您可以按广告系列找到所有商机的平均金额。GROUP BY
AggregateResult[] groupedResults
= [SELECT CampaignId, AVG(Amount)
FROM Opportunity
GROUP BY CampaignId];
for (AggregateResult ar : groupedResults) {
System.debug('Campaign ID' + ar.get('CampaignId'));
System.debug('Average amount' + ar.get('expr0'));
}
列表中没有 别名会自动获取一个隐含的别名,其格式为 ,其中表示 没有显式别名的聚合字段。的值从 0 开始,并且 每个聚合字段的增量,没有显式别名。有关更多信息,请参阅在 Salesforce SOQL 和 SOSL 中将别名与 GROUP BY 结合使用 参考指南。
注意
包含聚合函数的查询仍受 查询行。除每个函数之外的所有聚合函数,或包括每个聚合函数 聚合用作查询行的行,用于限制跟踪。COUNT()COUNT(fieldname)
对于 或 查询,限制计为一个查询行,除非查询 包含一个 GROUP BY 子句,在这种情况下,每个分组使用一个查询行。COUNT()COUNT(fieldname)
使用非常大的 SOQL 查询
重要
在可能的情况下,我们更改了非包容性条款,以符合我们的 平等的公司价值观。我们保留了某些条款,以避免对客户产生任何影响 实现。
SOQL 查询有时会返回如此多的 sObject,以至于堆大小限制为 超出并发生错误。要解决此问题,请改用 SOQL 查询循环,因为它可以处理多个 使用对 和 的内部调用对记录进行批处理。forqueryqueryMore
例如,如果结果太大,则以下语法会导致运行时异常:
Account[] accts = [SELECT Id FROM Account];
请改用 SOQL 查询循环,如以下 以下示例:for
// Use this format if you are not executing DML statements
// within the for loop
for (Account a : [SELECT Id, Name FROM Account
WHERE Name LIKE 'Acme%']) {
// Your code without DML statements here
}
// Use this format for efficiency if you are executing DML statements
// within the for loop
for (List<Account> accts : [SELECT Id, Name FROM Account
WHERE Name LIKE 'Acme%']) {
for (Account a : accts) {
// Your code here
}
update accts;
}
注意
在循环中使用 SOQL 查询 降低了达到堆大小限制的可能性。但是,这种方法可以 导致 DML 调用增加,导致使用的 CPU 周期更多。有关详细信息,请参阅 SOQL For 循环与标准 SOQL 查询。for
以下示例演示了用于批量更新记录的 SOQL 查询循环。假设你想 在记录中更改其名字和姓氏的联系人的联系人的姓氏 匹配指定条件:for
public void massUpdate() {
for (List<Contact> contacts:
[SELECT FirstName, LastName FROM Contact]) {
for(Contact c : contacts) {
if (c.FirstName == 'Barbara' &&
c.LastName == 'Gordon') {
c.LastName = 'Wayne';
}
}
update contacts;
}
}
不是在循环中使用 SOQL 查询,而是 批量更新记录的首选方法是使用批处理 Apex,这样可以最大限度地降低达到调速器限制的风险。for
有关更多信息,请参阅 SOQL For 循环。
更高效的 SOQL 查询
为了获得最佳性能,SOQL 查询必须是有选择性的,尤其是对于内部的查询 触发器。为了避免长时间的执行,系统可以终止非选择性 SOQL 查询。当触发器中的非选择性查询时,开发人员会收到错误消息 对包含超过 100 万条记录的对象执行。为了避免这种情况 错误,请确保查询是有选择性的。选择性 SOQL 查询条件
- 当其中一个查询筛选器位于索引上时,查询是有选择性的 字段和查询筛选器会减少生成的行数 低于系统定义的阈值。SOQL 查询的性能 改进了当 WHERE 子句中使用的两个或多个过滤器满足 提到的条件。
- 选择性阈值为前 100 万条记录的 10%,并且 在前 100 万条记录之后,少于 5% 的记录,最多 最多 333,333 条记录。在某些情况下,例如 作为索引标准字段的查询筛选器,阈值可以 更高。此外,选择性阈值受以下因素的影响 改变。
选择性 SOQL 查询的自定义索引注意事项
- 默认情况下,以下字段已编制索引。
- 主键(Id、Name 和 OwnerId 字段)
- 外键(查找或主从关系 字段)
- 审核日期(CreatedDate 和 SystemModstamp 字段)
- RecordType 字段(为以下所有标准对象编制索引 特色他们)
- 标记为“外部 ID”或“唯一”的自定义字段
- 默认情况下未编制索引的字段在以下情况下自动编制索引 Salesforce Optimizer 认识到索引可以改进 频繁运行查询的性能。
- Salesforce 支持可以根据请求添加自定义索引 客户。
- 无法在以下类型的字段上创建自定义索引: 多选选择列表,多币种中的货币字段 组织、长文本字段、某些公式字段和二进制文件 字段(Blob、文件或加密文本类型的字段。新数据 类型,通常是复杂的类型,会定期添加到 Salesforce, 这些类型的字段并不总是允许自定义索引。
- 您无法在包含以下内容的公式字段上创建自定义索引 对选择列表字段的函数调用。TEXT
- 通常,在这些情况下不使用自定义索引。
- 查询的值超过系统定义的阈值。
- filter 运算符为负运算符,例如 (或 )、 和 。NOT EQUAL TO!=NOT CONTAINSNOT STARTS WITH
- 运营商 在过滤器中使用,以及要扫描的行数 超过 333,333 人。操作员需要对 指数。此阈值可能会发生变化。CONTAINSCONTAINS
- 您正在与空值 () 进行比较。Name != ”
选择性 SOQL 查询的示例为了更好地了解对大型对象的查询是否具有选择性, 让我们分析一些查询。对于这些查询,假设有更多 帐户 sObject 的 100 万条记录。这些记录包括 软删除的记录,即仍在回收中的已删除记录 站。查询 1:
SELECT Id FROM Account WHERE Id IN (<list of account IDs>)
该子句位于索引上 字段 (Id)。如果返回更少 记录超过选择性阈值时,则使用索引 on。该指数通常为 当 ID 列表仅包含几条记录时使用。WHERESELECT COUNT() FROM Account WHERE Id IN (<list of account IDs>)Id查询 2:
SELECT Id FROM Account WHERE Name != ''
因为 Account 是一个大对象,即使 Name 已编制索引(主键), 此筛选器返回大部分记录,进行查询 非选择性。查询 3:
SELECT Id FROM Account WHERE Name != '' AND CustomField__c = 'ValueA'
这里 我们必须看看是否有任何过滤器,当单独考虑时,是 选择性。正如我们在前面的示例中看到的,第一个筛选器不是 选择性。因此,让我们关注第二个问题。如果记录计数 返回的 by 低于 选择性阈值,CustomField__c编制索引,则查询为 选择性。SELECT COUNT() FROM Account WHERE CustomField__c = ‘ValueA’
使用返回一条记录的 SOQL 查询
当结果列表仅包含一个 sObject 值时,可以使用 SOQL 查询来分配单个 sObject 值 元素。当表达式的 L 值为单个 sObject 类型时,Apex 会自动将 查询结果列表中的单个 sObject 记录为 L 值。如果为零,则会导致运行时异常 在列表中找到 sObject 或多个 sObject。例如:
List<Account> accts = [SELECT Id FROM Account];
// These lines of code are only valid if one row is returned from
// the query. Notice that the second line dereferences the field from the
// query without assigning it to an intermediary sObject variable.
Account acct = [SELECT Id FROM Account];
String name = [SELECT Name FROM Account].Name;
通过避免 null 值来提高性能
在 SOQL 和 SOSL 查询中,显式筛选出 WHERE 子句允许 Salesforce 提高查询性能。在以下示例中, 值为 null 的任何记录都是 从 搜索。
Thread__c
Public class TagWS {
/* getThreadTags
*
* a quick method to pull tags not in the existing list
*
*/
public static webservice List<String>
getThreadTags(String threadId, List<String> tags) {
system.debug(LoggingLevel.Debug,tags);
List<String> retVals = new List<String>();
Set<String> tagSet = new Set<String>();
Set<String> origTagSet = new Set<String>();
origTagSet.addAll(tags);
// Note WHERE clause optimizes search where Thread__c is not null
for(CSO_CaseThread_Tag__c t :
[SELECT Name FROM CSO_CaseThread_Tag__c
WHERE Thread__c = :threadId AND
Thread__c != null])
{
tagSet.add(t.Name);
}
for(String x : origTagSet) {
// return a minus version of it so the UI knows to clear it
if(!tagSet.contains(x)) retVals.add('-' + x);
}
for(String x : tagSet) {
// return a plus version so the UI knows it's new
if(!origTagSet.contains(x)) retvals.add('+' + x);
}
return retVals;
}
}
在 SOQL 查询中使用多态关系
多态关系是对象之间的关系,其中引用 对象可以是几种不同的类型之一。例如,任务的关系字段可以是联系人或潜在顾客。
Who
在Apex中使用具有多态关系的SOQL查询的方法如下。 如果需要有关多态关系的更多常规信息,请参阅了解关系字段和 SOQL 和 SOSL 引用中的多态字段。您可以使用引用 Apex 中的多态字段的 SOQL 查询来获取以下结果: 取决于多态字段引用的对象类型。一种方法是过滤 使用 Type 限定符的结果。此示例查询事件 通过“什么”与“帐户”或“商机”相关 田。
List<Event> events = [SELECT Description FROM Event WHERE What.Type IN ('Account', 'Opportunity')];
另一个 方法是在 SOQL 语句。此示例还查询 通过“什么”与“客户”或“商机”相关的事件 田。
TYPEOFSELECT
List<Event> events = [SELECT TYPEOF What WHEN Account THEN Phone WHEN Opportunity THEN Amount END FROM Event];
这些 查询返回 sObject 列表,其中关系字段引用所需的 对象类型。如果需要访问多态关系中的引用对象,可以使用 instanceof 关键字设置为 确定对象类型。以下示例用于确定 Account 或 Opportunity 是否与 事件。
instanceof
Event myEvent = eventFromQuery;
if (myEvent.What instanceof Account) {
// myEvent.What references an Account, so process accordingly
} else if (myEvent.What instanceof Opportunity) {
// myEvent.What references an Opportunity, so process accordingly
}
请注意,必须分配查询返回到的引用的 sObject 一个适当类型的变量,然后才能将其传递给另一个方法。这 以下示例
- 使用 SOQL 查询Merchandise__c自定义对象的用户或组所有者 使用子句进行查询TYPEOF
- 用于确定所有者 类型instanceof
- 将所有者对象分配给用户或组类型变量,然后再将其传递给 实用程序方法
public class PolymorphismExampleClass {
// Utility method for a User
public static void processUser(User theUser) {
System.debug('Processed User');
}
// Utility method for a Group
public static void processGroup(Group theGroup) {
System.debug('Processed Group');
}
public static void processOwnersOfMerchandise() {
// Select records based on the Owner polymorphic relationship field
List<Merchandise__c> merchandiseList = [SELECT TYPEOF Owner WHEN User THEN LastName WHEN Group THEN Email END FROM Merchandise__c];
// We now have a list of Merchandise__c records owned by either a User or Group
for (Merchandise__c merch: merchandiseList) {
// We can use instanceof to check the polymorphic relationship type
// Note that we have to assign the polymorphic reference to the appropriate
// sObject type before passing to a method
if (merch.Owner instanceof User) {
User userOwner = merch.Owner;
processUser(userOwner);
} else if (merch.Owner instanceof Group) {
Group groupOwner = merch.Owner;
processGroup(groupOwner);
}
}
}
}
在 SOQL 和 SOSL 查询中使用 Apex 变量
Apex 中的 SOQL 和 SOSL 语句可以引用 Apex 代码 变量和表达式(如果它们前面有冒号 ()。在 SOQL 中使用局部代码变量 或 SOSL 语句称为绑定。Apex 解析器首先评估 执行 SOQL 或 SOSL 语句之前代码上下文中的局部变量。:捆 表达式可以用作:
- 子句中的搜索字符串。FIND
- 子句中的筛选器文本。WHERE
- 子句中 or 运算符的值,允许对一组动态值进行筛选。请注意, 这对于 ID 或字符串列表特别有用,尽管它适用于 任何类型。INNOT INWHERE
- 子句中的分部名称。WITH DIVISION
- 子句中的数值。LIMIT
- 子句中的数值。OFFSET
例如:
Account A = new Account(Name='xxx');
insert A;
Account B;
// A simple bind
B = [SELECT Id FROM Account WHERE Id = :A.Id];
// A bind with arithmetic
B = [SELECT Id FROM Account
WHERE Name = :('x' + 'xx')];
String s = 'XXX';
// A bind with expressions
B = [SELECT Id FROM Account
WHERE Name = :'XXXX'.substring(0,3)];
// A bind with INCLUDES clause
B = [SELECT Id FROM Account WHERE :A.TYPE INCLUDES (‘Customer – Direct; Customer – Channel’)];
// A bind with an expression that is itself a query result
B = [SELECT Id FROM Account
WHERE Name = :[SELECT Name FROM Account
WHERE Id = :A.Id].Name];
Contact C = new Contact(LastName='xxx', AccountId=A.Id);
insert new Contact[]{C, new Contact(LastName='yyy',
accountId=A.id)};
// Binds in both the parent and aggregate queries
B = [SELECT Id, (SELECT Id FROM Contacts
WHERE Id = :C.Id)
FROM Account
WHERE Id = :A.Id];
// One contact returned
Contact D = B.Contacts;
// A limit bind
Integer i = 1;
B = [SELECT Id FROM Account LIMIT :i];
// An OFFSET bind
Integer offsetVal = 10;
List<Account> offsetList = [SELECT Id FROM Account OFFSET :offsetVal];
// An IN-bind with an Id list. Note that a list of sObjects
// can also be used--the Ids of the objects are used for
// the bind
Contact[] cc = [SELECT Id FROM Contact LIMIT 2];
Task[] tt = [SELECT Id FROM Task WHERE WhoId IN :cc];
// An IN-bind with a String list
String[] ss = new String[]{'a', 'b'};
Account[] aa = [SELECT Id FROM Account
WHERE AccountNumber IN :ss];
// A SOSL query with binds in all possible clauses
String myString1 = 'aaa';
String myString2 = 'bbb';
Integer myInt3 = 11;
String myString4 = 'ccc';
Integer myInt5 = 22;
List<List<SObject>> searchList = [FIND :myString1 IN ALL FIELDS
RETURNING
Account (Id, Name WHERE Name LIKE :myString2
LIMIT :myInt3),
Contact,
Opportunity,
Lead
WITH DIVISION =:myString4
LIMIT :myInt5];
注意单位不支持 Apex 绑定变量 参数。此查询 不起作用。
DISTANCE
String units = 'mi';
List<Account> accountList =
[SELECT ID, Name, BillingLatitude, BillingLongitude
FROM Account
WHERE DISTANCE(My_Location_Field__c, GEOLOCATION(10,10), :units) < 10];
使用 SOQL 语句查询所有记录
SOQL 语句可以使用关键字查询组织中的所有记录,包括 已删除的记录和存档的活动。例如:
ALL ROWS
System.assertEquals(2, [SELECT COUNT() FROM Contact WHERE AccountId = a.Id ALL ROWS]);
您可以使用 组织的回收站。不能将关键字与关键字一起使用。ALL ROWSALL ROWSFOR UPDATE
SOQL For 循环
SOQL 循环遍历所有 SOQL 查询返回的 sObject 记录。
forSOQL 循环的语法是 也:
for
for (variable : [soql_query]) {
code_block
}
或
for (variable_list : [soql_query]) {
code_block
}
两者 和 必须与 sObject 的类型相同 由 返回。与标准 SOQL 查询一样,该语句可以引用 在其子句中对表达式进行编码 使用语法。为 例:
variable variable_list soql_query[soql_query]WHERE:
String s = 'Acme';
for (Account a : [SELECT Id, Name from Account
where Name LIKE :(s+'%')]) {
// Your code
}
下面的示例将 SOQL 查询创建列表与 DML 方法相结合。
update
// Create a list of account records from a SOQL query
List<Account> accs = [SELECT Id, Name FROM Account WHERE Name = 'Siebel'];
// Loop through the list and update the Name field
for(Account a : accs){
a.Name = 'Oracle';
}
// Update the database
update accs;
SOQL For 循环与标准 SOQL 查询
SOQL 循环不同于标准 SOQL 语句,因为它们用于检索 sObject 的方法。虽然标准 SOQL 和 SOSL 查询中讨论的查询可以检索查询或多个对象记录, SOQL 循环检索所有 sObject,使用 通过调用 SOAP API 的 和 方法进行高效分块。 开发人员可以通过使用 SOQL 循环来处理返回的查询结果,从而避免对堆大小的限制 多条记录。但是,此方法可能会导致使用更多的 CPU 周期。 请参见堆总大小。forcountforqueryqueryMorefor
包含聚合函数的查询不支持 。如果出现以下情况,则会发生运行时异常 使用包含聚合函数的查询,该聚合函数在循环中返回超过 2,000 行。queryMorefor
SOQL For 循环格式
SOQL 循环可以一次处理一个记录 时间使用单个 sObject 变量,或一次使用 sObject 列表:
- 单个 sObject 格式对每个 sObject 记录执行一次循环。因此 它易于理解和使用,但如果您愿意,效率非常低下 在循环体中使用数据操作语言 (DML) 语句。每个 DML 语句结束 一次只能处理一个 sObject。for<code_block>for
- sObject 列表格式对每个包含 200 个 sObject 的列表执行一次循环。 因此,它更难理解和使用,但 如果必须在循环体中使用 DML 语句,则为最佳选择。每个 DML 语句可以 一次批量处理 sObject 列表。for<code_block>for
For example, the following code illustrates the difference between the two types of SOQL query loops:
for
// Create a savepoint because the data should not be committed to the database
Savepoint sp = Database.setSavepoint();
insert new Account[]{new Account(Name = 'yyy'),
new Account(Name = 'yyy'),
new Account(Name = 'yyy')};
// The single sObject format executes the for loop once per returned record
Integer i = 0;
for (Account tmp : [SELECT Id FROM Account WHERE Name = 'yyy']) {
i++;
}
System.assert(i == 3); // Since there were three accounts named 'yyy' in the
// database, the loop executed three times
// The sObject list format executes the for loop once per returned batch
// of records
i = 0;
Integer j;
for (Account[] tmp : [SELECT Id FROM Account WHERE Name = 'yyy']) {
j = tmp.size();
i++;
}
System.assert(j == 3); // The lt should have contained the three accounts
// named 'yyy'
System.assert(i == 1); // 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
// Revert the database to the original state
Database.rollback(sp);
注意
- 和关键字可用于两者 内联查询循环的类型 格式。使用 sObject 列表格式时,跳到下一个 sObject 列表。breakcontinueforcontinue
- DML 语句一次最多只能处理 10,000 条记录,而 sObject 列出循环进程记录 每批 200 个。因此,如果您要插入、更新或删除 在 sObject 列表循环中,每个返回的记录都有多个记录,可能会遇到 运行时限制的错误。查看执行 调速器和限制。forfor
- 你可能会得到一个 带有消息 的 SOQL 循环。有时会引发此异常 当访问检索到的大量子记录(200 个或更多)时 sObject,或者在获取此类记录集的大小时。为 例如,以下 SOQL 循环中的查询检索特定帐户的子联系人。如果 此帐户包含 200 多个子联系人,循环中的语句会导致异常。QueryExceptionforAggregate query has too many rows for direct assignment, use FOR loopforfor
for (Account acct : [SELECT Id, Name, (SELECT Id, Name FROM Contacts) FROM Account WHERE Id IN ('<ID value>')]) { List<Contact> contactList = acct.Contacts; // Causes an error Integer count = acct.Contacts.size(); // Causes an error }
若要避免出现此异常,请使用循环遍历子项 记录,作为 遵循。
for
for (Account acct : [SELECT Id, Name, (SELECT Id, Name FROM Contacts)
FROM Account WHERE Id IN ('<ID value>')]) {
Integer count=0;
for (Contact c : acct.Contacts) {
count++;
}
}