diff --git a/grade/edit/letter/index.php b/grade/edit/letter/index.php
index d0dc35a..f854deb 100644
--- a/grade/edit/letter/index.php
+++ b/grade/edit/letter/index.php
@@ -137,7 +137,7 @@ if (!$edit) {
         }
 
         $letters = array();
-        for($i=1; $i<$num+1; $i++) {
+        for ($i=1; $i < $num+1; $i++) {
             $gradelettername = 'gradeletter'.$i;
             $gradeboundaryname = 'gradeboundary'.$i;
 
@@ -146,32 +146,54 @@ if (!$edit) {
                 if ($letter == '') {
                     continue;
                 }
-                $letters[$data->$gradeboundaryname] = $letter;
+
+                $boundary = floatval($data->$gradeboundaryname);
+
+                if ($boundary < 0 || $boundary > 100) {
+                    continue;    // skip if out of range
+                }
+
+                $letters[number_format($boundary, 5)] = $letter;
             }
         }
-        krsort($letters, SORT_NUMERIC);
 
-        $old_ids = array();
-        if ($records = $DB->get_records('grade_letters', array('contextid' => $context->id), 'lowerboundary ASC', 'id')) {
-            $old_ids = array_keys($records);
+        $pool = array();
+        if ($records = $DB->get_records('grade_letters', array('contextid' => $context->id), 'lowerboundary ASC')) {
+            foreach ($records as $r) {
+                // will re-use the lowerboundary to avoid duplicate during the update process
+                $pool[number_format($r->lowerboundary, 5)] = $r;
+            }
         }
 
-        foreach($letters as $boundary=>$letter) {
+        foreach ($letters as $boundary => $letter) {
             $record = new stdClass();
             $record->letter        = $letter;
             $record->lowerboundary = $boundary;
             $record->contextid     = $context->id;
 
-            if ($old_id = array_pop($old_ids)) {
-                $record->id = $old_id;
+            // re-use the existing boundary to avoid key constraint
+            if (isset($pool[$boundary])) {
+                // skip if the letter has been assigned to the boundary already
+                if ($letter == $pool[$boundary]->letter) {
+                    unset($pool[$boundary]); // take it out of the pool
+                }
+                else {
+                    $record->id = $pool[$boundary]->id;
+                    $DB->update_record('grade_letters', $record);
+                    unset($pool[$boundary]);    // remove the ID from the pool
+                }
+            }
+            else if ($candidate = array_pop($pool)) {
+                $record->id = $candidate->id;
                 $DB->update_record('grade_letters', $record);
             } else {
                 $DB->insert_record('grade_letters', $record);
             }
         }
 
-        foreach($old_ids as $old_id) {
-            $DB->delete_records('grade_letters', array('id' => $old_id));
+        // delete the unused records
+        foreach($pool as $leftover) {
+            $DB->delete_records('grade_letters', array('id' => $leftover->id));
         }
 
         redirect($returnurl);
