function readOnly(count){ }
Don't have an account?
Search for an answer or ask a question of the zone or Customer Support.
You need to sign in to do that
Sign in to start searching questions
Signup for a Developer Edition
Sign in to start a discussion
ガバナー制限としてSOQLにて取得できるレコード数の上限は1万件まで(Trigger,Testは除く)というのが定められています。
(Total number of records retrieved by SOQL queries 10,000)
これはSOQLのCount()でも適用されるようです。
Integer i = [SELECT Count() FROM Account];
あるオブジェクトのレコード数を出したい場合で、その数が1万件を超える可能性がある場合、
このガバナーを回避して数を取得する方法があるでしょうか?
うーーん、ガバナ制限は回避するのはおそらく。。。 (ヾノ・∀・`)ムリムリ
StandardSetController クラスを利用すれば 5千万件まではカウントできると思われます。
以下のページを参考になるかもしれません。
http://www.salesforce.com/us/developer/docs/pages/Content/apex_pages_standardsetcontroller.htm#kanchor889
StandardSetControllerの中
getResultSizeメソッドがあるのこちらを利用してみるっす。
サンプルコードです。
Visualforceページ:Sample
<apex:page controller="TempController"> <apex:form> <apex:commandButton action="{!TestExec}" value="TestMethodCall" reRender="SizeSection"/> </apex:form> <p> <apex:outputPanel id="SizeSection"> 配列サイズ = <apex:outputText value="{!DataSize}" /> </apex:outputPanel> </p></apex:page>
コントローラ:TempController
public class TempController { public Long DataSize{get; set;} public PageReference TestExec() { ApexPages.StandardSetController ssc = new ApexPages.StandardSetController(Database.getQueryLocator([SELECT name FROM Contact])); DataSize = ssc.getResultSize(); return null; }}
5千万件を超える場合は Ajax(WebservicesAPI)の併用を検討してみはどうでしょうか?
LovelyWankoさん
頂いたSampleをAccountが1万件以上ある組織で実行したところ、ガバナーのエラーが発生しました。
たしかにドキュメントにはDatabase.QueryLocatorにて5000万件まで取得可能みたいなことが書かれていますが、
これって、あくまでガバナーに触れなければ5000万件まで可能ということじゃないでしょうか?
例えばBatch Apexのstartメソッドで返す時の値とか。
AJaxに関しては、これを使用すると今度はAPIコール数の問題とか出てくるんで、使いどころを見極める必要がありそうです。
そうするとApexのみで考えるとやはり1万件の問題は解決しないわけですが。。
今のところ「カウントしたいオブジェクトの総数を管理する別テーブルを作成してTriggerで更新」
というようなイケてない方法しか思いつきません。。
まぁ、何か作っていて問題が発生しているわけではなく、あくまで気になっただけの問題なので緊急性はないのですが。
:smileysurprised: Database.QueryLocatorを通常のApexクラスで利用しても1万件を超える
とエラーになってしまうのですね!
BatchApex のときが有効なのですね。
Ikouさんの案:カスタムオブジェクトなどにTriggerで都度カウントしておきQueryで全件のカウント
を取得すると ⇒ な~るほど the world。(ちょっと古い :robotsurprised:)
苦肉の策として思いついたのは、BatchApexを非同期で呼び出してBatchApexの処理結果を
カスタムオブジェクトに書き出してポーリングなどをかけてその結果に書き出されたカスタムオブジェクト
から値を取得する感じですか。。。:smileysad:
http://hikey.web.fc2.com/discussion_boards/partnersmall.xml
1万件以上をApexコントローラから取得する方法を考えた見たyo :smileysurprised:
ApexコントローラからSalesforceサーバに対してCallOutを行う方法 ヾ(・∀・o)ノダー!!
以下の手順で行ってみるyo (`・ω・´)
1.リモートサイトの設定
ログインURL と API で使うURL(LoginResult でReturnされるURL)を設定
σ(・Д・`) の場合 ログインURL:https://www.salesforce.com
APIのURL(ログインすると帰ってくるAPI利用サーバ):https://na7-api.salesforce.com
2.WSDLからApexクラスを生成する!!。
SFのParner.wsdlを利用。ただしそのままだとApexクラスが大きくなりすぎてエラーになるのでQueryとログインに必要そうな定義だけに削る。
3.後はCallOutを実装するだけ
縮小版PartnerWSDL:
Apexコントローラ:
public class QueryCallOutSampleController { partnerSoapSforceCom.Soap bind = new partnerSoapSforceCom.Soap(); public QueryCallOutSampleController(){ } public PageReference Query() { partnerSoapSforceCom.LoginResult result = bind.login('<loginId>', '<password>'); bind.endpoint_x = result.serverUrl; partnerSoapSforceCom.SessionHeader_element sh = new partnerSoapSforceCom.SessionHeader_element(); sh.sessionId = result.sessionId; //ログインしない場合は自分のセッションIDを利用 //sh.sessionId = UserInfo.getSessionId(); bind.SessionHeader = sh; partnerSoapSforceCom.QueryResult qresult = bind.query('Select count() from Account'); return null; } }
呼び出しVisualforce:
<apex:page controller="QueryCallOutSampleController"> <apex:form > <apex:commandButton action="{!Query}" value="CallOut"/> </apex:form> </apex:page>
Hikeyさん
すみません、返事が遅くなりました!
仕事でJavaScriptが動作しない環境にいるのでDiscussionBoardsを見ることができず。。。
というグチはさておき。
お二人とも方法を考えて頂き、ありがとうございます。
特にHikeyさん案のコントローラからCallOutを行うという方法は考えもしませんでした。
ただ、私の知識不足でぱっと見で理解できないので、時間があるときにちょっと検証してみたいと思います。
うーーん、ガバナ制限は回避するのはおそらく。。。 (ヾノ・∀・`)ムリムリ
StandardSetController
クラスを利用すれば 5千万件まではカウントできると思われます。
以下のページを参考になるかもしれません。
http://www.salesforce.com/us/developer/docs/pages/Content/apex_pages_standardsetcontroller.htm#kanchor889
StandardSetControllerの中
getResultSizeメソッドがあるのこちらを利用してみるっす。
サンプルコードです。
Visualforceページ:Sample
<apex:page controller="TempController">
<apex:form>
<apex:commandButton action="{!TestExec}" value="TestMethodCall" reRender="SizeSection"/>
</apex:form>
<p>
<apex:outputPanel id="SizeSection">
配列サイズ = <apex:outputText value="{!DataSize}" />
</apex:outputPanel>
</p>
</apex:page>
コントローラ:TempController
public class TempController {
public Long DataSize{get; set;}
public PageReference TestExec() {
ApexPages.StandardSetController ssc =
new ApexPages.StandardSetController(Database.getQueryLocator([SELECT name FROM Contact]));
DataSize = ssc.getResultSize();
return null;
}
}
5千万件を超える場合は Ajax(WebservicesAPI)の併用を検討してみはどうでしょうか?
LovelyWankoさん
頂いたSampleをAccountが1万件以上ある組織で実行したところ、ガバナーのエラーが発生しました。
たしかにドキュメントにはDatabase.QueryLocatorにて5000万件まで取得可能みたいなことが書かれていますが、
これって、あくまでガバナーに触れなければ5000万件まで可能ということじゃないでしょうか?
例えばBatch Apexのstartメソッドで返す時の値とか。
AJaxに関しては、これを使用すると今度はAPIコール数の問題とか出てくるんで、使いどころを見極める必要がありそうです。
そうするとApexのみで考えるとやはり1万件の問題は解決しないわけですが。。
今のところ「カウントしたいオブジェクトの総数を管理する別テーブルを作成してTriggerで更新」
というようなイケてない方法しか思いつきません。。
まぁ、何か作っていて問題が発生しているわけではなく、あくまで気になっただけの問題なので緊急性はないのですが。
:smileysurprised: Database.QueryLocatorを通常のApexクラスで利用しても1万件を超える
とエラーになってしまうのですね!
BatchApex のときが有効なのですね。
Ikouさんの案:カスタムオブジェクトなどにTriggerで都度カウントしておきQueryで全件のカウント
を取得すると ⇒ な~るほど the world。(ちょっと古い :robotsurprised:)
苦肉の策として思いついたのは、BatchApexを非同期で呼び出してBatchApexの処理結果を
カスタムオブジェクトに書き出してポーリングなどをかけてその結果に書き出されたカスタムオブジェクト
から値を取得する感じですか。。。:smileysad:
http://hikey.web.fc2.com/discussion_boards/partnersmall.xml
1万件以上をApexコントローラから取得する方法を考えた見たyo :smileysurprised:
ApexコントローラからSalesforceサーバに対してCallOutを行う方法 ヾ(・∀・o)ノダー!!
以下の手順で行ってみるyo (`・ω・´)
1.リモートサイトの設定
ログインURL と API で使うURL(LoginResult でReturnされるURL)を設定
σ(・Д・`) の場合 ログインURL:https://www.salesforce.com
APIのURL(ログインすると帰ってくるAPI利用サーバ):https://na7-api.salesforce.com
2.WSDLからApexクラスを生成する!!。
SFのParner.wsdlを利用。ただしそのままだとApexクラスが大きくなりすぎてエラーになるのでQueryとログインに必要そうな定義だけに削る。
3.後はCallOutを実装するだけ
縮小版PartnerWSDL:
http://hikey.web.fc2.com/discussion_boards/partnersmall.xml
Apexコントローラ:
呼び出しVisualforce:
LovelyWankoさん
Hikeyさん
すみません、返事が遅くなりました!
仕事でJavaScriptが動作しない環境にいるのでDiscussionBoardsを見ることができず。。。
というグチはさておき。
お二人とも方法を考えて頂き、ありがとうございます。
特にHikeyさん案のコントローラからCallOutを行うという方法は考えもしませんでした。
ただ、私の知識不足でぱっと見で理解できないので、時間があるときにちょっと検証してみたいと思います。