diff --git a/templates/relationship_to_many_setops.tpl b/templates/relationship_to_many_setops.tpl
index bda27fa..2ee47a9 100644
--- a/templates/relationship_to_many_setops.tpl
+++ b/templates/relationship_to_many_setops.tpl
@@ -109,25 +109,7 @@ func ({{$rel.Function.Receiver}} *{{$rel.LocalTable.NameGo}}) Set{{$rel.Function
   }
 
   {{if .ToJoinTable -}}
-  for _, rel := range related {
-    if rel.R == nil {
-      continue
-    }
-    for i, ri := range rel.R.{{$rel.Function.ForeignName}} {
-      if {{$rel.Function.Receiver}}.{{$rel.Function.LocalAssignment}} != ri.{{$rel.Function.LocalAssignment}} {
-        continue
-      }
-
-      ln := len(rel.R.{{$rel.Function.ForeignName}})
-      if ln > 1 && i < ln-1 {
-        rel.R.{{$rel.Function.ForeignName}}[i], rel.R.{{$rel.Function.ForeignName}}[ln-1] =
-          rel.R.{{$rel.Function.ForeignName}}[ln-1], rel.R.{{$rel.Function.ForeignName}}[i]
-      }
-      rel.R.{{$rel.Function.ForeignName}} = rel.R.{{$rel.Function.ForeignName}}[:ln-1]
-      break
-    }
-  }
-
+  remove{{$rel.LocalTable.NameGo}}From{{$rel.ForeignTable.NameGo}}Slice({{$rel.Function.Receiver}}, related)
   {{$rel.Function.Receiver}}.R.{{$rel.Function.Name}} = nil
   {{else -}}
   if {{$rel.Function.Receiver}}.R != nil {
@@ -148,12 +130,87 @@ func ({{$rel.Function.Receiver}} *{{$rel.LocalTable.NameGo}}) Set{{$rel.Function
 }
 
 // Remove{{$rel.Function.Name}} relationships from objects passed in.
-// Removes related items from R.{{$rel.Function.Name}}.
-// Sets related.R.{{$rel.Function.ForeignName}}
+// Removes related items from R.{{$rel.Function.Name}} (uses pointer comparison, removal does not keep order)
+// Sets related.R.{{$rel.Function.ForeignName}}.
 func ({{$rel.Function.Receiver}} *{{$rel.LocalTable.NameGo}}) Remove{{$rel.Function.Name}}(exec boil.Executor, related ...*{{$rel.ForeignTable.NameGo}}) error {
+  var err error
+  {{if .ToJoinTable -}}
+  query := fmt.Sprintf(
+    `delete from "{{.JoinTable}}" where "{{.JoinLocalColumn}}" = $1 and "{{.JoinForeignColumn}}" in (%s)`,
+    strmangle.Placeholders(len(related), 1, 1),
+  )
+  values := []interface{}{{"{"}}{{$rel.Function.Receiver}}.{{$rel.LocalTable.ColumnNameGo}}}
+
+  if boil.DebugMode {
+    fmt.Fprintln(boil.DebugWriter, query)
+    fmt.Fprintln(boil.DebugWriter, values)
+  }
+
+  _, err = exec.Exec(query, values...)
+  if err != nil {
+    return errors.Wrap(err, "failed to remove relationships before set")
+  }
+  {{else -}}
+  for _, rel := range related {
+    rel.{{$rel.ForeignTable.ColumnNameGo}}.Valid = false
+    {{if not .ToJoinTable -}}
+    if rel.R != nil {
+      rel.R.{{$rel.Function.ForeignName}} = nil
+    }
+    {{end -}}
+    if err = rel.Update(exec, "{{.ForeignColumn}}"); err != nil {
+      return err
+    }
+  }
+  {{end -}}
+
+  {{if .ToJoinTable -}}
+  remove{{$rel.LocalTable.NameGo}}From{{$rel.ForeignTable.NameGo}}Slice({{$rel.Function.Receiver}}, related)
+  {{end -}}
+  if {{$rel.Function.Receiver}}.R == nil {
+    return nil
+  }
+
+  for _, rel := range related {
+    for i, ri := range {{$rel.Function.Receiver}}.R.{{$rel.Function.Name}} {
+      if rel != ri {
+        continue
+      }
+
+      ln := len({{$rel.Function.Receiver}}.R.{{$rel.Function.Name}})
+      if ln > 1 && i < ln-1 {
+        {{$rel.Function.Receiver}}.R.{{$rel.Function.Name}}[i] = {{$rel.Function.Receiver}}.R.{{$rel.Function.Name}}[ln-1]
+      }
+      {{$rel.Function.Receiver}}.R.{{$rel.Function.Name}} = {{$rel.Function.Receiver}}.R.{{$rel.Function.Name}}[:ln-1]
+      break
+    }
+  }
+
   return nil
 }
-{{end -}}
+
+{{if .ToJoinTable -}}
+func remove{{$rel.LocalTable.NameGo}}From{{$rel.ForeignTable.NameGo}}Slice({{$rel.Function.Receiver}} *{{$rel.LocalTable.NameGo}}, related []*{{$rel.ForeignTable.NameGo}}) {
+  for _, rel := range related {
+    if rel.R == nil {
+      continue
+    }
+    for i, ri := range rel.R.{{$rel.Function.ForeignName}} {
+      if {{$rel.Function.Receiver}}.{{$rel.Function.LocalAssignment}} != ri.{{$rel.Function.LocalAssignment}} {
+        continue
+      }
+
+      ln := len(rel.R.{{$rel.Function.ForeignName}})
+      if ln > 1 && i < ln-1 {
+        rel.R.{{$rel.Function.ForeignName}}[i] = rel.R.{{$rel.Function.ForeignName}}[ln-1]
+      }
+      rel.R.{{$rel.Function.ForeignName}} = rel.R.{{$rel.Function.ForeignName}}[:ln-1]
+      break
+    }
+  }
+}
+{{end -}}{{- /* if join table */ -}}
+{{- end -}}{{- /* if nullable foreign key */ -}}
 {{- end -}}{{- /* if unique foreign key */ -}}
 {{- end -}}{{- /* range relationships */ -}}
 {{- end -}}{{- /* outer if join table */ -}}
diff --git a/templates_test/relationship_to_many_setops.tpl b/templates_test/relationship_to_many_setops.tpl
index dc039ff..b6fd0f7 100644
--- a/templates_test/relationship_to_many_setops.tpl
+++ b/templates_test/relationship_to_many_setops.tpl
@@ -126,7 +126,7 @@ func test{{$rel.LocalTable.NameGo}}ToManySetOp{{$rel.Function.Name}}(t *testing.
     t.Fatal(err)
   }
 
-  err = a.Add{{$rel.Function.Name}}(tx, false, &b, &c)
+  err = a.Set{{$rel.Function.Name}}(tx, false, &b, &c)
   if err != nil {
     t.Fatal(err)
   }
@@ -136,7 +136,7 @@ func test{{$rel.LocalTable.NameGo}}ToManySetOp{{$rel.Function.Name}}(t *testing.
     t.Fatal(err)
   }
   if count != 2 {
-    t.Error("count was wrong:", 2)
+    t.Error("count was wrong:", count)
   }
 
   err = a.Set{{$rel.Function.Name}}(tx, true, &d, &e)
@@ -149,7 +149,7 @@ func test{{$rel.LocalTable.NameGo}}ToManySetOp{{$rel.Function.Name}}(t *testing.
     t.Fatal(err)
   }
   if count != 2 {
-    t.Error("count was wrong:", 2)
+    t.Error("count was wrong:", count)
   }
 
   {{- if .ToJoinTable}}
@@ -182,16 +182,16 @@ func test{{$rel.LocalTable.NameGo}}ToManySetOp{{$rel.Function.Name}}(t *testing.
   }
 
   if b.R.{{$rel.Function.ForeignName}} != nil {
-    t.Error("relationship was not removed properly from the foreign slice")
+    t.Error("relationship was not removed properly from the foreign struct")
   }
   if c.R.{{$rel.Function.ForeignName}} != nil {
-    t.Error("relationship was not removed properly from the foreign slice")
+    t.Error("relationship was not removed properly from the foreign struct")
   }
   if d.R.{{$rel.Function.ForeignName}} != &a {
-    t.Error("relationship was not added properly to the foreign slice")
+    t.Error("relationship was not added properly to the foreign struct")
   }
   if e.R.{{$rel.Function.ForeignName}} != &a {
-    t.Error("relationship was not added properly to the foreign slice")
+    t.Error("relationship was not added properly to the foreign struct")
   }
   {{- end}}
 
@@ -204,6 +204,103 @@ func test{{$rel.LocalTable.NameGo}}ToManySetOp{{$rel.Function.Name}}(t *testing.
 }
 
 func test{{$rel.LocalTable.NameGo}}ToManyRemoveOp{{$rel.Function.Name}}(t *testing.T) {
+  var err error
+
+  tx := MustTx(boil.Begin())
+  defer tx.Rollback()
+
+  var a {{$rel.LocalTable.NameGo}}
+  var b, c, d, e {{$rel.ForeignTable.NameGo}}
+
+  seed := randomize.NewSeed()
+  if err = randomize.Struct(seed, &a, {{$varNameSingular}}DBTypes, false, {{$varNameSingular}}PrimaryKeyColumns...); err != nil {
+    t.Fatal(err)
+  }
+  foreigners := []*{{$rel.ForeignTable.NameGo}}{&b, &c, &d, &e}
+  for _, x := range foreigners {
+    if err = randomize.Struct(seed, x, {{$foreignVarNameSingular}}DBTypes, false, {{$foreignVarNameSingular}}PrimaryKeyColumns...); err != nil {
+      t.Fatal(err)
+    }
+  }
+
+  if err := a.Insert(tx); err != nil {
+    t.Fatal(err)
+  }
+
+  err = a.Add{{$rel.Function.Name}}(tx, true, foreigners...)
+  if err != nil {
+    t.Fatal(err)
+  }
+
+  count, err := a.{{$rel.Function.Name}}(tx).Count()
+  if err != nil {
+    t.Fatal(err)
+  }
+  if count != 4 {
+    t.Error("count was wrong:", count)
+  }
+
+  err = a.Remove{{$rel.Function.Name}}(tx, foreigners[:2]...)
+  if err != nil {
+    t.Fatal(err)
+  }
+
+  count, err = a.{{$rel.Function.Name}}(tx).Count()
+  if err != nil {
+    t.Fatal(err)
+  }
+  if count != 2 {
+    t.Error("count was wrong:", count)
+  }
+
+  {{- if .ToJoinTable}}
+
+  if len(b.R.{{$rel.Function.ForeignName}}) != 0 {
+    t.Error("relationship was not removed properly from the slice")
+  }
+  if len(c.R.{{$rel.Function.ForeignName}}) != 0 {
+    t.Error("relationship was not removed properly from the slice")
+  }
+  if d.R.{{$rel.Function.ForeignName}}[0] != &a {
+    t.Error("relationship was not added properly to the foreign struct")
+  }
+  if e.R.{{$rel.Function.ForeignName}}[0] != &a {
+    t.Error("relationship was not added properly to the foreign struct")
+  }
+  {{- else}}
+
+  if b.{{$rel.ForeignTable.ColumnNameGo}}.Valid {
+    t.Error("want b's foreign key value to be nil")
+  }
+  if c.{{$rel.ForeignTable.ColumnNameGo}}.Valid {
+    t.Error("want c's foreign key value to be nil")
+  }
+
+  if b.R.{{$rel.Function.ForeignName}} != nil {
+    t.Error("relationship was not removed properly from the foreign struct")
+  }
+  if c.R.{{$rel.Function.ForeignName}} != nil {
+    t.Error("relationship was not removed properly from the foreign struct")
+  }
+  if d.R.{{$rel.Function.ForeignName}} != &a {
+    t.Error("relationship to a should have been preserved")
+  }
+  if e.R.{{$rel.Function.ForeignName}} != &a {
+    t.Error("relationship to a should have been preserved")
+  }
+  {{- end}}
+
+  if len(a.R.{{$rel.Function.Name}}) != 2 {
+    t.Error("should have preserved two relationships")
+  }
+
+  // Removal doesn't do a stable deletion for performance so we have to flip the order
+  if a.R.{{$rel.Function.Name}}[1] != &d {
+    t.Error("relationship to d should have been preserved")
+  }
+  if a.R.{{$rel.Function.Name}}[0] != &e {
+    t.Error("relationship to e should have been preserved")
+  }
 }
 {{end -}}
 {{- end -}}{{- /* if unique foreign key */ -}}