<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Enforcer.net &#187; SOQL</title>
	<atom:link href="http://theEnforcer.net/category/soql/feed/" rel="self" type="application/rss+xml" />
	<link>http://theEnforcer.net</link>
	<description>a force.com blog</description>
	<lastBuildDate>Thu, 19 Aug 2010 23:03:36 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Using WhatId to find Opportunities associated with Activities</title>
		<link>http://theEnforcer.net/2010/07/using-whatid-to-find-opportunities-associated-with-activities/</link>
		<comments>http://theEnforcer.net/2010/07/using-whatid-to-find-opportunities-associated-with-activities/#comments</comments>
		<pubDate>Mon, 12 Jul 2010 02:56:05 +0000</pubDate>
		<dc:creator>The Enforcer</dc:creator>
				<category><![CDATA[Apex]]></category>
		<category><![CDATA[SOQL]]></category>

		<guid isPermaLink="false">http://theEnforcer.net/?p=252</guid>
		<description><![CDATA[We recently reassigned a heap of Opportunities between staff members. However, the previous Opportunity Owner had open Activities on the Opportunities. The new Opportunity owners couldn&#8217;t close those Activities since they belong to somebody else. So, they asked me to find a way to bulk-close the Activities. This sounded simple, but was made more difficult [...]]]></description>
			<content:encoded><![CDATA[<p>We recently reassigned a heap of Opportunities between staff members. However, the previous Opportunity Owner had open Activities on the Opportunities. The new Opportunity owners couldn&#8217;t close those Activities since they belong to somebody else.</p>
<p>So, they asked me to find a way to bulk-close the Activities.</p>
<p>This sounded simple, but was made more difficult by the fact that Activities can link to many different object types:  Account, Opportunity, Campaign, Case or Custom Object.</p>
<p>The connection is made via WhatID, which is the ID of the associated object. It can be accessed via SOQL like this:</p>
<p><code>SELECT Id, What.Name from Task</code></p>
<p>However, not all fields are available, so you can&#8217;t <code>SELECT What.OwnerId</code>.</p>
<p>Fortunately, I found a forum post called <a href="http://community.salesforce.com/t5/General-Development/Getting-Object-type-of-WhatId-WhoId-Task-Event-fields/td-p/2928" target="_blank">Getting Object type of WhatId/WhoId Task/Event fields</a> gave me a few hints, and I came up with this code:</p>
<pre class="brush: plain;">
// Get list of Opportunities owned by new person
Opportunity[] opps = [Select Id from Opportunity where OwnerId = '005200300014jeN'];

// Get incomplete Activities owned by previous person attached to the above Opportunities
Task[] tasks = [select Id, What.Name from Task where OwnerId = '00520000000tSOj' and Status != 'Completed' and WhatId in :opps];
for (Task t : tasks) {
  t.Status = 'Completed';
}
update tasks;
</pre>
<p>This grabs a list of &#8216;owned&#8217; Opportunities and checks for any Activities (which are actually Task objects) that have a <code>WhatId</code> matching those Opportunities.</p>
<p>Straight-forward and pretty simple. Almost makes up for not being able to traverse directly to the linked object.</p>
<h3>The Bottom Line</h3>
<ul class="nomargin">
<li>Activities can link to multiple objects</li>
<li>They connect via WhatId, but only a limited number of fields are exposed, eg What.Name</li>
<li>Use an &#8216;IN&#8217; comparison to match the Activities with Opportunities</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://theEnforcer.net/2010/07/using-whatid-to-find-opportunities-associated-with-activities/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Manually-entered Date value in Apex SOQL query</title>
		<link>http://theEnforcer.net/2010/07/manually-entered-date-value-in-apex-soql-query/</link>
		<comments>http://theEnforcer.net/2010/07/manually-entered-date-value-in-apex-soql-query/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 01:24:36 +0000</pubDate>
		<dc:creator>The Enforcer</dc:creator>
				<category><![CDATA[Apex]]></category>
		<category><![CDATA[SOQL]]></category>

		<guid isPermaLink="false">http://theEnforcer.net/?p=244</guid>
		<description><![CDATA[I run into this problem all the time. I want to write a quite routine in the System Log window to Mass Update some records (eg my previous Mass Delete via System Log window blog post). I want to find all records before a certain date, but SOQL never likes my date format, eg: select [...]]]></description>
			<content:encoded><![CDATA[<p>I run into this problem all the time.</p>
<p>I want to write a quite routine in the System Log window to Mass Update some records (eg my previous <a href="http://theEnforcer.net/2009/01/mass-delete">Mass Delete via System Log window</a> blog post). I want to find all records before a certain date, but SOQL never likes my date format, eg:</p>
<p><code>select Id from Opportunity where Expiry_Date__c &lt; <span style="color: #ff0000;">2010-01-01</span></code></p>
<p>Yes, it is possible to convert it to Timezone format and do it this way:</p>
<p><code>select Id from Opportunity where Expiry_Date__c &lt; 2008-01-01<span style="color: #ff0000;">T00:00:00Z</span></code></p>
<p>but I&#8217;ve always thought that silly when comparing against a Date field.</p>
<p>So, I eventually figured out that I can do it this way:</p>
<p><code>select Id, Name, LastLoginDate from User where LastLoginDate &gt; <span style="color: #ff0000;">:Date.valueOf('2008-01-01')</span></code></p>
<p>Of course, this only works within the context of Apex, such as the System Log window. It won&#8217;t work in pure SOQL tools like <a href="http://www.pocketsoap.com/osx/soqlx/">SOQL Explorer</a>. Here&#8217;s an example:</p>
<pre class="brush: plain;">
Opportunity[] opps = [select Id from Opportunity where Expiry_Date__c &lt; :Date.valueOf('2010-01-01')];
System.Debug(opps.size());
</pre>
<h3>The Bottom Line</h3>
<ul class="nomargin">
<li>Date strings can&#8217;t be entered into SOQL</li>
<li>Option 1: Use Timezone format: 2010-01-01T00:00:00Z</li>
<li>Option 2: Convert from string: :Date.valueOf(&#8217;2010-01-01&#8242;)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://theEnforcer.net/2010/07/manually-entered-date-value-in-apex-soql-query/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>List has no rows for assignment to SObject</title>
		<link>http://theEnforcer.net/2009/09/list-has-no-rows-for-assignment-to-sobject/</link>
		<comments>http://theEnforcer.net/2009/09/list-has-no-rows-for-assignment-to-sobject/#comments</comments>
		<pubDate>Sat, 12 Sep 2009 22:46:33 +0000</pubDate>
		<dc:creator>The Enforcer</dc:creator>
				<category><![CDATA[Apex]]></category>
		<category><![CDATA[SOQL]]></category>

		<guid isPermaLink="false">http://theEnforcer.net/?p=122</guid>
		<description><![CDATA[Here&#8217;s a lesson I learned while making our Cloud Developer Challenge entry. Take a look at these lines of code and tell me which ones are OK and which ones are dangerous: integer count = [SELECT count() FROM Contact]; Contact c1 = [SELECT Id FROM Contact LIMIT 1]; Contact c2 = [SELECT Id FROM Contact [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a lesson I learned while making our Cloud Developer Challenge entry.</p>
<p>Take a look at these lines of code and <strong>tell me which ones are OK and which ones are dangerous:</strong></p>
<pre class="brush: java; light: true;">integer count = [SELECT count() FROM Contact];
Contact c1 = [SELECT Id FROM Contact LIMIT 1];
Contact c2 = [SELECT Id FROM Contact LIMIT 1];
Id first = [SELECT Id FROM Contact LIMIT 1].Id;
Contact[] contacts = [SELECT Id FROM Contact LIMIT 1];
Contact[] allContacts = [SELECT Id FROM Contact];</pre>
<p>If you executed the above code on most systems, it will run just fine. However, there is a situation in which you&#8217;ll get the dreaded <code><span style="color: #ff0000;">List has no rows for assignment to SObject</span></code> error. Can you figure out which one?</p>
<p><strong>It&#8217;s when there&#8217;s no objects to return!</strong></p>
<p>For example, if you have a system with no Contracts, try running the above code with <code>Cont<strong><span style="color: #ff0000;">r</span></strong>act</code> in place of <code>Contact</code> and you&#8217;ll get:</p>
<p><code><span style="color: #ff0000;">ERROR - Evaluation error: System.QueryException: List has no rows for assignment to SObject<br />
ERROR - Evaluation error: AnonymousBlock: line 2, column 15</span></code></p>
<p>What happened? Well, these 3 lines will all give an error if there&#8217;s no row found:</p>
<pre class="brush: java; light: true;">Contact c1 = [SELECT Id FROM Contact LIMIT 1];
Contact c2 = [SELECT Id FROM Contact LIMIT 1];
Id first = [SELECT Id FROM Contact LIMIT 1].Id;
</pre>
<p>While a <code>SELECT</code> normally returns an array/list, these statements are using the shorthand syntax that assumes only one row is returned. What&#8217;s not obvious is that it also assumes that <strong><span style="text-decoration: underline;">exactly</span> one row is returned!</strong></p>
<p>While this is unlikely to occur for <code>Contact</code>, it is highly likely to occur for any custom objects you create, especially when a <code>WHERE</code> statement is used that might return zero rows, such as:</p>
<pre class="brush: java;">Player__c player = [SELECT Id from Player__c where Name = :username];
if (player != null)
    p = player.Id;</pre>
<p><strong>The above code will fail</strong> if there is no <code>Player__c</code> record with the matching username. It doesn&#8217;t actually return a <code>null</code>.</p>
<p>It would be safer to do the following:</p>
<pre class="brush: java;">Player__c[] players = [SELECT Id from Player__c where Name = :username];
if (players.size() &gt; 0)
    p = players[0].Id;</pre>
<p>It&#8217;s one of those situations for which you wouldn&#8217;t normally think of creating a test, so it&#8217;s safer to just avoid the possibility rather than making an assumption about your data.</p>
<h3>The Bottom Line</h3>
<ul class="nomargin">
<li>The shorthand syntax that expects one row to be returned from a <code>SELECT</code> statement is very handy</li>
<li>It&#8217;s also dangerous if no rows are found!</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://theEnforcer.net/2009/09/list-has-no-rows-for-assignment-to-sobject/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
