Success! Sort of …
Instead of the complicated method I described previously, I’ve gone manual, which is, yes, more complicated :-).
I started with the latest sms.db file from my new iPhone, and then editing SQLite scripts, incremented the ROWIDs by 30,000 for the message table, and 1000 for the others, so as to avoid collisions. I then ran the INSERT statements from the old sms.db file, with their original ROWIDs, so that they’d slot in before the newer stuff. There are significant gaps in the ROWIDs, but I don’t care about those because I can store two billion messages before I run out of numbers.
The iBackupBot restore was a success, albeit edge-of-my-seat stuff when I opened the Messages app and got a blank screen (it eventually opened up, but it took a while).
The biggest complication was the relationships between chats, handles and messages. I still don’t know what a handle is, but to be fair, I haven’t even looked at the table closely.
Because the chat table has a unique constraint on the [guid] field, which forced me to go manual, I had to map this value back to the old sms.db chat table, and this is where the “sort of” in my original statement comes from: some of the conversation threads (chats) were wrongly attributed to contacts, groups of contacts, and so on. This is due to my naïveté in understanding the data.
Second phase is to analyse the records more closely to see how handles and chats work exactly, and then use a different method to remove duplication.
So for all you people out there, I am using SQLiteAdmin, TextPad, and a lot of patience to manually match key fields between both databases.
2013-03-09 Edit: According to John Lehr, the handle_id is the link I should have deduplicated first, before doing the chat_id. Simple enough (though manual), so I’ll keep that in mind when I address this again.