It would be really weird to have lookups silently count as ext. id fields...
Try performing describe calls on all objects in your package that you suspect to clash? I have a custom field marked as "External Id", "Unique Case Insensitive" and I get this:
Schema.DescribeFieldResult f = Account.Account_Number__c.getDescribe();
System.debug(f.isExternalID()); // true
System.debug(f.isUnique()); // true
System.debug(f.isIdLookup()); // true
EDIT:
There are 3 unique / ext. id fields per object. Ask support for increase.
BUT
How many formulas do you have on the objects that can be "common" with the other package. And do these formulas utilize in total 10 lookups to different places? (scroll to "Formulas: Number of Unique Relationships Per Object" text)?
I can imagine this being different kind of limit (put in place because too many lookups / formulas make joins in the underlying database extra painful to retrieve data). In that case you might have to consider rewriting some of your lookups into fields updated with triggers (always pain in managed package as I understand).
Upsert depends upon the value of External ID
fields being unique. If you choose to not make External ID
unique, you cannot leverage this feature. This means that you would need to leverage external logic in order to perform the upsert operations. Either clean up your data, or use external logic. One potential solution could be to write a trigger to eliminate a previous External ID matching the record's value when it is inserted or updated; you'll still need to clean up data that existed before this trigger was implemented. Off the top of my head, your trigger might look like this:
trigger clearOldIds on Contact (after insert, after update) {
Set<String> newIds = new Set<String>(); // All new ID values
for(Contact record:Trigger.new)
newIds.add(record.External_Id__c);
newIds.remove(null); // Ignore blank values
Contact[] others = [SELECT Id FROM Contact WHERE External_Id__c IN :newIds AND Id NOT IN :Trigger.new];
for(Contact record:others) // Clear old IDs
record.External_ID__c = null;
update others;
}
This would probably work in most cases, but you'll need to clean up your data at least once for this to operate correctly.
Another solution would be to create a service that your external service could consume. Here's a primitive example that would cover this:
global with sharing class SystemUtils {
global webservice void upsertLast(Contact[] records) {
Map<String, Id> uniqueValues = new Map<String, Id>();
Contact[] newRecords = new Contact[0], oldRecords = new Contact[0];
for(Contact record:records)
uniqueValues.put(record.External_ID__c,null);
for(Contact record:[SELECT Id,External_ID__c FROM Contact WHERE External_Id__c IN :uniqueValues.keySet() ORDER BY SystemModStamp ASC])
uniqueValues.put(record.External_Id__c, record.Id);
for(Contact record:records)
record.Id = uniqueValues.get(record.External_Id__c);
for(Contact record:records)
(record.Id==null?newRecords:oldRecords).add(record);
insert newRecords;
update oldRecords;
}
}
I haven't implemented error checking, that'd be the last step, but this sort of code would conceivably work assuming there were no errors.
Best Answer
Yes, those fields can have a NULL value but wont serve the purpose.
External ID: This is a field that usually references an ID from another (external) system. For instance, if the customer has an Oracle Financials system that they will be linking with salesforce.com, it may be easier for them to be able to refer to the Oracle ID of account records from within salesforce. So they would create an external ID in salesforce.com and they would load the Oracle ID into that field for each account. They can then refer to that ID field, rather than the salesforce.com id.
Additionally, if you have an external ID field, the field becomes searchable in the sidebar search. You also can use the upsert API call with the extenal ID to refer to records.
You can have multiple records with the same external ID (though it is not reccomended, as it will defeat the purpose of the external id)
Unique ID field
This is a setting for the field that will prevent you from using the same value in multiple records for the unique field. So if I create a 5 character text field and make it unique, and I create a record with the value "12345" I will not be able to create another record with that same value in the unique field. If I try to do so, I will get an error saying that the value is already in use.
Often, External Ids are set with the unique property so that the IDs will be unique to each record.
Please refer to : https://help.salesforce.com/HTViewHelpDoc?id=custom_field_attributes.htm&language=en_US