diff --git a/boil/helpers.go b/boil/helpers.go
index 2fdca1c..dd19b98 100644
--- a/boil/helpers.go
+++ b/boil/helpers.go
@@ -9,6 +9,49 @@ import (
 	"unicode"
 )
 
+// WherePrimaryKeyIn generates a "in" string for where queries
+// For example: (col1, col2) IN (($1, $2), ($3, $4))
+func WherePrimaryKeyIn(numRows int, keyNames ...string) string {
+	in := &bytes.Buffer{}
+
+	if len(keyNames) == 0 {
+		return ""
+	}
+
+	in.WriteByte('(')
+	for i := 0; i < len(keyNames); i++ {
+		in.WriteString(`"` + keyNames[i] + `"`)
+		if i < len(keyNames)-1 {
+			in.WriteByte(',')
+		}
+	}
+
+	in.WriteString(") IN (")
+
+	c := 1
+	for i := 0; i < numRows; i++ {
+		for y := 0; y < len(keyNames); y++ {
+			if len(keyNames) > 1 && y == 0 {
+				in.WriteByte('(')
+			}
+
+			in.WriteString(fmt.Sprintf("$%d", c))
+			c++
+
+			if len(keyNames) > 1 && y == len(keyNames)-1 {
+				in.WriteByte(')')
+			}
+
+			if i != numRows-1 || y != len(keyNames)-1 {
+				in.WriteByte(',')
+			}
+		}
+	}
+	in.WriteByte(')')
+
+	return in.String()
+}
+
 // SelectNames returns the column names for a select statement
 // Eg: col1, col2, col3
 func SelectNames(results interface{}) string {
diff --git a/boil/helpers_test.go b/boil/helpers_test.go
index 2f68966..988f56b 100644
--- a/boil/helpers_test.go
+++ b/boil/helpers_test.go
@@ -11,6 +11,58 @@ type testObj struct {
 	HeadSize int
 }
 
+func TestWherePrimaryKeyIn(t *testing.T) {
+	t.Parallel()
+
+	x := WherePrimaryKeyIn(1, "aa")
+	expect := `("aa") IN ($1)`
+	if x != expect {
+		t.Errorf("Expected %s, got %s\n", expect, x)
+	}
+
+	x = WherePrimaryKeyIn(2, "aa")
+	expect = `("aa") IN ($1,$2)`
+	if x != expect {
+		t.Errorf("Expected %s, got %s\n", expect, x)
+	}
+
+	x = WherePrimaryKeyIn(3, "aa")
+	expect = `("aa") IN ($1,$2,$3)`
+	if x != expect {
+		t.Errorf("Expected %s, got %s\n", expect, x)
+	}
+
+	x = WherePrimaryKeyIn(1, "aa", "bb")
+	expect = `("aa","bb") IN (($1,$2))`
+	if x != expect {
+		t.Errorf("Expected %s, got %s\n", expect, x)
+	}
+
+	x = WherePrimaryKeyIn(2, "aa", "bb")
+	expect = `("aa","bb") IN (($1,$2),($3,$4))`
+	if x != expect {
+		t.Errorf("Expected %s, got %s\n", expect, x)
+	}
+
+	x = WherePrimaryKeyIn(3, "aa", "bb")
+	expect = `("aa","bb") IN (($1,$2),($3,$4),($5,$6))`
+	if x != expect {
+		t.Errorf("Expected %s, got %s\n", expect, x)
+	}
+
+	x = WherePrimaryKeyIn(4, "aa", "bb")
+	expect = `("aa","bb") IN (($1,$2),($3,$4),($5,$6),($7,$8))`
+	if x != expect {
+		t.Errorf("Expected %s, got %s\n", expect, x)
+	}
+
+	x = WherePrimaryKeyIn(4, "aa", "bb", "cc")
+	expect = `("aa","bb","cc") IN (($1,$2,$3),($4,$5,$6),($7,$8,$9),($10,$11,$12))`
+	if x != expect {
+		t.Errorf("Expected %s, got %s\n", expect, x)
+	}
+}
+
 func TestGoVarToSQLName(t *testing.T) {
 	t.Parallel()
 
diff --git a/boil/query_test.go b/boil/query_test.go
index 9950fc0..7ec84e2 100644
--- a/boil/query_test.go
+++ b/boil/query_test.go
@@ -56,18 +56,6 @@ func TestBuildQuery(t *testing.T) {
 	}
 }
 
-func TestExecQuery(t *testing.T) {
-	t.Parallel()
-}
-
-func TestExecQueryOne(t *testing.T) {
-	t.Parallel()
-}
-
-func TestExecQueryAll(t *testing.T) {
-	t.Parallel()
-}
-
 func TestSetLimit(t *testing.T) {
 	t.Parallel()
 
diff --git a/cmds/config.go b/cmds/config.go
index 4156832..6641084 100644
--- a/cmds/config.go
+++ b/cmds/config.go
@@ -39,6 +39,7 @@ var sqlBoilerImports = imports{
 	},
 	thirdparty: importList{
 		`"github.com/pobri19/sqlboiler/boil"`,
+		`"github.com/pobri19/sqlboiler/boil/qs"`,
 	},
 }
 
@@ -47,6 +48,7 @@ var sqlBoilerSinglesImports = map[string]imports{
 		standard: importList{},
 		thirdparty: importList{
 			`"github.com/pobri19/sqlboiler/boil"`,
+			`"github.com/pobri19/sqlboiler/boil/qs"`,
 		},
 	},
 }
@@ -102,6 +104,7 @@ var sqlBoilerTemplateFuncs = template.FuncMap{
 	"primaryKeyFlagIndex":  primaryKeyFlagIndex,
 	"updateParamNames":     updateParamNames,
 	"updateParamVariables": updateParamVariables,
+	"primaryKeyStrList":    primaryKeyStrList,
 }
 
 // LoadConfigFile loads the toml config file into the cfg object
diff --git a/cmds/sqlboiler_test.go b/cmds/sqlboiler_test.go
index 0bd56b4..b628c6a 100644
--- a/cmds/sqlboiler_test.go
+++ b/cmds/sqlboiler_test.go
@@ -176,12 +176,12 @@ func outputCompileErrors(buf *bytes.Buffer, outFolder string) {
 		}
 
 		scanner := bufio.NewScanner(fh)
-		throwaway := eObj.lineNumber - 2
+		throwaway := eObj.lineNumber - 5
 		for throwaway > 0 && scanner.Scan() {
 			throwaway--
 		}
 
-		for i := 0; i < 3; i++ {
+		for i := 0; i < 6; i++ {
 			if scanner.Scan() {
 				b := scanner.Bytes()
 				if len(b) != 0 {
diff --git a/cmds/template_funcs.go b/cmds/template_funcs.go
index 9385d30..332b1c4 100644
--- a/cmds/template_funcs.go
+++ b/cmds/template_funcs.go
@@ -234,6 +234,16 @@ func wherePrimaryKey(pkeyCols []string, start int) string {
 	return output
 }
 
+// primaryKeyStrList returns a list of primary key column names in strings
+// For example: "col1", "col2", "col3"
+func primaryKeyStrList(pkeyCols []string) string {
+	for i, c := range pkeyCols {
+		pkeyCols[i] = fmt.Sprintf(`"%s"`, c)
+	}
+
+	return strings.Join(pkeyCols, ", ")
+}
+
 // commaList returns a comma seperated list: "col1, col2, col3"
 func commaList(cols []string) string {
 	return strings.Join(cols, ", ")
diff --git a/cmds/templates/all.tpl b/cmds/templates/all.tpl
index d0ee4e8..22f69e3 100644
--- a/cmds/templates/all.tpl
+++ b/cmds/templates/all.tpl
@@ -1,17 +1,16 @@
 {{- $tableNameSingular := titleCaseSingular .Table.Name -}}
 {{- $tableNamePlural := titleCasePlural .Table.Name -}}
 {{- $varNameSingular := camelCaseSingular .Table.Name -}}
-{{- $varNamePlural := camelCasePlural .Table.Name -}}
 type {{$varNameSingular}}Query struct {
   *boil.Query
 }
 
 // {{$tableNamePlural}}All retrieves all records.
-func {{$tableNamePlural}}(mods ...QueryMod) {{$varNameSingular}}Query {
+func {{$tableNamePlural}}(mods ...qs.QueryMod) {{$varNameSingular}}Query {
   return {{$tableNamePlural}}X(boil.GetDB(), mods...)
 }
 
-func {{$tableNamePlural}}X(exec boil.Executor, mods ...QueryMod) {{$tableNameSingular}}Query {
-  mods = append(mods, boil.From("{{.Table.Name}}"))
-  return NewQueryX(exec, mods...)
+func {{$tableNamePlural}}X(exec boil.Executor, mods ...qs.QueryMod) {{$varNameSingular}}Query {
+  mods = append(mods, qs.From("{{.Table.Name}}"))
+  return {{$varNameSingular}}Query{NewQueryX(exec, mods...)}
 }
diff --git a/cmds/templates/delete.tpl b/cmds/templates/delete.tpl
index cd737ab..bf9d73e 100644
--- a/cmds/templates/delete.tpl
+++ b/cmds/templates/delete.tpl
@@ -3,19 +3,22 @@
 {{- $varNameSingular := camelCaseSingular .Table.Name -}}
 // Delete deletes a single {{$tableNameSingular}} record.
 // Delete will match against the primary key column to find the record to delete.
-func (o *{{$tableNameSingular}}) Delete(mods ...QueryMod) error {
-  return o.DeleteX(boil.GetDB(), mods...)
+func (o *{{$tableNameSingular}}) Delete() error {
+  return o.DeleteX(boil.GetDB())
 }
 
-func (o *{{$tableNameSingular}}) DeleteX(exec boil.Executor, mods ...QueryMod) error {
+func (o *{{$tableNameSingular}}) DeleteX(exec boil.Executor) error {
+  var mods []qs.QueryMod
+
   mods = append(mods,
-    boil.From("{{.table.Name}}"),
-    boil.Where("{{wherePrimaryKey .Table.Pkey.Columns 1}}", {{paramsPrimaryKey "o." .Table.PKey.Columns true}}),
+    qs.From("{{.Table.Name}}"),
+    qs.Where("{{wherePrimaryKey .Table.PKey.Columns 1}}", {{paramsPrimaryKey "o." .Table.PKey.Columns true}}),
   )
 
   query := NewQueryX(exec, mods...)
+  boil.SetDelete(query)
 
-  _, err := exec.Exec("DELETE FROM {{.Table.Name}} WHERE {{wherePrimaryKey .Table.PKey.Columns 1}}", {{paramsPrimaryKey "o." .Table.PKey.Columns true}})
+  _, err := boil.ExecQuery(query)
   if err != nil {
     return fmt.Errorf("{{.PkgName}}: unable to delete from {{.Table.Name}}: %s", err)
   }
@@ -24,9 +27,37 @@ func (o *{{$tableNameSingular}}) DeleteX(exec boil.Executor, mods ...QueryMod) e
 }
 
 func (o {{$varNameSingular}}Query) DeleteAll() error {
-  _, err := db.Exec("DELETE FROM {{.Table.Name}} WHERE {{wherePrimaryKey .Table.PKey.Columns 1}}", {{paramsPrimaryKey "o." .Table.PKey.Columns true}})
+  boil.SetDelete(o)
+
+  _, err := boil.ExecQuery(query)
   if err != nil {
-    return fmt.Errorf("{{.PkgName}}: unable to delete from {{.Table.Name}}: %s", err)
+    return fmt.Errorf("{{.PkgName}}: unable to delete all from {{.Table.Name}}: %s", err)
+  }
+
+  return nil
+}
+
+func (o {{$varNameSingular}}Slice) DeleteAll() error {
+  return DeleteAllX(boil.GetDB())
+}
+
+func (o {{$varNameSingular}}Slice) DeleteAllX(exec boil.Executor) error {
+  var mods []qs.QueryMod
+
+  args := o.inPrimaryKeyArgs()
+  in := boil.WherePrimaryKeyIn(len(o), {{primaryKeyStrList .Table.PKey.Columns}})
+
+  mods = append(mods,
+    qs.From("{{.Table.Name}}"),
+    qs.Where(in, args...),
+  )
+
+  query := NewQueryX(exec, mods...)
+  boil.SetDelete(query)
+
+  _, err := boil.ExecQuery(query)
+  if err != nil {
+    return fmt.Errorf("{{.PkgName}}: unable to delete all from {{$varNameSingular}} slice: %s", err)
   }
 
   return nil
diff --git a/cmds/templates/find.tpl b/cmds/templates/find.tpl
index 52ae0cf..955c14b 100644
--- a/cmds/templates/find.tpl
+++ b/cmds/templates/find.tpl
@@ -21,7 +21,7 @@ func {{$tableNameSingular}}FindX(exec boil.Executor, id int64, selectList ...str
     return nil, errors.New("{{.PkgName}}: no id provided for {{.Table.Name}} select")
   }
   var {{$varNameSingular}} *{{$tableNameSingular}}
-  err := boil.GetDB().Select(&{{$varNameSingular}}, `SELECT {{selectParamNames $dbName .Table.Columns}} WHERE id=$1`, id)
+  //err := boil.GetDB().Select(&{{$varNameSingular}}, `SELECT {{selectParamNames $dbName .Table.Columns}} WHERE id=$1`, id)
 
   if err != nil {
     return nil, fmt.Errorf("{{.PkgName}}: unable to select from {{.Table.Name}}: %s", err)
diff --git a/cmds/templates/helpers.tpl b/cmds/templates/helpers.tpl
new file mode 100644
index 0000000..0ccb920
--- /dev/null
+++ b/cmds/templates/helpers.tpl
@@ -0,0 +1,15 @@
+{{if hasPrimaryKey .Table.PKey -}}
+{{- $tableNameSingular := titleCaseSingular .Table.Name -}}
+{{- $varNameSingular := camelCaseSingular .Table.Name -}}
+func (o {{$varNameSingular}}Slice) inPrimaryKeyArgs() []interface{} {
+  var args []interface{}
+
+  for i := 0; i < len(o); i++ {
+    {{- range $key, $value := .Table.PKey.Columns }}
+    args = append(args, o.{{titleCase $value}})
+    {{ end -}}
+  }
+
+  return args
+}
+{{- end}}
diff --git a/cmds/templates/singles/helpers.tpl b/cmds/templates/singles/helpers.tpl
index d8c1b8c..304b1ce 100644
--- a/cmds/templates/singles/helpers.tpl
+++ b/cmds/templates/singles/helpers.tpl
@@ -7,8 +7,9 @@ func NewQuery(mods ...qs.QueryMod) *boil.Query {
 }
 
 // NewQueryX initializes a new Query using the passed in QueryMods
-func NewQueryX(executor boil.Executor, mods ...qs.QueryMod) *boil.Query {
-	q := &boil.Query{executor: executor}
+func NewQueryX(exec boil.Executor, mods ...qs.QueryMod) *boil.Query {
+	q := &boil.Query{}
+	boil.SetExecutor(q, exec)
 	qs.Apply(q, mods...)
 
 	return q