You are correct Lucas that you do need a conditional statement. Something like the following:
$user_preferences->userid = $usernew->id;
$user_preferences->name = 'docked_block_instance_5';
$user_preferences->value = '1';
$query = 'select id from mdl_user_preferences where userid='.$user_preferences->userid.' and name=\''.$user_preferences->name.'\';';
$result = $DB->get_record_sql($query);
if ($result) { // update
$user_preferences->id = $result->id;
$DB->update_record('user_preferences', $user_preferences);
} else { // insert
$DB->insert_record('user_preferences', $user_preferences);
}
The error that you are seeing is being raised because you are trying to insert a row over a row that already exists. So a check must be put in place to determine if the information you are trying to edit already exists and if it does update instead of insert. I found this error by turning on all levels of debugging from Site administration -> Development -> Debugging.
Of course though, as I was digging into this there seem to be some caveats worth mentioning IMO. For one, this all works based off of when a user is enrolled in a course or user information is changed. What happens if an admin adds another instance of a block through the admin interface, but never interacts with the user once said user is enrolled? I am thinking of something like the settings block where you can end up with multiple instances within one user interface. Also, the number in something like "docked_block_instance_5" comes from the instance of the block itself from the mdl_block_instances table and is generated as blocks are added throughout the life of the system. So unless you are going to periodically check your DB for new instances there must be an instance of code somewhere that automatically handles re-docking if you will anytime a change is made otherwise you might end up with some odd circumstances.
Interestingly, I am working on all of the caveats I just mentioned because I am looking for a solution to this as well. Ian my particular case I would like to dock the settings block for all students, but not for admins, teachers, etc... I am new to all of this, but from what I can tell the settings block seems unique compared to other blocks in the way it is propagated across my site and even though I can find the instance of settings that applies to all pages and auto-dock for students it would only take on admin to add another settings block with a slightly different pagetypepattern to throw it all off.