function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Integration User 181Integration User 181 

Update record on External ID

Hi,

We are using Talend middleware to integrate and exchange data between our internal systems and SF using SF API. The SF CRM is acting as a 'slave' while our system database is a master.  So, almost every object in SF has an external ID that maches the record in our DB. 

All our 'upserts' works fine when matched on External ID. But in this case, we need to update - not upsert - the record in SF using External ID, which is marked as unique in SF. 

But, when runing the code this is the error: MISSING_ARGUMENT:Id not specified in an update call - for every single record regardles if the External ID already exist in SF or not.

So, my question is - can update be done on External ID or it must be the SF Id ?

Thanks


 
Best Answer chosen by Integration User 181
Daniel BallingerDaniel Ballinger
So you have a collection of records that you want to send updates to Salesforce for. Some of them may exist in Salesforce already with the External ID field set. Some of them won't?

If, as you say, you don't have the Salesforce ID or another way in you local system to identify which records are already in Salesforce, you would need to do a SOQL query first to identifiy which External Ids existing in Salesforce.

I.e.
  1. Get the list of all the External IDs you want to update
  2. Do a SOQL query to Salesforce to see which of those records exist in Salesforce already
  3. Only do the upsert for the records that are already in Salesforce (by this stage you could also do an update() as the SOQL query could bring back the Salesforce ID)
Again, as you say, if you can add the Salesforce ID to the local system or otherwise keep track of which records are already in Salesforce it would be more efficent in terms of Salesforce API calls.

All Answers

Daniel BallingerDaniel Ballinger
The update() API requires the ID to be defined. Only the upsert call supports using the External Id. If you look at them in the API documentation you will see that upsert(String externalIdFieldName, sObject[] sObjects) (https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_calls_upsert.htm) has externalIdFieldName to identify the external Id field to use. Without this it wouldn't be possible to work with sObject containing multiple external Ids.

You can safely use upsert instead of update. It will just convert all the actions to an update when the corresponding records are found with matching external ids.
Integration User 181Integration User 181
Hi Daniel,

Thank you very much for fast reply.

The problem is that we are updating just a 'flag' in custom object 'Application__c' that represents our student applpications, we are educational institution. So we need to update the status of the application - 'acknowledged' ,  'in progress' , 'enrolled'... and so on.

I have tried usiong 'upsert' but for every record that does not have External ID yet ( and shouldn't have - integration flow rules - the student is not yet created in our internal system - so no External ID ), in SF the 'upsert' action created the record in Application__c - basicaly orphaned applications.  What UPSERT should do - update or insert if not exist. At this stage we are not saving the SF ID of the record in our internal system.

So I am guessing that we should save the SF Id of the Application when created/synced with our internal system, then using the same id - update the status of the Application in SF when changed by admins in our internal system.

Thanks again
Alex
 
Daniel BallingerDaniel Ballinger
So you have a collection of records that you want to send updates to Salesforce for. Some of them may exist in Salesforce already with the External ID field set. Some of them won't?

If, as you say, you don't have the Salesforce ID or another way in you local system to identify which records are already in Salesforce, you would need to do a SOQL query first to identifiy which External Ids existing in Salesforce.

I.e.
  1. Get the list of all the External IDs you want to update
  2. Do a SOQL query to Salesforce to see which of those records exist in Salesforce already
  3. Only do the upsert for the records that are already in Salesforce (by this stage you could also do an update() as the SOQL query could bring back the Salesforce ID)
Again, as you say, if you can add the Salesforce ID to the local system or otherwise keep track of which records are already in Salesforce it would be more efficent in terms of Salesforce API calls.
This was selected as the best answer
Integration User 181Integration User 181
Hi,

Yes, that looks like the good option. I think that is a way to go as we can't use upsert. We already getting the list of External IDs returned by our system API that we want to update, I can then do a SOQL lookup in SF and retrieve ID and do update.

Thank you for your help.
Alex
Daniel BallingerDaniel Ballinger
Great, glad to help. As an assistance to others who arrive here in the future and to other members looking to answer questions you may like to select one of the response and use the "accept as answer link", This will make it clearer how it was resolved and that no further action is required.
Develop Team 1Develop Team 1

Actually, the primary benefit of upsert (https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_calls_upsert.htm" target="_blank) is that it saves the requests count since it does not require a prior query (https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_calls_query.htm" target="_blank)
But the current version of update (https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_calls_update.htm" target="_blank) requires it when you know only the external ID value because it requires the internal ID value.

I am wonering if it might be upgraded in some upcoming version of API.

MrBrianMrBrian
There is a workaround for this. Create a validation rule for the object you are upserting, ie, that a certain field must have a value or not have a value in order to be created or edited; make sure that every value you insert has passes that validation run. When when you do your upsert, make sure that said field does not pass the validation rule. This way, only records already in the DB get updated, while anything that is not there will not get inserted since it will not pass the validation check.