Okay, for sure you went the right way, then!
Getting the countries other than USA & Canada via the UNION would be a royal pain.
I don't think you are going to do better than what you have.
Well, not strictly true.
One thing you *COULD* do would be to create a unified StatesAndProvinces table. Instead of having the two separate tables.
Easy enough to do:
And now do all your operations against a single table. Such as
SELECT 226 AS bcntry_id, id, abbr
INSERT INTO StatesAndProvinces (bcntry_id, id, abbr)
SELECT 38, id, abbr
SELECT c.*, sap.abbr
FROM contacts AS c
LEFT JOIN StatesAndProvinces AS sap ON (c.bstate_id = sap.id AND c.bcntry_id = sap.bcntry_id)
Since neither the list of states nor the list of provinces is likely to change real often, why not?
Surely would gain a lot of efficiency at the minor cost of a pretty small additional table.