upsert()
新しいオブジェクトを作成するか、既存のオブジェクトを更新します。カスタム項目を使用して、既存オブジェクトの有無を判別します。セールスフォース・ドットコムでは、多くの場合、不要な重複レコードが作成されないようにするために、create() の代わりに upsert() を使用することをお勧めしています。API バージョン 7.0 以降で使用できます。create() または update() コールでは複数のオブジェクト種別のレコードを処理できますが、upsert() ではすべてのレコードのオブジェクト種別が同じである必要があります。
構文
1UpsertResult[] = connection.upsert(String externalIdFieldName, sObject[] sObjects);使用方法
Upsert は、insert と update の結合したものです。このコールは、オブジェクトに外部 ID 項目または項目プロパティが idLookup の項目がある場合、オブジェクトに使用できます。
カスタムオブジェクトの場合、このコールは、外部 ID というインデックス付けされたカスタム項目を使用して、新しいレコードを作成するか、既存オブジェクトを更新するかを判別します。標準オブジェクトの場合、このコールは外部 ID の代わりに、項目プロパティが idLookup プロパティの項目の名前を使用できます。
外部 ID 項目など、カスタム項目のオブジェクトへの追加に関する詳細は、Salesforce オンラインヘルプの項目の追加に関するトピックを参照してください。
- 組織の Salesforce データと、経理や製造など��� ERP (統合業務ソフト) システムと統合する場合。
- データをインポートして、重複オブジェクトの作成を回避する場合。
[外部 ID] 属性および Unique 属性の両方が選択された (インデックスが一意) カスタム項目を持つオブジェクトのレコードを更新/挿入する場合、Unique 属性によって重複作成が防止されるため、特別な権限は必要ありません。[外部 ID] 属性が選択され、Unique 属性が選択されていない (インデックスが一意ではない) オブジェクトのレコードを更新/挿入する場合、クライアントアプリケーションがこのコールを実行するには「すべてのデータの参照」権限が必要です。この権限を割り当てることにより、クライアントアプリケーションでは、レコードの存在を確認できないことが原因で upsert() によって誤って重複レコードが挿入される事態を回避できます。
upsert が update() と create() を判別する方法
upsert では、外部 ID を使用して、新規レコードを作成するか、既存レコードを更新するかを判別します。
- 外部 ID が一致しない場合、新規レコードが作成されます。
- 外部 ID が一度だけ一致したら、既存レコードが更新されます。
- 外部 ID が複数回一致すると、エラーが報告されます。
- バッチコールで外部 ID が同じ複数のレコードを一括更新すると、それらのレコードは、UpsertResult ファイルでエラーとしてマークされます。レコードは作成も更新もされません。
エラー時のロールバック
AllOrNoneHeader ヘッダーを使用すると、すべてのレコードが正常に処理されない限り、すべての変更をロールバックできます。このヘッダーは、API バージョン 20.0 以降で使用できます。デフォルトの動作では、コールの部分的な成功を許可します。つまり、エラーのないレコードはコミットされますが、エラーのあったレコードはコールの結果では失敗とマークされます。
Chatter フィードの自動登録
作成するレコードを登録するには、ユーザは個人設定の [作成したレコードを自動的にフォローする] オプションを有効にする必要があります。自動登録が有効化されている場合、ユーザは自分が作成したレコードを自動的にフォローし、それらのレコードへの変更が [ホーム] タブの Chatter フィードに表示されます。
レコードの所有者を更新する場合、新しい所有者が Chatter フィード設定でレコードの自動登録が有効化されていない限り、新しい所有者は自動的にレコードに登録されません。前の所有者の登録は自動的には解除されません。新しい所有者のレコードの自動登録が有効化されている場合は、新旧両方の所有者のニュースフィードでレコードへの変更が表示されます。
ユーザはレコードまたは他のユーザを登録できます。レコードへの変更とユーザからの更新は、ユーザのホームページの Chatter フィードに表示されます。これは、Salesforce で他のユーザやレコードに加えられた変更の最新状況を把握するのに役立ちます。フィードは、API バージョン 18.0 以降で使用できます。
upsert() と外部キー
外部 ID 項目を外部キーとして使用することによって、最初に親レコードの ID をクエリするのではなく、レコードを作成または更新して他の既存のレコードに関連付ける操作を 1 つの手順で実行できます。これを行うには、指定された外部 ID 項目のみを持つ親 sObject のインスタンスに、外部キーを設定します。この外部 ID は親レコードの外部 ID の値と一致する必要があります。create() とは異なり、upsert() を使用して外部キーで関連する子レコードを作成または更新するには、親レコードがすでに存在する必要があります。
次の Java および C# の例では、商談を更新/挿入します。この場合、商談はデータベースに存在しないので、upsert() コールによって作成されます。この商談は既存の取引先を参照します。個別のクエリを取得する必要がある取引先 ID を指定せず、取引先の外部 ID、この例では MyExtId__c カスタム項目を指定します。
Java の例
1swfobject.registerObject("clippy.codeblock-1", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public void upsertForeignKeySample() {
18 try {
19 Opportunity newOpportunity = new Opportunity();
20 newOpportunity.setName("UpsertOpportunity");
21 newOpportunity.setStageName("Prospecting");
22 Calendar dt = connection.getServerTimestamp().getTimestamp();
23 dt.add(Calendar.DAY_OF_MONTH, 7);
24 newOpportunity.setCloseDate(dt);
25 newOpportunity.setMyExtId__c("UPSERTID001");
26
27 // Parent Account record must already exist
28 Account parentAccountRef = new Account();
29 parentAccountRef.setMyExtId__c("SAP111111");
30 newOpportunity.setAccount(parentAccountRef);
31
32 SaveResult[] results = connection
33 .upsert("MyExtId__c", new SObject[] { newOpportunity });
34 } catch (ConnectionException ce) {
35 ce.printStackTrace();
36 }
37}C# の例
1swfobject.registerObject("clippy.codeblock-2", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public void upsertForeignKeySample()
18{
19 try
20 {
21 Opportunity newOpportunity = new Opportunity();
22 newOpportunity.Name = "UpsertOpportunity";
23 newOpportunity.StageName = "Prospecting";
24 DateTime dt = (DateTime)binding.getServerTimestamp().timestamp;
25 newOpportunity.CloseDate = dt.AddDays(7);
26 newOpportunity.CloseDateSpecified = true;
27 newOpportunity.MyExtId__c = "UPSERTID001";
28
29 // Parent Account record must already exist
30 Account parentAccountRef = new Account();
31 parentAccountRef.MyExtId__c = "SAP111111";
32 newOpportunity.Account = parentAccountRef;
33
34 SaveResult[] results = binding
35 .upsert("MyExtId", new sObject[] { newOpportunity });
36 }
37 catch (SoapException e)
38 {
39 Console.WriteLine("An unexpected error has occurred: " +
40 e.Message + "\n" + e.StackTrace);
41 }
42}upsert() と多態��な外部キー
多態的なキーでは、その ID で複数の種別のオブジェクトを親として参照できます。たとえば、Case オブジェクトの OwnerId 項目は、User または Group のいずれかを参照できます。同様に、Task オブジェクトの WhoID 項目は、Contact または Lead のいずれかを参照できます。
サンプルコード —Java
このサンプルでは、MyExtId__c というカスタム外部 ID 項目を使用して 2 つの取引先を更新/挿入します。upsert() コールでは、取引先を作成するか更新するかを決定するため、MyExtId__c 項目に基づいて取引先を照合します。このサンプルを実行する前に、MyExtId__c 項目名を組織の既存のカスタム ID 項目名に変更してください。
1swfobject.registerObject("clippy.codeblock-3", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public void upsertRecords() {
18 SObject[] upserts = new Account[2];
19
20 Account upsertAccount1 = new Account();
21 upsertAccount1.setName("Begonia");
22 upsertAccount1.setIndustry("Education");
23 upsertAccount1.setMyExtId__c("1111111111");
24 upserts[0] = upsertAccount1;
25
26 Account upsertAccount2 = new Account();
27 upsertAccount2 = new Account();
28 upsertAccount2.setName("Bluebell");
29 upsertAccount2.setIndustry("Technology");
30 upsertAccount2.setMyExtId__c("2222222222");
31 upserts[1] = upsertAccount2;
32
33 try {
34 // Invoke the upsert call and save the results.
35 // Use External_Id custom field for matching records.
36 UpsertResult[] upsertResults = connection.upsert(
37 "MyExtId__c", upserts);
38 for (UpsertResult result : upsertResults) {
39 if (result.isSuccess()) {
40 System.out.println("\nUpsert succeeded.");
41 System.out.println((result.isCreated() ? "Insert" : "Update")
42 + " was performed.");
43 System.out.println("Account ID: " + result.getId());
44 } else {
45 System.out.println("The Upsert failed because: "
46 + result.getErrors()[0].getMessage());
47 }
48 }
49 } catch (ConnectionException ce) {
50 ce.printStackTrace();
51 }
52}サンプルコード —C#
このサンプルでは、MyExtId__c というカスタム外部 ID 項目を使用して 2 つの取引先を更新/挿入します。upsert() コールでは、取引先を作成するか更新するかを決定するため、MyExtId__c 項目に基づいて取引先を照合します。このサンプルを実行する前に、MyExtId__c 項目名を組織の既存のカスタム ID 項目名に変更してください。
1swfobject.registerObject("clippy.codeblock-4", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public void upsertRecords()
18{
19 sObject[] upserts = new Account[2];
20
21 Account upsertAccount1 = new Account();
22 upsertAccount1.Name = "Begonia";
23 upsertAccount1.Industry = "Education";
24 upsertAccount1.MyExtId__c = "1111111111";
25 upserts[0] = upsertAccount1;
26
27 Account upsertAccount2 = new Account();
28 upsertAccount2 = new Account();
29 upsertAccount2.Name = "Bluebell";
30 upsertAccount2.Industry = "Technology";
31 upsertAccount2.MyExtId__c = "2222222222";
32 upserts[1] = upsertAccount2;
33
34 try
35 {
36 // Invoke the upsert call and save the results.
37 // Use External_Id custom field for matching records.
38 UpsertResult[] upsertResults =
39 binding.upsert("MyExtId__c", upserts);
40 foreach (UpsertResult result in upsertResults)
41 {
42 if (result.success)
43 {
44 Console.WriteLine("\nUpsert succeeded.");
45 Console.WriteLine(
46 (result.created ? "Insert" : "Update") +
47 " was performed."
48 );
49 Console.WriteLine("Account ID: " + result.id);
50 }
51 else
52 {
53 Console.WriteLine("The Upsert failed because: " +
54 result.errors[0].message);
55 }
56 }
57 }
58 catch (SoapException e)
59 {
60 Console.WriteLine("An unexpected error has occurred: " +
61 e.Message + "\n" + e.StackTrace);
62 }
63}