# Introduction

## Introduction

qb is a fluent query builder for CFML. It is **heavily** inspired by [Eloquent](https://laravel.com/docs/5.3/eloquent) from [Laravel](https://laravel.com/).

Using qb, you can:

* Quickly scaffold simple queries
* Make complex, out-of-order queries possible
* Abstract away differences between database engines

## Requirements

* BoxLang 1+
* Adobe ColdFusion 2021+
* Lucee 5+

qb supports the following database grammars:

* MySQL (`MySQLGrammar@qb`)
* Oracle (`OracleGrammar@qb`)
* Postgres (`PostgresGrammar@qb`)
* Microsoft SQL Server (`SqlServerGrammar@qb`)
* SQLite (`SQLiteGrammar@qb`)
* Derby (`DerbyGrammar@qb`)

### Discussion & Help

The Box modules discussion group and community can be found here:

<https://community.ortussolutions.com/c/box-modules/qb/27>

## Installation

Installation is easy through [CommandBox](https://www.ortussolutions.com/products/commandbox) and [ForgeBox](https://www.coldbox.org/forgebox). Simply type `box install qb` to get started.

## Code Samples

Compare these two examples:

```cfscript
// Plain old CFML
var results = queryExecute( "SELECT * FROM users" );

// qb
var qb = wirebox.getInstance( "QueryBuilder@qb" );
var results = qb.from( "users" ).get();
```

The differences become even more stark when we introduce more complexity:

```cfscript
// Plain old CFML
var results = queryExecute(
    "SELECT * FROM posts WHERE published_at IS NOT NULL AND author_id IN ?",
    [ { value = "5,10,27", cfsqltype = "CF_SQL_NUMERIC", list = true } ]
);

// qb
var qb = wirebox.getInstance( "QueryBuilder@qb" );
var results = qb.from( "posts" )
    .whereNotNull( "published_at" )
    .whereIn( "author_id", [ 5, 10, 27 ] )
    .get();
```

With qb you can easily handle setting order by statements before the columns you want or join statements after a where clause:

```cfscript
var qb = wirebox.getInstance( "QueryBuilder@qb" );
var results = qb.from( "posts" )
         .orderBy( "published_at" )
         .select( "post_id", "author_id", "title", "body" )
         .whereLike( "author", "Ja%" )
         .join( "authors", "authors.id", "=", "posts.author_id" )
         .get();

// Becomes
var results = queryExecute(
    "SELECT post_id, author_id, title, body FROM posts INNER JOIN authors ON authors.id = posts.author_id WHERE author LIKE ? ORDER BY published_at",
    [ { value = "Ja%", cfsqltype = "CF_SQL_VARCHAR", list = false, null = false } ]
);
```

qb enables you to explore new ways of organizing your code by letting you pass around a query builder object that will compile down to the right SQL without you having to keep track of the order, whitespace, or other SQL gotchas!

Here's a gist with an example of the powerful models you can create with this! <https://gist.github.com/elpete/80d641b98025f16059f6476561d88202>

## Usage

To start a new query, instantiate a new Builder: `wirebox.getInstance( "QueryBuilder@qb" )`.

By default, qb uses a generic Grammar. You can specify your specific grammar in ColdBox by setting the `defaultGrammar` in your `moduleSettings`.

```cfscript
moduleSettings = {
    qb = {
        defaultGrammar = "MySQLGrammar@qb"
    }
};
```

If you are not using WireBox, just make sure to wire up the `Builder` object with the correct grammar:

```cfscript
var grammar = new qb.models.Query.Grammars.MySQLGrammar();
var builder = new qb.models.Query.Builder( grammar );
```


# What's New?

## 12.1.1

**QueryUtils**: Add `name` as a valid query param key.

## 12.1.0

qb now checks the shape of query param structs passed as bindings and will throw a `QBInvalidQueryParam` if there are any invalid keys.

This is to help developers who may have passed a struct as a param that they meant to first serialize to JSON.

## 12.0.0

### Breaking Changes

#### Add new [`convertEmptyStringsToNull`](/12.1.0/installation-and-usage#configuration-settings) setting and default to true.

qb now automatically converts an empty string value to `null` when inserting into a query.  If your application relies on inserting or updating values to an empty string, set this setting to `false`.

#### Remove `autoAddScale` setting.

qb now always automatically adds a `scale` to `decimal` and `float` query params. This has been the default since [v8.5.0](#id-8.5.0). This can still be overridden by providing a full struct query param when adding bindings.

#### Remove `strictDateDetection` setting

qb will now only use type introspection over the `isDate` function for all date detection. This has been the default since [v9.0.0](#id-9.0.0).

#### Remove `autoDeriveNumericType` setting

qb will only use `INTEGER` or `DECIMLAL` sql types instead of the more ambiguous `NUMERIC`. This has been the default since [v9.0.0](#id-9.0.0).

#### Allow for default values for [`max`](/12.1.0/query-builder/executing-queries/aggregates#max), [`min`](/12.1.0/query-builder/executing-queries/aggregates#min), [`count`](/12.1.0/query-builder/executing-queries/aggregates#count), and [`sum`](/12.1.0/query-builder/executing-queries/aggregates#sum) functions

The argument order change to account for the new `defaultValue` argument. If you are using positional parameters with these functions, please migrate to the new function signatures.

#### Removal of `CF_SQL` prefix

The `CF_SQL` prefix for `cfsqltype` has been optional since [ColdFusion 11](https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-tags/tags-p-q/cfqueryparam.html), so while this change should not impact any running application, we are labelling it as a breaking change out of an abundance of caution.

#### Initializer Argument change for `QueryUtils`

To support removal of the settings above and to add a new setting to convert empty strings to null, the `QueryUtils` class' initializer has been modified.  If you are creating this class manually, please check the API docs and upgrade to the new initializer arguments.

### New Features

* New `DerbyGrammar` support.
* Allow queries [without a table name or `FROM` clause](/12.1.0/query-builder/building-queries/from#from).
* Add a new [`returningAll()`](/12.1.0/query-builder/executing-queries/inserts-updates-deletes#returningall) shortcut method for `returning( "*" )`.
* Order your queries randomly with the [`orderByRandom`](/12.1.0/query-builder/building-queries/ordering-grouping-and-limit#order-by-random) method.
* New [`createAs`](/12.1.0/schema-builder/create#createas) method available on `SchemaBuilder`.
* `TRUNCATE` tables with [`SchemaBuilder.truncate( ... )`](/12.1.0/schema-builder/drop#truncate).
* **SQL Server**: Add support for [`FOR ...` clauses](/12.1.0/query-builder/building-queries/for).
* **SQL Server**: Allow restricting the [`DELETE UNMATCHED` clause in `upsert`](/12.1.0/query-builder/executing-queries/inserts-updates-deletes#upsert).
* **Postgres**: Add [`jsonb(`](/12.1.0/schema-builder/columns#jsonb)`)` support in `SchemaBuilder`.
* **MySQL**: Use `JSON` type for [`json()`](/12.1.0/schema-builder/columns#json) columns.

### Bug Fixes

* Compatibility fixes for BoxLang and Adobe ColdFusion.
* Compatibility for pure BoxLang (without the `bx-compat-cfml` module).
* Fix the `count` method for pagination when being used with a query with `DISTINCT` turned on.
* Fix for `UPDATE` queries with `RETURNING` clauses being invalid.
* Improve performance for [`exists`](/12.1.0/query-builder/executing-queries/aggregates#exists) queries.
* **Postgres**: Use the native `UUID` type for [`guid()`](/12.1.0/schema-builder/columns#guid) columns.
* **Oracle**: Support Unicode versions of table column types (e.g. [`unicodeText()`](/12.1.0/schema-builder/columns#unicodetext))

## 11.1.0

**QueryBuilder:** Support JOINS in DELETE statements for supported grammars, like MySQL and SQL Server.

## 11.0.3

**QueryBuilder:** Don't overly specify that grammars must extend `BaseGrammar`. It's just an implicit interface, after all.

## 11.0.2

**QueryBuilder:** Have aliases work with full server qualifications, like `ServerName.schemaName.tableName`.

## 11.0.1

### Allow for disabling of wrapping values

Either a Grammar setting (`setShouldWrapValues( true|false )`) or for a one-off Query Builder ([`withoutWrappingValues()`](/12.1.0/query-builder/options-and-utilities/query-options#withoutwrappingvalues) / [`withWrappingValues()`](/12.1.0/query-builder/options-and-utilities/query-options#withwrappingvalues)) can control whether identifiers like table names, columns, etc. are wrapped.

### BoxLang Compatibility

This release includes updates to be compatible with the latest releases of BoxLang.

## 11.0.0

### Auto Boolean Casting

Grammars will be able to influence the `cfsqltype` and value when passing in a literal boolean value as a binding. Postgres and SQLite have boolean support, so they will keep the literal boolean value and use a `cfsqltype` of `CF_SQL_OTHER`. SQL Server uses `CF_SQL_BIT`, Oracle users `CF_SQL_NUMERIC`, and MySQL uses `CF_SQL_TINYINT` — all of these will convert literal boolean values to either 1 or 0. This behavior is skipped when providing a custom `cfsqltype`.

{% hint style="info" %}
Custom grammars can implement the `getBooleanSqlType` and `convertBooleanValue` methods to customize this behavior.
{% endhint %}

{% hint style="danger" %}
Additionally, attempting to change the grammar with any bindings currently configured will throw an exception. This is because the bindings are converted via the grammar when added to the builder and cannot be changed retroactively when setting a new grammar. Set the grammar first before configuring the query to avoid this exception.
{% endhint %}

## 10.0.2

**QueryUtils:** Fix timestamp formatting losing timezone information

## 10.0.1

**QueryUtils:** Manually construct ISO 8601 timestamps due to lack of Adobe support

## 10.0.0

* Full compatibility for running on [BoxLang](https://boxlang.io/) with the [`bx-compat-cfml`](https://forgebox.io/view/bx-compat-cfml) module.
* Internal property name changes for BoxLang compatibility as well as cleaner code. (This *may* cause breaking changes, in rare cases.  See the [Migration Guide](https://qb.ortusbooks.com/12.1.0/pages/-LA-U_b2vfkZD-h5AIUm#v10.0.0) for more details.)

## 9.8.1

* Fix missing `parseNumber` function for ACF
* Add alias to `clone()`

## 9.8.0

Support alias renaming using [`withAlias`](/12.1.0/query-builder/building-queries/from#withalias)&#x20;

## 9.7.1

Add in missing join compilations.

## 9.7.0

Implement [crossApply](/12.1.0/query-builder/building-queries/joins#crossapply) and [outerApply](/12.1.0/query-builder/building-queries/joins#outerapply) for supported Grammars

## 9.6.1

Expand type annotation for `from`. This can be a string or an Expression.

## 9.6.0

Make [`addBindings`](/12.1.0/query-builder/building-queries/parameters-and-bindings#addbindings) and [`addBindingsFromBuilder`](/12.1.0/query-builder/building-queries/parameters-and-bindings#addbindingsfrombuilder) publicly accessible.

## 9.5.1

Add MariaDB support to `AutoDiscover@qb` grammar. (It will choose the `MySQLGrammar@qb`.)

## 9.5.0

Add [`findOrFail`](/12.1.0/query-builder/executing-queries/retrieving-results#findorfail) and [`existsOrFail`](/12.1.0/query-builder/executing-queries/aggregates#existsorfail) methods, inspired by [Quick](https://quick.ortusbooks.com).

## 9.4.1

Better Support for OracleGrammar in SchemaBuilder

* Fix trigger creation by escaping colons (`:`).
* Try to drop associated sequences and triggers when dropping a table.
* Better support for creating a table in a different schema by only checking for the last identifier as the table name in [`hasTable`](/12.1.0/schema-builder/schema-builder#hastable) and [`hasColumn`](/12.1.0/schema-builder/schema-builder#hascolumn).

## 9.4.0

Allow for setting a [`defaultSchema`](/12.1.0/schema-builder/schema-builder) property on a `SchemaBuilder` instance.

The `defaultSchema` will be used for methods like [`hasTable`](/12.1.0/schema-builder/schema-builder#hastable) and [`hasColumn`](/12.1.0/schema-builder/schema-builder#hascolumn). A passed in `schema` will still take precedence.

## 9.3.1

* Use `CHAR` for `GUID` and `UUID` types in MySQL.
* Don't call `getUtils` from inside `QueryUtils`.

## 9.3.0

Make [`replaceBindings`](/12.1.0/query-builder/options-and-utilities/query-options#replacing-or-inlining-bindings) publicly available in `QueryUtils`.

This is used by qb to inline query bindings in `toSQL` or `dump` calls and can be used to inline the bindings in other tools like[ CommandBox Migrations](https://forgebox.io/view/commandbox-migrations).

## 9.2.5

Use named parameters when passing to `BaseGrammar`. This avoids problems where custom Grammars have extra arguments and we add arguments to the official grammar.

## 9.2.4

{% hint style="info" %}
We apologize for the new features in a patch release.
{% endhint %}

#### New Features

* Add the ability to pretend to run queries, both in [QueryBuilder](/12.1.0/query-builder/debugging#pretend) and [SchemaBuilder](/12.1.0/schema-builder/debugging#pretend).
* Add query logging to [QueryBuilder](/12.1.0/query-builder/debugging#querylog) and [SchemaBuilder](/12.1.0/schema-builder/debugging#querylog) instances.

#### Bug Fixes

* Use varchar for clob when converting to a CFML query. This is used when removing a column like in Oracle pagination.

## 9.2.3

Handle more numeric SQL types like `AtomicInteger` and `Long`.

## 9.2.2

Add millisecond accuracy to inline bindings.

## 9.2.1

Separate `having` bindings from `where` bindings.

## 9.2.0

### New Features

We now support the `returning` function inside `update` and `delete` statements for supported Grammars.  Supported grammars are SQL Server, Postgres, and SQLite.

### Bug Fixes

* Fix raw table name parsing in update queries for `SqlServerGrammar`.
* Fix truncating text in nested wheres inside joins.
* Fix out of order bindings in joinSub

## 9.1.5

Switch from `table_catalog` to `table_schema` when referencing schema for `PostgresGrammar`.

## 9.1.4

CommandBox-friendly injections for SQL Commenter.

## 9.1.3

Add support for `from` bindings, used especially in `fromSub` queries.

## 9.1.2

This release reverts the use of native `returntype`s.  There are too many bugs between engine implementations to make it viable.  No end-user changes should be visible.

## 9.1.1

Make `withReturnFormat` a public method.

## 9.1.0

### New Features

Add ability to inline bindings when calling `toSQL` and `dump`. These strings can be executed in a DBMS application.

### Bug Fixes

* Move `coldbox` namespace injection to the function body so CommandBox doesn't blow up.
* Correctly apply native returntypes after `newQuery` and `withReturnFormat`.

## 9.0.2

* Fix losing `defaultOptions` when calling `newQuery`.
* Shortcut for no return format using `none`.
* Allow for native struct returntypes. Requires a return format of `none`.

## 9.0.1

Fix `RouteInfoCommenter` file name.

## 9.0.0

### Breaking Changes

#### Dropped support for Adobe ColdFusion 2016

Adobe has ended support for ACF 2016, and so must we.

#### SchemaBuilder's `uuid` split into [guid()](/12.1.0/schema-builder/columns#guid) and [uuid()](/12.1.0/schema-builder/columns#uuid)

CFML's `uuid` does not match other languages; it's one character shorter. Because of this, the value from `createUUID()` cannot be used in some database column types like SQL Server's `uniqueidentifier`. This made for some confusion in SchemaBuilder since it wasn't clear if `uuid` meant CFML's definition or the wider world's definition.

So, the types have been split, following Lucee's pattern, into [`uuid`](/12.1.0/schema-builder/columns#uuid) (matching CFML's [`createUUID()`](https://cfdocs.org/createuuid)) and [`guid`](/12.1.0/schema-builder/columns#guid) (matching Java's UUID or [`createGUID()`](https://cfdocs.org/createguid) on Lucee).

#### Returning all rows from [paginate](/12.1.0/query-builder/executing-queries/retrieving-results#paginate) when maxRows is  0 or lower

Popular grid frameworks like Quasar and Datatables use values of 0 or -1 to return all rows from a query. This is now supported in qb. Previously, it generated an invalid query (`SELECT * FROM users LIMIT 0 OFFSET 0`).

This behavior can be customized by providing a callback to the `shouldMaxRowsOverrideToAll` setting or `init` argument. For instance, to revert to the previous behavior you would set the function as follows:

```cfscript
moduleSettings = {
    "qb": {
        "shouldMaxRowsOverrideToAll": function( maxRows ) {
            return false;
        }
    }
};
```

#### [`autoDeriveNumericType`](/12.1.0/query-builder/building-queries/parameters-and-bindings#numeric-sql-type) is now the default

Introduced in [8.10.0](#8.10.0), this feature uses separate SQL types for integers and decimals to increase performance in certain database grammars.  This feature is now the default, but the previous behavior can be enabled by setting `autoDeriveNumericType` to `false`.

{% hint style="warning" %}
**Note:** the option to revert to the old behavior will be removed in the next major version.
{% endhint %}

#### [`strictDateDetection`](/12.1.0/query-builder/building-queries/parameters-and-bindings#strict-date-detection) is now the default

Introduced in [8.1.0](#8.1.0), this feature only returns a SQL type of `CF_SQL_TIMESTAMP` if the param is a date object, not just a string that looks like a date.  This helps avoid situations where some strings were incorrectly interpreted as dates.  For many, the migration path is straightforward — calls to [`now()`](https://cfdocs.org/now) are already date objects as well as any function that operates on a date.  If you need to parse a string as a date, the [`parseDateTime`](https://cfdocs.org/parsedatetime) built-in function can accomplish that.

{% hint style="warning" %}
**Note:** the option to revert to the old behavior **may** be removed in the next major version.
{% endhint %}

### New Features and Improvements

#### SQLite Grammar Support

Thanks to [Jason Steinhouer](https://github.com/jsteinshouer), qb now supports SQLite for both `QueryBuilder` and `SchemaBuilder`.  You can use it in your apps by specifying `SQLiteGrammar@qb` as the default grammar.

#### [sqlCommenter Support](/12.1.0/query-builder/debugging/sqlcommenter)

sqlCommenter is a [specification by Google](https://google.github.io/sqlcommenter/) for adding contextual information as a comment at the end of a SQL statement.  This can give insights into your application, especially when diagnosing slow queries. Examples of the information you can append to your queries are `route`, `handler`, `action`, `version`, and others, as well as the ability to add your own, such as `loggedInUser` and more.

#### [sumRaw](/12.1.0/query-builder/executing-queries/aggregates#sumraw) helper function

There's a new shortcut method to return `qb.sum( qb.raw( expression ) )`. You're welcome. 😉

#### Dedicated [`dropIndex`](/12.1.0/schema-builder/alter#dropindex) method

Some grammars, like SQL Server, do not treat simple indexes as constraints.  For this reason, we've added a [`dropIndex`](/12.1.0/schema-builder/alter#dropindex) method alongside the existing [`dropConstraint`](/12.1.0/schema-builder/alter#dropconstraint).

#### [`columnList`](/12.1.0/query-builder/executing-queries/aggregates#columnlist) helper method

[`columnList`](/12.1.0/query-builder/executing-queries/aggregates#columnlist) will return either an array of column names for the configured table or the query that is generated by `cfdbinfo` for the configured table.  Especially useful when working with dynamically generated grids.&#x20;

### Bug Fixes

* Correctly compile `insertUsing` statements that use Common Table Expressions (CTEs).
* Update `announceInterception` calls for ColdBox 7. (Thank you, Michael Born.)
* Fixed `insertUsing` not placing Common Table Expressions (CTEs) in the correct order.
* Added the missing keyword in the Postgres [`upsert`](/12.1.0/query-builder/executing-queries/inserts-updates-deletes#upsert) syntax.
* Don't add `DISTINCT` when doing a `COUNT(*)`.
* Support aggregates for unioned queries.

## 8.10.0

* Add a [`firstOrFail`](/12.1.0/query-builder/executing-queries/retrieving-results#firstorfail) fetch method inspired by [Quick](https://quick.ortusbooks.com).
* There are now [specific numeric SQL types for integers and decimals](/12.1.0/query-builder/building-queries/parameters-and-bindings#numeric-sql-type) used during the `inferSQLType` check in `QueryUtils`.  This is an opt-in feature, enabled by setting the `autoDeriveNumericType` setting. The previous approach was to use `CF_SQL_NUMERIC` for all numeric types which could cause performance issues in some grammars as they interpreted all `CF_SQL_NUMERIC` as floating point numbers.

## 8.9.1

* `HOLDLOCK` and `READPAST` are mutually exclusive table locks in SQL Server but were mistakenly being applied together.

## 8.9.0

* Specify `defaultOptions` [inside of your ColdBox config.](/12.1.0/query-builder/options-and-utilities/query-options)

## 8.8.1

* Better parsing of `raw` statements when deriving [`insertUsing`](/12.1.0/query-builder/executing-queries/inserts-updates-deletes#insertusing) columns.

## 8.8.0

### New Features and Improvements

* Insert data based off of a callback or builder using [`insertUsing`](/12.1.0/query-builder/executing-queries/inserts-updates-deletes#insertusing).
* Insert data ignoring duplicate key errors using [`insertIgnore`](/12.1.0/query-builder/executing-queries/inserts-updates-deletes#insertignore).
* Use a callback or builder as the source for an [`upsert`](/12.1.0/query-builder/executing-queries/inserts-updates-deletes#upsert) statement.
* Allow for deleting unmatched source records in [upserts](/12.1.0/query-builder/executing-queries/inserts-updates-deletes#upsert) (SQL Server only).
* Add a new `skipLocked` flag to [`lockForUpdate`](/12.1.0/query-builder/building-queries/locks#lockforupdate).

### Bug Fixes

* Don't uppercase quoted aliases in Oracle.
* Fix for aliases in update statements.
* Don't sort columns for `insertUsing`.
* Add subquery bindings in insert and upsert statements.
* Maintain column order when using source in upsert.

## 8.7.8

* Fix for Oracle returning custom column types when renaming a column.

## 8.7.7

* Explicit arguments scoping.

## 8.7.6

* `arrayEach` is slow compared to merging arrays.

## 8.7.5

* Fix wheres with joins in update statements.

## 8.7.2

* Add better null handling to `inferSqlType`.

## 8.7.1

* Correctly format columns being updated.

## 8.7.0

### New Features and Improvements

* Add an [upsert](/12.1.0/query-builder/executing-queries/inserts-updates-deletes#upsert) method.  `upsert` can update or insert multiple records at once depending on if a column is matched.
* Allow expressions in [`value`](/12.1.0/query-builder/executing-queries/retrieving-results#value) and [`values`](/12.1.0/query-builder/executing-queries/retrieving-results#values).  Also add a [`valueRaw`](/12.1.0/query-builder/executing-queries/retrieving-results#valueraw) and [`valuesRaw`](/12.1.0/query-builder/executing-queries/retrieving-results#valuesraw) helper method to make that pattern more ergonomic.
* Allow [`JOIN` statements in `UPDATE` statements](/12.1.0/query-builder/executing-queries/inserts-updates-deletes#updating-with-joins).  (This is **not** supported on Oracle.)
* Allow [updates with subselects](/12.1.0/query-builder/executing-queries/inserts-updates-deletes#updating-with-subselects) using closures or builder instances.

### Bug Fixes

* Better handling of [`group by`](/12.1.0/query-builder/building-queries/group-by-and-having#groupby) and [`having`](/12.1.0/query-builder/building-queries/group-by-and-having#having) clauses in [pagination](/12.1.0/query-builder/building-queries/limit-offset-and-pagination#simplepaginate-and-paginate) queries.
* Allow any value to be returned from [aggregates](/12.1.0/query-builder/executing-queries/aggregates) including strings, numbers, and dates.
* Provide default values for [sum](/12.1.0/query-builder/executing-queries/aggregates#sum) and [count](/12.1.0/query-builder/executing-queries/aggregates#count) if no records are returned.
* Test in CI with [full](https://coldfusion.adobe.com/2018/07/null-support-in-coldfusion-2018/) [null](https://docs.lucee.org/guides/cookbooks/NullSupport.html) support.

## 8.6.1

* Correctly wrap CTE expressions with parenthesis when required in certain grammars.

## 8.6.0

* `SchemaBuilder` can now be configured with [default query options](/12.1.0/schema-builder/schema-builder).  (Default options will still be overridden by options passed to each `SchemaBuilder` method.)

## 8.5.0

### QueryBuilder

* Add a [`reset`](/12.1.0/query-builder/options-and-utilities/clone-and-reset#reset) method to QueryBuilder.
* Add [locking](/12.1.0/query-builder/building-queries/locks) helpers such as [`lock`](/12.1.0/query-builder/building-queries/locks#lock), [`noLock`](/12.1.0/query-builder/building-queries/locks#nolock), [`lockForUpdate`](/12.1.0/query-builder/building-queries/locks#lockforupdate), and [`sharedLock`](/12.1.0/query-builder/building-queries/locks#sharedlock).
* Correct return aggregate values for date values from `max` and `min` executors.
* [Automatically add a `scale`](/12.1.0/query-builder/building-queries/parameters-and-bindings#automatic-scale-detection) to an incoming query param when needed.
* Add a [`whereNotLike`](/12.1.0/query-builder/building-queries/wheres#wherenotlike) shortcut method.
* Correctly format a `COUNT(DISTINCT column)` query.
* Only use bulk insert syntax when needed in OracleGrammar due to interactions between the `result` parameter to `cfquery`, Lucee, and the Oracle JDBC driver.

### SchemaBuilder

* Add support for [stored computed columns](/12.1.0/schema-builder/column-modifiers#storedas) and [virtual computed columns](/12.1.0/schema-builder/column-modifiers#virtualas).

## 8.4.9

* Swap `master` branch to `main` branch.

## 8.4.8

* Remove unnecessary injection for QueryUtils.

## 8.4.7

* Account for raw expressions when generating mementos for comparison

## 8.4.6

* Add support for [mediumtext](/12.1.0/schema-builder/columns#mediumtext) & [longtext](/12.1.0/schema-builder/columns#longtext) types for MySQLGrammar.

## 8.4.5

* Fix limit on [simplePaginate](/12.1.0/query-builder/executing-queries/retrieving-results#simplepaginate).

## 8.4.1 - 8.4.4

* Migrate release process to GitHub Actions.

## 8.4.0

* Add a `simplePaginate` pagination method for quicker performance when total records or total pages are not needed or too slow.

## 8.3.0

* Introduce a [`numericSQLType`](/12.1.0/query-builder/building-queries/parameters-and-bindings#numeric-sql-type) setting to specify the default numeric SQL type.

## 8.2.2

* Default to `html` for the `dump` format argument to `writeDump`.

## 8.2.1

* Correctly use the passed in `strictDateDetection` to the `QueryUtils.cfc`.

## 8.2.0

{% hint style="success" %}
📹 [Watch a walkthrough of this change on CFCasts.](https://cfcasts.com/series/whats-new-in-qb-8)
{% endhint %}

* Added a [`dump`](/12.1.0/query-builder/debugging#dump) command to aid in debugging a query while chaining.

## 8.1.0

{% hint style="success" %}
📹 [Watch a walkthrough of these changes on CFCasts.](https://cfcasts.com/series/whats-new-in-qb-8)
{% endhint %}

* [`orderByRaw`](/12.1.0/query-builder/building-queries/ordering-grouping-and-limit#order-by-raw) now can accept bindings.
* A new, optional [`strictDateDetection`](/12.1.0/query-builder/building-queries/parameters-and-bindings#strict-date-detection) setting is available to check the underlying Java class of a date object instead of using `isDate`.

## 8.0.3

* Ignore select bindings for aggregate queries.
* Allow spaces in table aliases.
* Split FLOAT and DECIMAL column types in SQL Server.

## 8.0.2

* Clear orderBy bindings when calling `clearOrders`.

## 8.0.1

* Trim table definitions before searching for aliases.  Makes qb more lenient with extra whitespace.

## 8.0.0

{% hint style="success" %}
📹 [Watch a walkthrough of these changes on CFCasts.](https://cfcasts.com/series/whats-new-in-qb-8)
{% endhint %}

#### BREAKING CHANGES

* \`\`[`when`](/12.1.0/query-builder/building-queries/when#when) callbacks now automatically scope and group where clauses when an `OR` combinator is used.

#### Other Changes

* Combine [`clearOrders`](/12.1.0/query-builder/building-queries/ordering-grouping-and-limit#clearorders) and `orderBy` with a new [`reorder`](/12.1.0/query-builder/building-queries/ordering-grouping-and-limit#reorder)method.
* Clear current selected columns with [`clearSelect`](/12.1.0/query-builder/building-queries/selects#clearselect).
* Combine [`clearSelect`](/12.1.0/query-builder/building-queries/selects#clearselect) and either [`select`](/12.1.0/query-builder/building-queries/selects#get) or [`selectRaw`](/12.1.0/query-builder/building-queries/selects#get-3) with [`reselect`](/12.1.0/query-builder/building-queries/selects#reselect) and [`reselectRaw`](/12.1.0/query-builder/building-queries/selects#reselectraw) respectively.

## 7.10.0

* Expose nested where functions to enable advanced query manipulation in downstream libraries like Quick.

## 7.9.9

* Fixes for OracleGrammar including table aliases and wrapped subqueries.

## 7.9.8

* Allow nullable [timestamps](/12.1.0/schema-builder/columns#timestamp) in MySQL.

## 7.9.7

* Return 0 on null [aggregates](/12.1.0/query-builder/executing-queries/aggregates).

## 7.9.6

* Match type hints to documentation for [join](/12.1.0/query-builder/building-queries/joins) functions

## 7.9.5

* Handle enhanced numeric checks with Secure Profile enabled.

## 7.9.4

* Allow raw statements in basic where clauses.

## 7.9.3

* Passed along the options struct to the [`count`](/12.1.0/query-builder/executing-queries/aggregates#count) method when calling [`paginate`](/12.1.0/query-builder/building-queries/limit-offset-and-pagination#paginate).

## 7.9.2

* Allow for space-delimited [sort](/12.1.0/query-builder/building-queries/ordering-grouping-and-limit) directions like `column DESC`.
* Add helpful message when trying to use a closure with [`from`](/12.1.0/query-builder/building-queries/from#get) instead of [`fromSub`](/12.1.0/query-builder/building-queries/from#get-3).
* \`\`[`value`](/12.1.0/query-builder/executing-queries/retrieving-results#value) and [`values`](/12.1.0/query-builder/executing-queries/retrieving-results#values) now work with [column formatters.](/12.1.0/query-builder/options-and-utilities/column-formatter)
* Correctly format RETURNING clauses with [column formatters](/12.1.0/query-builder/options-and-utilities/column-formatter) and ignoring table qualifiers.

## 7.9.1

* Handle multi-word columns in `queryRemoveColumns`.

## 7.9.0

* Remove elvis operator due to ACF compatibility issues

## 7.8.0

* Add support for [MONEY](/12.1.0/schema-builder/columns#money) and [SMALLMONEY](/12.1.0/schema-builder/columns#smallmoney) data types to [SchemaBuilder](/12.1.0/schema-builder/create).

## 7.7.3

* Fix wrapping of [enum](/12.1.0/schema-builder/columns#enum) types for Postgres.

## 7.7.2

* Compatibility fix for ACF 2018 and `listLast` parsing.
* Include current\_timestamp default for [`timestamp`](/12.1.0/schema-builder/columns#timestamp) columns in SchemaBuilder.
* Ignore table qualifiers for insert and update.

## 7.7.1

* Fix a bug with preventDuplicateJoins when using the closure syntax with a join.

## 7.7.0

* Add executionTime to the data output from BaseGrammar, including being available in interceptors.

## 7.6.2

* Fix a case where a column was not wrapped correctly when a `where` used a subquery for the value.

## 7.6.1

* Avoid `duplicate` function due to cbORM / Hibernate bugs when used in the same application.

## 7.6.0

* Split off a private `whereBasic` method.  This is used in Quick to provide extra sql type features.
* Add a [`clearOrders`](/12.1.0/query-builder/building-queries/ordering-grouping-and-limit#clearorders) method.  Any already configured orders are cleared.  Any orders added after this call will be added as normal.
* [`selectRaw`](/12.1.0/query-builder/building-queries/selects#get-3) now can take an array of expressions.

## 7.5.1

Fixed an issue using column formatters with `update` and `insert`.

## 7.5.0

Using a new `preventDuplicateJoins` setting in the module settings, qb can detect duplicate joins and ignore them. This is especially useful in a heavily filtered and dynamic query where you may or may not need the join at all or more than one column may need the same join. `preventDuplicateJoins` defaults to `false`, so it is opt-in. It may be turned on by default in a future breaking release of qb.

## 7.4.0

Enhance order by's with more direction options ([c767ac8](https://github.com/coldbox-modules/qb/commit/c767ac8764fab70d70dc77baa7bb9fb27c1d4eeb))

You can now use two shortcut methods: `orderByAsc` and `orderByDesc`. Additionally, `orderBySub` or using `orderBy` with a closure or builder instance will respect the direction argument.

## 7.3.15

* Fix using `whereBetween` with query param structs ([07c9b72](https://github.com/coldbox-modules/qb/commit/07c9b728bdbad6bf02ccd9d21dbdf6968062c02e))

## 7.3.14

* Ignore orders in aggregate queries ([39e1338](https://github.com/coldbox-modules/qb/commit/39e1338a147838165e05225bd91ef7e6cde2319a))

## 7.3.13

* Format with cfformat ([dc2a9b6](https://github.com/coldbox-modules/qb/commit/dc2a9b61503690d753a71c3b7bce002ebdf4ccda))

## 7.3.12

* Improve column wrapping with trimming ([d98a5cb](https://github.com/coldbox-modules/qb/commit/d98a5cb65851c154b6755e90254d1a2c1df82833))
* Prefer the parent query over magic methods when the parent query has the exact method. ([f9fd8d1](https://github.com/coldbox-modules/qb/commit/f9fd8d157cdc0d7480811c4659c130ee1d58888f))

## 7.3.9, 7.3.10, 7.3.11

* Switch to using [ForgeBox Storage](https://commandbox.ortusbooks.com/forgebox-enterprise/storage#storing-package-binaries-on-forgebox).

## 7.3.8

* Allow passing query options in to paginate ([cdecfb3](https://github.com/coldbox-modules/qb/commit/cdecfb36f5acab87edd3a478c570f77d285df554))

## 7.3.7

* Fix for inserting null values directly ([1de27a6](https://github.com/coldbox-modules/qb/commit/1de27a697f65bfdeed63442ad66be47cd0d30344))

## 7.3.5, 7.3.6

* Use cfformat for automatic formatting ([119e434](https://github.com/coldbox-modules/qb/commit/119e434b307a2cc2323b857a214c20842cafbbd4))
* Add a type to the onMissingMethod exception ([90d1093](https://github.com/coldbox-modules/qb/commit/90d109312b2ea86c00db34020b12b5ab22bb377b))

## 7.3.4

* Correctly wrap [comments](/12.1.0/schema-builder/column-modifiers#comment) in `MySQLGrammar`.

## 7.3.2, 7.3.3

* Publish qb apidocs to [Ortus API Docs](https://apidocs.ortussolutions.com/#/coldbox-modules/qb/).

## 7.3.1

* Fix for null values breaking the new `checkIsActuallyNumeric` method in `QueryUtils`.

## 7.3.0

* Add a `parameterLimit` public property to `SqlServerGrammar`.  This property is used in Quick to split up eager loading to work around the 2100 param limit of SQL Server.

## 7.2.0

* Allow a [parent query](broken://pages/-LxZv7a5KIrwcD1HJyVa) to be set.  A parent query will receive any method calls that are not found on the Query Builder instance.  This is especially useful for instances like [Quick](https://quick.ortusbooks.com/) to allow Quick features like scopes to be available inside any closures.

## 7.1.0

* Lambdas (arrow functions) are now allowed wherever closures are allowed.
* Add an [`orderByRaw`](/12.1.0/query-builder/building-queries/ordering-grouping-and-limit#order-by-raw) method.
* Allow for fully-qualified column names (`table_name.column.name`) in the [`value`](/12.1.0/query-builder/executing-queries/retrieving-results#value) and [`values`](/12.1.0/query-builder/executing-queries/retrieving-results#values) methods.

## 7.0.0

#### **BREAKING CHANGES**

*Please see the* [*Migration Guide*](/12.1.0/migration-guide#v-7-0-0) *for more information on these changes.*

* Drop support for Lucee 4.5 and Adobe ColdFusion 11.
* `MSSQLGrammar` renamed to `SqlServerGrammar`
* Remove variadic parameters support in builder functions like `select`.
* The `defaultGrammar` mapping needs to be the full WireBox mapping, including the `@qb`, if needed.
  * For instance, `MSSQLGrammar` would become `MSSQLGrammar@qb`.
  * This will allow for other grammars to be more easily contributed via third party modules.
* The argument names of `forPage` changed to match the new `paginate` method.
* Add `defaultValue` and optional exception throwing to `value`. (This changed the argument order.)
* All methods that could conceivably take a subquery as well as a value now accept a closure or another builder instance to use as a subquery. (This changed the argument names in some instances.)

#### **Other Changes**

* Completely revamped documentation! (You're looking at it right now.)
* Add new flag to [`toSQL( showBindings = true )`](/12.1.0/query-builder/debugging#tosql) to replace question marks (`?`) with `cfqueryparam`-compatible structs for debugging.
* Preserve column case and order when converting a query to an array using the default `"array"` return format.
* Add a new [paginate](/12.1.0/query-builder/executing-queries/retrieving-results#paginate) method to generate a pagination struct alongside the results.  This can be customized using a custom [PaginationCollector](/12.1.0/query-builder/executing-queries/retrieving-results#custom-pagination-collectors).
* Allow raw values in [`insert`](/12.1.0/query-builder/executing-queries/inserts-updates-deletes#insert) calls.
* Allow [default `queryExecute` `options`](/12.1.0/query-builder/options-and-utilities/query-options#default-options) to be configure at a Query Builder level.  This also enables custom `QueryBuilders` a la [Hyper](https://www.forgebox.io/view/hyper).
* Add a [`whereLike`](/12.1.0/query-builder/building-queries/wheres#wherelike) method.
* Allow closures to be used in left and right joins.
* Provide an [`addUpdate`](/12.1.0/query-builder/executing-queries/inserts-updates-deletes#addupdate) method to programmatically build the `SET` clause of an update query.
* [Add a new `chunk` method](/12.1.0/query-builder/executing-queries/retrieving-results#chunking-results) to grab records from the database in small sets.
* Add `raw` in `alterTable` segments.
* Add `dropAllObjects` support for `SqlServerGrammar` and `OracleGrammar` to support `migrate fresh` from cfmigrations.
* Add a `renameTable` alias for `rename`.
* Remove default constraints when dropping columns with a default on `SqlServerGrammar`.
* Add more column types and column helpers to `SchemaBuilder`, including:
  * `datetimeTz`
  * `lineString`
  * `nullableTimestamps`
  * `point`
  * `polygon`
  * `softDeletes`
  * `softDeletesTz`
  * `timeTz`
  * `timestamps`
  * `timestampTz`
  * `timestampsTz`
  * `withCurrent`

\*\*\*\*

## 6.4.0

* [Allow Expressions (`query.raw`) in update statements.](/12.1.0/whats-new)


# Installation & Usage

## Installation

Installation is easy through [CommandBox](https://www.ortussolutions.com/products/commandbox) and [ForgeBox](https://www.forgebox.io/). Simply type `box install qb` to get started.

## Usage

To start a new query, instantiate a new Builder: `wirebox.getInstance('QueryBuilder@qb')`.

By default, qb uses a generic Grammar. You can specify your specific grammar in ColdBox by setting the `defaultGrammar` in your `moduleSettings`.

```cfscript
moduleSettings = {
    qb = {
        defaultGrammar = "MySQLGrammar@qb"
    }
};
```

The grammars provided by qb are:

* MySQLGrammar
* OracleGrammar
* PostgresGrammar
* SqlServerGrammar
* SQLiteGrammar
* DerbyGrammar

If you are not using WireBox, make sure to wire up the `Builder` object with the correct grammar:

```cfscript
var grammar = new qb.models.Grammars.MySQLGrammar();
var builder = new qb.models.Query.QueryBuilder( grammar );
```

## Configuration Settings

Here are the full configuration settings you can use in the module settings:

```javascript
moduleSettings = {

    qb : {
        "defaultGrammar": "AutoDiscover@qb",
        "defaultReturnFormat": "array",
        "preventDuplicateJoins": false,
        "convertEmptyStringsToNull": true,
        "numericSQLType": "NUMERIC",
        "integerSQLType": "INTEGER",
        "decimalSQLType": "DECIMAL",
        "defaultOptions": {},
        "sqlCommenter": {
            "enabled": false,
            "commenters": [
                { "class": "FrameworkCommenter@qb", "properties": {} },
                { "class": "RouteInfoCommenter@qb", "properties": {} },
                { "class": "DBInfoCommenter@qb", "properties": {} }
            ]
        },
        "shouldMaxRowsOverrideToAll": function( maxRows ) {
            return maxRows <= 0;
        }
    }

}
```

## SQL Type Inference

QB binds all parameters by default and guesses the SQL type based on passed values. The default SQL type for numeric values is `CF_SQL_NUMERIC`, which is a floating point number, for the widest compatibility. This can cause performance problems with large recordsets in some database engines. You can provide a different default in `coldbox.cfc` if you wish to override this setting:

```cfscript
moduleSettings = {
    qb = {
        defaultGrammar = "MySQLGrammar@qb",
        numericSQLType = "CF_SQL_BIGINT"
    }
};
```

## Integrating With FW/1

> Note: These instructions assume a basic knowledge of FW/1, a working FW/1 application structure with qb installed in the `/subsystems` directory (manually or via CommandBox), and a database configured to run with your application.

### Wiring Up With DI/1

Once the application structure is setup, now we need to wire up qb to a bean factory using DI/1.

First we will add a mapping in `Application.cfc`.

```cfscript
this.mappings = {
    "/qb" = expandPath("./subsystems/qb")
};
```

Next we need to tell DI/1 where qb's components are and how to reference them for later use in the application. We can do so by defining the configuration settings in the `variables.framework.subsystems` struct in `Application.cfc`. The example below makes use of a load listener to declare each component instance and pass in any constructor arguments.

```cfscript
qb = {
  diLocations = "/qb/models",
  diConfig = {
    loadListener = function( di1 ) {
      di1.declare( "BaseGrammar" ).instanceOf( "qb.models.Query.Grammars.Grammar" ).done()
         .declare( "MySQLGrammar" ).instanceOf( "qb.models.Query.Grammars.MySQLGrammar" ).done()
         .declare( "QueryUtils" ).instanceOf( "qb.models.Query.QueryUtils" ).done()
         .declare( "QueryBuilder" ).instanceOf( "qb.models.Query.QueryBuilder" )
         .withOverrides({
            grammar = di1.getBean( "MySQLGrammar" ),
            utils = di1.getBean( "QueryUtils" ),
            returnFormat = "array"
         })
         .asTransient();
    }
  }
}
```

### Usage In Your FW/1 Application

Now that everything is configured, you can launch your application with CommandBox by entering `start` in the terminal or use whatever method you're accustomed to.

To access qb from your application's code, you can call on it by using `getBeanFactory()`.

```cfscript
// Create an instance of qb
builder = getBeanFactory( "qb" ).getBean( "QueryBuilder" );
// Query the database
posts = builder.from( "Posts" ).get();
posts = builder.from( "Posts" ).where( "IsDraft", "=", 0 ).get();
```

#### For further instructions on getting started with qb & FW/1, refer to [this blog post](http://tonyjunkes.com/blog/working-with-fw1-and-qb/).


# Migration Guide

## v12.0.0

### Add new [`convertEmptyStringsToNull`](/12.1.0/installation-and-usage#configuration-settings) setting and default to true.

qb now automatically converts an empty string value to `null` when inserting into a query.  If your application relies on inserting or updating values to an empty string, set this setting to `false`.

### Remove `autoAddScale` setting

It is no longer possible to disable auto scale being added.  You can still override any scale by providing it in your query param struct.

### Remove `strictDateDetection` setting

It is no longer possible to disable strict date detection being performed.  You can still override the `cfsqltype` by specifying it in your query param struct.

### Remove `autoDeriveNumericType` setting

It is no longer possible to disable the numeric type detection.  You can specify the numeric types you want used in your settings.  You can also override the `cfsqltype` by specifying it in your query param struct.

### Argument order changed for some aggregate functions

The [`max`](/12.1.0/query-builder/executing-queries/aggregates#max), [`min`](/12.1.0/query-builder/executing-queries/aggregates#min), [`count`](/12.1.0/query-builder/executing-queries/aggregates#count), and [`sum`](/12.1.0/query-builder/executing-queries/aggregates#sum) methods now accept a `defaultValue` argument.  This comes **before** the `defaultOptions` argument.  If you are using positional parameters with any of these functions, update your code to the new method signature.

### Argument order changed for QueryUtils initializer

This only affects people instantiating `QueryUtils` manually (such as non-ColdBox users) and instantiating with positional arguments.

Please review the QueryUtils `init` function and update your code to the new method signature, if needed.

### Generated `cfsqltype` attributes no longer include the `CF_SQL_` prefix

Although it shouldn't impact any running application, out of an abundance of caution, we are labeling the drop of the`CF_SQL_` prefix as a breaking change.  This prefix has been optional since Adobe ColdFusion 11.

## v11.0.0

### Auto Boolean Casting

Grammars will be able to influence the `cfsqltype` and value when passing in a literal boolean value as a binding. Postgres and SQLite have boolean support, so they will keep the literal boolean value and use a`cfsqltype` of `CF_SQL_OTHER`. SQL Server uses `CF_SQL_BIT`, Oracle users`CF_SQL_NUMERIC`, and MySQL uses `CF_SQL_TINYINT` — all of these will convert literal boolean values to either 1 or 0. This behavior is skipped when providing a custom `cfsqltype`. Custom grammars can implement the`getBooleanSqlType` and `convertBooleanValue` methods to customize this behavior.

Most people will not need to change anything in their code for this breaking change.

## v10.0.0

### Dropped Support for Adobe Coldfusion 2018

### Internal variables renamed for compatibility with BoxLang and cleaner code in general

In certifying qb for BoxLang, we discovered that some of the way qb had worked for years was due to a lucky interaction between properties and functions sharing a name.  Both of these values are put into the `variables` scope, and the way qb shared some of these names like the `from` method as well as the `from` property only worked because of the way Lucee and ACF ordered defining the function and properties.  BoxLang is more strict in this regard and probably for the best.  You can probably imagine how setting `variables.from` inside a function called `from` would maybe work once and then cause a very strange bug when trying to call the `from` function internally again.  Because of these reasons, the following properties have had their names changed:

#### QueryBuilder

* `from` -> `tableName`

#### Column

* `nullable` -> `isNullable`
* `unique` -> `isUnique`
* `unsigned` -> `isUnsigned`
* `default` -> `defaultValue`
* `comment` -> `commentValue`
* `onUpdate` -> `onUpdateAction`
* `onDelete` -> `onDeleteAction`

The following functions have had their signatures updated:

#### BaseGrammar

* `compileFrom` -> `compileTableName( required QueryBuilder query, required any tableName )`

For the majority of users, this will not take any updates to their code to work with qb 10.  For users who have created a custom grammar, column type, or a custom QueryBuilder class, you will need to make sure you code uses the updated property names and functions.

## v9.0.0

### Dropped support for Adobe ColdFusion 2016

Adobe has ended support for ACF 2016, and so must we.

### SchemaBuilder's `uuid` split into [guid()](/12.1.0/schema-builder/columns#guid) and [uuid()](/12.1.0/schema-builder/columns#uuid)

CFML's `uuid` does not match other languages; it's one character shorter. Because of this, the value from `createUUID()` cannot be used in some database column types like SQL Server's `uniqueidentifier`. This made for some confusion in SchemaBuilder since it wasn't clear if `uuid` meant CFML's definition or the wider world's definition.

So, the types have been split, following Lucee's pattern, into [`uuid`](/12.1.0/schema-builder/columns#uuid) (matching CFML's [`createUUID()`](https://cfdocs.org/createuuid)) and [`guid`](/12.1.0/schema-builder/columns#guid) (matching Java's UUID or [`createGUID()`](https://cfdocs.org/createguid) on Lucee).

{% hint style="warning" %}
If you are using `uuid` with 36 character UUIDs or SQL Server's `uniqueidentifier` columns, please migrate your `uuid` calls to `guid`.
{% endhint %}

### Returning all rows from [paginate](/12.1.0/query-builder/executing-queries/retrieving-results#paginate) when maxRows is  0 or lower

Popular grid frameworks like Quasar and Datatables use values of 0 or -1 to return all rows from a query. This is now supported in qb. Previously, it generated an invalid query (`SELECT * FROM users LIMIT 0 OFFSET 0`).

{% hint style="success" %}
If this behavior is fine for your application, you don't need to change anything.
{% endhint %}

This behavior can be customized by providing a callback to the `shouldMaxRowsOverrideToAll` setting or `init` argument.&#x20;

{% hint style="danger" %}
If you need to revert to the previous behavior, provide the following as the `shouldMaxRowsOverrideToAll` setting:

```cfscript
moduleSettings = {
    "qb": {
        "shouldMaxRowsOverrideToAll": function( maxRows ) {
            return false;
        }
    }
};
```

{% endhint %}

### [`autoDeriveNumericType`](/12.1.0/query-builder/building-queries/parameters-and-bindings#numeric-sql-type) is now the default

Introduced in [8.10.0](#8.10.0), this feature uses separate SQL types for integers and decimals to increase performance in certain database grammars.  This feature is now the default, but the previous behavior can be enabled by setting `autoDeriveNumericType` to `false`.

{% hint style="success" %}
This behavior *should* be an improvement in most every case without any changes needed.
{% endhint %}

{% hint style="danger" %}
If you need to revert to the previous behavior, provide the following as the `autoDeriveNumericType` setting:

```cfscript
moduleSettings = {
    "qb": {
        "autoDeriveNumericType": false
    }
};
```

{% endhint %}

{% hint style="warning" %}
**Note:** The option to revert to the old behavior will be removed in the next major version.
{% endhint %}

#### [`strictDateDetection`](/12.1.0/query-builder/building-queries/parameters-and-bindings#strict-date-detection) is now the default

Introduced in [8.1.0](#8.1.0), this feature only returns a SQL type of `CF_SQL_TIMESTAMP` if the param is a date object, not just a string that looks like a date.  This helps avoid situations where some strings were incorrectly interpreted as dates.  For many, the migration path is straightforward — calls to [`now()`](https://cfdocs.org/now) are already date objects as well as any function that operates on a date.  If you need to parse a string as a date, the [`parseDateTime`](https://cfdocs.org/parsedatetime) built-in function can accomplish that.

{% hint style="warning" %}
If you are relying on qb treating any strings as dates you will need to parse them as actual date objects first. (You can do so using functions like [`parseDateTime`](https://cfdocs.org/parsedatetime).
{% endhint %}

{% hint style="danger" %}
If you need to revert to the previous behavior, provide the following as the `strictDateDetection` setting:

```cfscript
moduleSettings = {
    "qb": {
        "strictDateDetection": false
    }
};
```

{% endhint %}

{% hint style="warning" %}
**Note:** The option to revert to the old behavior **may** be removed in the next major version.
{% endhint %}

## v8.0.0

### Where clauses with an OR combinator are now automatically wrapped inside [`when`](/12.1.0/query-builder/building-queries/when#when) callbacks

This isn't a breaking change that will affect most people.  In fact, it will most likely improve your code.

Previously, when using the [`when`](/12.1.0/query-builder/building-queries/when#when) control flow function, you were fully responsible for the wrapping of your where statements.  For example, the following query:

```javascript
qb.from( "users" )
    .where( "active", 1 )
    .when( len( url.q ), function( q ) {
        q.where( "username", "LIKE", q & "%" )
            .orWhere( "email", "LIKE", q & "%" );   
    } );
```

Would generate the following SQL:

```sql
SELECT *
FROM "users"
WHERE "active" = ?
    AND "username" = ?
    OR "email" = ?
```

The problem with this statement is that the `OR` can short circuit the `active` check.

The fix is to wrap the `LIKE` statements in parenthesis.  This is done in qb using a function callback to `where`.

```javascript
qb.from( "users" )
    .where( "active", 1 )
    .where( function( q ) {
        q.where( "username", "LIKE", q & "%" )
            .orWhere( "email", "LIKE", q & "%" );
    } );
```

```sql
SELECT *
FROM "users"
WHERE "active" = ?
    AND (
        "username" = ?
        OR "email" = ?
    )
```

When using the `when` control flow function, it was easy to miss this.  This is because you are already in a closure - it looks the same as when using `where` to group the clauses.

In qb 8.0.0, `when` will automatically group added where clauses when needed.  That means our original example now produces the SQL we probably expected.

```javascript
// qb 8.0.0
qb.from( "users" )
    .where( "active", 1 )
    .when( len( url.q ), function( q ) {
        q.where( "username", "LIKE", q & "%" )
            .orWhere( "email", "LIKE", q & "%" );   
    } );
```

```sql
SELECT *
FROM "users"
WHERE "active" = ?
    AND (
        "username" = ?
        OR "email" = ?
    )
```

Grouping is not needed if there is no `OR` combinator.  In these cases no grouping is added.

```javascript
// qb 8.0.0
qb.from( "users" )
    .where( "active", 1 )
    .when( url.keyExists( "admin" ), function( q ) {
        q.where( "admin", 1 )
            .whereNotNull( "hireDate" );
    } );
```

```sql
SELECT *
FROM "users"
WHERE "active" = ?
    AND "admin" = ?
    AND "hireDate IS NOT NULL
```

If you had already wrapped your expression in a group inside the `when` callback, nothing changes.  Your code works as before.  The `OR` combinator check only works on the top most level of added where clauses.

```javascript
qb.from( "users" )
    .where( "active", 1 )
    .when( len( url.q ), function( q ) {
        q.where( function( q2 ) {
            q2.where( "username", "LIKE", q & "%" )
                .orWhere( "email", "LIKE", q & "%" );
        } );
    } );
```

```sql
SELECT *
FROM "users"
WHERE "active" = ?
    AND (
        "username" = ?
        OR "email" = ?
    )
```

Additionally, if you do not add any where clauses inside a `when` callback, nothing changes from qb 7.

The breaking change part is if you were relying on these statements residing at the same level without grouping.  In those cases, you may pass the `withoutScoping` flag to the `when` callback.

```javascript
// qb 8.0.0
qb.from( "users" )
    .where( "active", 1 )
    .when(
        condition = len( url.q ),
        onTrue = function( q ) {
            q.where( "username", "LIKE", q & "%" )
                .orWhere( "email", "LIKE", q & "%" );   
        },
        withoutScoping = true
    );
```

```sql
SELECT *
FROM "users"
WHERE "active" = ?
    AND "username" = ?
    OR "email" = ?
```

## v7.0.0

### Lucee 4.5 and Adobe ColdFusion 11 EOL

Support for Lucee 4.5 and Adobe ColdFusion 11 has been dropped. If you need support for these engines, please remain on an earlier version of qb.

### MSSQLGrammar renamed to SqlServerGrammar

`MSSQLGrammar` was visually too close to `MySQLGrammar` and was hard to differentiate quickly. `SqlServerGrammar` is much more unique and easily identifiable. Additionally, more people that use this library refer to their database engine as "SQL Server" than "MSSQL".

To migrate, replace any instances of `MSSQLGrammar` with `SqlServerGrammar`. Make sure to also append the `@qb` namespace, if needed, [as explained below.](/12.1.0/migration-guide#defaultgrammar-updated-to-be-the-full-wirebox-mapping)

### Variadic Parameters Support Removed

Variadic parameter support was the ability to pass any number of arguments to certain methods like `select`.

```javascript
qb.select( "name", "email", "createdDate" );
```

This code came with a slight performance cost and readability cost. That, combined with the fact that the above syntax is very close to an array, we are dropping support for variadic parameters. To migrate, wrap instances of variadic parameters in an array:

```javascript
qb.select( [ "name", "email", "createdDate" ] );
```

### defaultGrammar updated to be the full WireBox mapping

In previous versions, the value passed to `defaultGrammar` was used to look up a mapping in the `@qb` namespace. This made it difficult to add or use grammars that weren't part of qb. (You could get around this be registering your custom grammar in the `@qb` namespace, but doing so seemed strange.)

To migrate this code, change your `defaultGrammar` to be the full WireBox mapping in your `moduleSettings`:

```javascript
moduleSettings = {
    "qb": {
        "defaultGrammar": "MSSQLGrammar@qb"
    }
};
```

### value method argument order changed

A `defaultValue` parameter and optional exception throwing was added to `value`. This pushed the `options` struct to the end of the method. If you are using positional parameters with `value`, you will need to update your method calls to either use named parameters or the new positions.

```javascript
public any function value(
    required string column,
    string defaultValue = "",
    boolean throwWhenNotFound = false,
    struct options = {}
);
```

### Some methods renamed `callback` to `query`

All methods that could conceivably take a subquery as well as a value now accept a closure or another builder instance to use as a subquery. This led to changing the `callback` argument to `query` in the following cases:

* `whereSub`
* `whereInSub`
* `whereExists`
* `orWhereExists`
* `whereNotExists`
* `andWhereNotExists`
* `orWhereNotExists`
* `whereNullSub`
* `orderBySub`
* `subSelect`

If you are using named parameters with any of the above methods you will need to migrate your method calls.

## v5.0.0

Version `v5.0.0` brings support for `SchemaBuilder` inside `qb`. To avoid naming confusion, `Builder` was renamed to `QueryBuilder`. Any references in your code to `Builder@qb` need to be updated to `QueryBuilder@qb`.


# Contributing & Filing Issues

We welcome all types of contributions!

The most common type of contribution is to fix an incorrect SQL generation for a database grammar.

To debug what SQL is being ran, you can always call `toSQL` on any `QueryBuilder` or `SchemaBuilder` object. Additionally, you can listen to the `preQBExecute` interception point for the generated SQL.

Each of the database grammars have two tests — `{Grammar}QueryBuilderSpec.cfc` and `{Grammar}SchemaBuilderSpec.cfc`. These tests run the same qb syntax across the different grammars. In each test are methods that return SQL strings like so:

```javascript
// MSSQLQueryBuilderSpec.cfc
function orWhere() {
    // If just a string is returned, we assume the bindings is an empty array ([])
    return {
        sql = "SELECT * FROM [users] WHERE [id] = ? OR [email] = ?",
        bindings = [ 1, "foo" ]
    };
}
```

```javascript
// OracleSchemaBuilderSpec.cfc
function boolean() {
    // returns an array since schema builder can execute multiple statements.
    return [ "CREATE TABLE ""USERS"" (""ACTIVE"" NUMBER(1, 0) NOT NULL)" ];
}
```

If you find an issue with the SQL generated from a grammar, please file a pull request with the correct SQL in these tests. It's okay if you don't submit a fix as well. (But we'd greatly appreciate it!) Doing so will help expedite the fix.

If you want to add support for a new database grammar, simply copy these two tests from an existing grammar, rename them, change the `getBuilder` method to return your new grammar, and fill out the SQL as it should be. That will guide your implementation to be 100% compatible with the other grammars in qb.


# Getting a New Query

A query builder is a stateful, transient object. That means that if you want to execute two different queries, you need two separate instances of `QueryBuilder`.

{% code title="QueryBuilder" %}

```javascript
// This will cause you pain and grief...

var user = query.from( "users" )
  .where( "username", rc.username )
  .first();

var posts = query.from( "posts" ).get();
// This will error because `username` is not a column in `posts`.
```

{% endcode %}

As such, be careful when injecting QueryBuilder in to a component. If the component is a singleton, you will need to create the QueryBuilder inline or use a provider. This applies to ColdBox handlers as well.

{% code title="handlers/posts.cfc" %}

```javascript
component {

    property name="query" inject="QueryBuilder@qb";

    function create( event, rc, prc ) {
        // This will cause you pain and grief...
        query.table( "posts" )
            .where( "id", rc.id )
            .update( event.getOnly( [ "body" ] ) );
    }

}
```

{% endcode %}

While the above may seem innoculous, it can run in to issues as multiple requests come in to your application. Each request is sharing the same query builder instance and subsequent requests will have unintended results as the `where` clause keeps growing request after request.

The solution is to either create the QueryBuilder inline, ensuring that each request has its own query to execute:

{% code title="handlers/posts.cfc" %}

```javascript
component {

    function create( event, rc, prc ) {
        getInstance( "QueryBuilder@qb" )
            .table( "posts" )
            .where( "id", rc.id )
            .update( event.getOnly( [ "body" ] ) );
    }

}
```

{% endcode %}

Or to use a WireBox provider to create a new query each time it is accessed:

{% code title="handlers/posts.cfc" %}

```javascript
component {

    property name="query" inject="provider:QueryBuilder@qb";

    function create( event, rc, prc ) {
        query.table( "posts" )
            .where( "id", rc.id )
            .update( event.getOnly( [ "body" ] ) );
    }

}
```

{% endcode %}

{% hint style="warning" %}
One caveat when using a WireBox Provider: WireBox Providers proxy methods on to a new instance of the provided mapping on all methods except `get`. `get` is a method on the Provider itself. If you call `get` as the first method on a Provider it will return a new instance of QueryBuilder, not execute the query. In those (rare) cases you will need to call `query.get().get()`.
{% endhint %}

## newQuery

Once you have access to a QueryBuilder instance, you can create a new query using the same datasource, utils, returnFormat, paginationCollector, columnFormatter, and defaultOptions as the current QueryBuilder instance.

```javascript
// This will cause you pain and grief...

var user = query.from( "users" )
  .where( "username", rc.username )
  .first();

var posts = query.newQuery().from( "posts" ).get();
// This will work as we expect it to.
```


# Building Queries


# Selects

## Specifying A Select Clause

You may not always want to select all columns from a database table. You can influence the select list of a query with the following methods.

Individual columns can contain fully-qualified names (`some_table.some_column`), table aliases (`alias.some_column`), and even set column aliases themselves (`some_column AS c`). The `columns` argument can be a single column, a list of columns (comma-separated), or an array of columns.

## select <a href="#get" id="get"></a>

| Name    | Type            | Required | Default | Description                                                        |
| ------- | --------------- | -------- | ------- | ------------------------------------------------------------------ |
| columns | string \| array | `false`  | ​`"*"`  | A single column, list of columns, or array of columns to retrieve. |

When calling `select` any previous columns are discarded. If you want to incrementally select columns, use the `addSelect` method.

If you pass no columns to this method, it will default to `"*"`.

{% code title="QueryBuilder" %}

```javascript
query.select( [ "fname AS firstName", "age" ] ).from( "users" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT `fname` AS `firstName`, `age` FROM `users`
```

{% endcode %}

## distinct <a href="#get" id="get"></a>

| Name  | Type    | Required | Default | Description                     |
| ----- | ------- | -------- | ------- | ------------------------------- |
| state | boolean | `false`  | ​`true` | Value to set the distinct flag. |

Calling distinct will cause the query to be executed with the `DISTINCT` keyword.

{% code title="QueryBuilder" %}

```javascript
query.select( "username" ).distinct().from( "users" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT DISTINCT `username` FROM `users`
```

{% endcode %}

{% hint style="info" %}
`distinct` applies to the entire query, not just certain fields.
{% endhint %}

## addSelect <a href="#get" id="get"></a>

| Name    | Type            | Required | Default | Description                                                                 |
| ------- | --------------- | -------- | ------- | --------------------------------------------------------------------------- |
| columns | string \| array | `true`   | ​       | A single column, list of columns, or array of columns to add to the select. |

This method adds the columns passed to it to the currently selected columns.

{% hint style="warning" %}
If the `QueryBuilder` is currently selecting all columns (`"*"`) when this method is called, the incoming columns will becoming the only columns selected.
{% endhint %}

{% code title="QueryBuilder" %}

```javascript
query.addSelect( [ "fname AS firstName", "age" ] ).from( "users" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT `fname` AS `firstName`, `age` FROM `users`
```

{% endcode %}

## selectRaw <a href="#get" id="get"></a>

| Name       | Type  | Required | Default | Description                                  |
| ---------- | ----- | -------- | ------- | -------------------------------------------- |
| expression | any   | `true`   | ​       | The raw expression for the select statement. |
| bindings   | array | `false`  | `[]`    | Any bindings needed for the raw expression.  |

A shortcut to use a raw expression in the select clause.

The expression is added to the other already selected columns.

*(To learn more about raw and expressions, check out the docs on* [*Raw Expressions*](/12.1.0/query-builder/building-queries/raw-expressions)*.)*

{% code title="QueryBuilder" %}

```javascript
query.selectRaw( "YEAR(birthdate) AS birth_year" ).from( "users" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT YEAR(birthdate) AS birth_year FROM `users`
```

{% endcode %}

## subSelect <a href="#get" id="get"></a>

| Name  | Type                     | Required | Default | Description                                    |
| ----- | ------------------------ | -------- | ------- | ---------------------------------------------- |
| alias | string                   | `true`   | ​       | The alias for the subselect expression.        |
| query | Function \| QueryBuilder | `true`   |         | The callback or query to use in the subselect. |

The method lets you pass either a callback or a `QueryBuilder` instance to be used as a subselect expression. If a callback is passed it will be passed a new query instance as the only parameter.

The subselect is added to the other already selected columns.

{% code title="QueryBuilder" %}

```javascript
query.subSelect( "last_login_date", function( q ) {
    q.selectRaw( "MAX(created_date)" )
        .from( "logins" )
        .whereColumn( "users.id", "logins.user_id" );
} ) ).from( "users" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT (
    SELECT MAX(created_date)
    FROM `logins`
    WHERE `users`.`id` = `logins`.`user_id`
) AS `last_login_date`
FROM `users
```

{% endcode %}

## clearSelect <a href="#clearselect" id="clearselect"></a>

| Name         | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      | \`\`     |         |             |

Clears out the selected columns for a query along with any configured select bindings.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .select( [ "fname AS firstName", "age" ] )
    .clearSelect();
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT * FROM `users`
```

{% endcode %}

## reselect <a href="#reselect" id="reselect"></a>

| Name    | Type            | Required | Default | Description                                                        |
| ------- | --------------- | -------- | ------- | ------------------------------------------------------------------ |
| columns | string \| array | `false`  | ​`"*"`  | A single column, list of columns, or array of columns to retrieve. |

Clears out the selected columns for a query along with any configured select bindings. Then sets a selection of columns to select from the query. Any valid argument to [`select`](/12.1.0/query-builder/building-queries/selects#get) can be passed here.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .select( [ "fname AS firstName", "age" ] )
    .reselect( "username" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT `username` FROM `users`
```

{% endcode %}

## reselectRaw <a href="#reselectraw" id="reselectraw"></a>

| Name       | Type  | Required | Default | Description                                  |
| ---------- | ----- | -------- | ------- | -------------------------------------------- |
| expression | any   | `true`   | ​       | The raw expression for the select statement. |
| bindings   | array | `false`  | `[]`    | Any bindings needed for the raw expression.  |

Clears out the selected columns for a query along with any configured select bindings. Then adds an Expression or array of expressions to the already selected columns.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .select( [ "fname AS firstName", "age" ] )
    .reselectRaw( "YEAR(birthdate) AS birth_year" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT YEAR(birthdate) AS birth_year FROM `users`
```

{% endcode %}


# From

## from <a href="#from" id="from"></a>

| Name | Type                 | Required | Default | Description                                                                 |
| ---- | -------------------- | -------- | ------- | --------------------------------------------------------------------------- |
| from | string \| Expression | `true`   | ​       | The name of the table or a Expression object from which the query is based. |

Used to set the base table for the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT * FROM `users`
```

{% endcode %}

You can optionally specify an alias for the table.

{% code title="QueryBuilder" %}

```javascript
query.from( "users as u" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT * FROM `users` AS `u`
```

{% endcode %}

{% hint style="info" %}
A query does not need to have a table name specified.  If a query does not, it will be executed without a table (in the manner specified by the grammar).
{% endhint %}

## table <a href="#table" id="table"></a>

| Name  | Type                 | Required | Default | Description                                                                 |
| ----- | -------------------- | -------- | ------- | --------------------------------------------------------------------------- |
| table | string \| Expression | `true`   | ​       | The name of the table or a Expression object from which the query is based. |

An alias for `from` where you like how calling `table` looks.

{% code title="QueryBuilder" %}

```javascript
query.table( "users" ).insert( { "name" = "jon" } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
INSERT INTO `users` (`name`) VALUES (?)
```

{% endcode %}

## fromRaw <a href="#fromraw" id="fromraw"></a>

| Name     | Type   | Required | Default | Description                             |
| -------- | ------ | -------- | ------- | --------------------------------------- |
| from     | string | `true`   | ​       | The sql snippet to use as the table.    |
| bindings | array  | `false`  | `[]`    | Any bindings needed for the expression. |

Sometimes you need more control over your `from` clause in order to add grammar specific instructions, such as adding SQL Server table hints to your queries.

{% code title="QueryBuilder" %}

```javascript
query.fromRaw( "[users] u (nolock)" ).get();
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT * FROM [users] u (nolock) 
```

{% endcode %}

Since the `fromRaw()` takes your string verbatim, it's important that you make sure your SQL declaration is escaped properly. Failure to properly escape your table names may result in SQL errors.

{% hint style="warning" %}
Using `fromRaw` will most likely tie your code to a specific database, so think carefully before using the `fromRaw` method if you want your project to be database agnostic.
{% endhint %}

Many database engines allow you to define User Defined Functions. For example, SQL Server allows you to define UDFs that will return a table. In these type of cases, it may be necessary to bind parameters to your `from` clause.

You can bind parameters to the `fromRaw()` method by passing a secondary argument that is an array of the parameters to bind.

{% code title="QueryBuilder" %}

```javascript
query.fromRaw(
    "dbo.generateDateTable(?, ?, ?) as dt",
    [ "2017-01-01", "2017-12-31", "m" ]
).get();
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT * FROM dbo.generateDateTable(?, ?, ?) as dt
```

{% endcode %}

## fromSub <a href="#fromsub" id="fromsub"></a>

| Name  | Type                     | Required | Default | Description                                                                |
| ----- | ------------------------ | -------- | ------- | -------------------------------------------------------------------------- |
| alias | string                   | `true`   | ​       | The alias for the derived table.                                           |
| input | Function \| QueryBuilder | `true`   |         | Either a `QueryBuilder` instance or a closure to define the derived query. |

Complex queries often contain derived tables. Derived tables are essentially a temporal table defined as a subquery in the `from` statement.

{% code title="QueryBuilder" %}

```javascript
query.select( [ "firstName", "lastName" ] )
    .fromSub( "legalUsers", function ( q ) {
        q.select( [ "lName as lastName", "fName as firstName" ] )
            .from( "users" )
            .where( "age", ">=", 21 )
        ;
    } )
    .orderBy( "lastName" )
    .get()
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT `firstName`, `lastName`
FROM (
    SELECT `lName` as `lastName`, `fName` as `firstName`
    FROM `users`
    WHERE `age` >= 21
) AS `legalUsers`
ORDER BY `lastName`
```

{% endcode %}

In additional a function callback, a separate `QueryBuilder` instance can be passed to the `fromSub` method.

{% code title="QueryBuilder" %}

```javascript
var legalUsersQuery = query
    .select( [ "lName as lastName", "fName as firstName" ] )
    .from( "users" )
    .where( "age", ">=", 21 );

query.select( [ "firstName", "lastName" ] )
    .fromSub( "legalUsers", legalUsersQuery )
    .orderBy( "lastName" )
    .get();
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT `firstName`, `lastName`
FROM (
    SELECT `lName` as `lastName`, `fName` as `firstName`
    FROM `users`
    WHERE `age` >= 21
) AS `legalUsers`
ORDER BY `lastName`
```

{% endcode %}

## withAlias

<table><thead><tr><th>Name</th><th>Type</th><th data-type="checkbox">Required</th><th>Default Value</th><th>Description</th></tr></thead><tbody><tr><td>alias</td><td><code>string</code></td><td>true</td><td></td><td>The new alias to use for the table.</td></tr></tbody></table>

Adds an alias to the specified `from` table or renames a current alias.  Any existing aliased values in `columns`, `wheres`, `joins`, `groupBys`, or `orders` that match the previous alias will be remapped to the new alias.  This includes the full table name when used as an alias.

```cfscript
qb.from( "users" ).select( [ "users.name", "birthdate" ] );
// SELECT "users"."name", "birthdate" FROM "users"
qb.withAlias( "u1" );
// SELECT "u1"."name", "birthdate" FROM "users" AS "u1"
```


# For

{% hint style="warning" %}
This section only applies to SQL Server Grammars.
{% endhint %}

In SQL Server, `FOR` clauses are how you can return JSON or XML directly from your query.

In qb, only raw expressions are accepted via the `forRaw` method.

## forRaw

<table><thead><tr><th width="147.90625">Name</th><th width="121.19921875">Type</th><th width="80.03125">Required</th><th width="89.56640625">Default</th><th>Description</th></tr></thead><tbody><tr><td>expression</td><td>string</td><td>true</td><td></td><td>The raw sql for the <code>FOR</code> clause.</td></tr></tbody></table>

{% code title="QueryBuilder" %}

```javascript
query
    .select( [ "id", "name" ] )
    .from( "users" )
    .forRaw( "JSON AUTO" );
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT [id], [name]
FROM [users]
FOR JSON AUTO
```

{% endcode %}


# Joins

Join clauses range from simple to complex including joining complete subqueries on multiple conditions. qb has your back with all of these use cases.

| Table of Contents                                                   |                                                                           |                                                                           |                                                                       |
| ------------------------------------------------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------- |
| [join](/12.1.0/query-builder/building-queries/joins#join)           | [joinRaw](/12.1.0/query-builder/building-queries/joins#joinraw)           | [joinSub](/12.1.0/query-builder/building-queries/joins#joinsub)           | [joinWhere](/12.1.0/query-builder/building-queries/joins#joinwhere)   |
| [leftJoin](/12.1.0/query-builder/building-queries/joins#leftjoin)   | [leftJoinRaw](/12.1.0/query-builder/building-queries/joins#leftjoinraw)   | [leftJoinSub](/12.1.0/query-builder/building-queries/joins#leftjoinsub)   | [newJoin](/12.1.0/query-builder/building-queries/joins#newjoin)       |
| [rightJoin](/12.1.0/query-builder/building-queries/joins#get)       | [rightJoinRaw](/12.1.0/query-builder/building-queries/joins#rightjoinraw) | [rightJoinSub](/12.1.0/query-builder/building-queries/joins#rightjoinsub) | [JoinClause](/12.1.0/query-builder/building-queries/joins#joinclause) |
| [crossJoin](/12.1.0/query-builder/building-queries/joins#crossjoin) | [crossJoinRaw](/12.1.0/query-builder/building-queries/joins#crossjoinraw) | [crossJoinSub](/12.1.0/query-builder/building-queries/joins#crossjoinsub) |                                                                       |

## join <a href="#join" id="join"></a>

| Name     | Type                                                                                                                                                    | Required | Default   | Description                                                                                                                                                                                                                                                               |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| table    | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) \| [JoinClause](/12.1.0/query-builder/building-queries/joins#joinclause) | `true`   | ​         | The name of the table or a [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) object from which the query is based.  Alternatively, a configured [`JoinClause`](/12.1.0/query-builder/building-queries/joins#joinclause) instance can be passed.      |
| first    | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) \| Function                                                              | `false`  |           | The first column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) to join the table on.  Alternatively, a function can be passed to configure complex join statements.                                                                           |
| operator | string                                                                                                                                                  | `false`  | `"="`     | The boolean operator for the join clause.                                                                                                                                                                                                                                 |
| second   | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions)                                                                          | `false`  |           | The second column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) to join the table on.                                                                                                                                                         |
| type     | string                                                                                                                                                  | `false`  | `"inner"` | The type of the join.  Passing this as an argument is discouraged for readability. Use the dedicated methods like [`leftJoin`](/12.1.0/query-builder/building-queries/joins#leftjoin) and [`rightJoin`](/12.1.0/query-builder/building-queries/joins#get) where possible. |
| where    | boolean                                                                                                                                                 | `false`  | `false`   | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use the dedicated [`joinWhere`](/12.1.0/query-builder/building-queries/joins#joinwhere) or a join closure where possible.                         |

Applies a join to the query. The simplest join is to a table based on two columns:

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .join( "posts", "users.id", "=", "posts.author_id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
```

{% endcode %}

When doing a simple join using `=` as the operator, you can omit it and pass just the column names:

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .join( "posts", "users.id", "posts.author_id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
```

{% endcode %}

\`\`[`Expressions`](/12.1.0/query-builder/building-queries/raw-expressions) are also supported as the `table` argument (though you may prefer the readability of the [`joinRaw`](/12.1.0/query-builder/building-queries/joins#joinraw) method):

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .join( query.raw( "posts (nolock)" ), "users.id", "=", "posts.author_id" );
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT *
FROM [users]
JOIN posts (nolock)
  ON [users].[id] = [posts].[author_id]
```

{% endcode %}

{% hint style="warning" %}
Using `raw` will most likely tie your code to a specific database, so think carefully before using the `raw` method if you want your project to be database agnostic.
{% endhint %}

When you need to specify more clauses to join, you can pass a function as the second argument:

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .join( "posts", function( j ) {
        j.on( "users.id", "=", "posts.author_id" );
        j.on( "users.prefix", "=", "posts.prefix" );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
  AND `users`.`prefix` = `posts`.`prefix`
```

{% endcode %}

You can specify [`where`](/12.1.0/query-builder/building-queries/wheres) clauses in your joins as well.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .join( "posts", function( j ) {
        j.on( "users.id", "=", "posts.author_id" );
        j.whereNotNull( "posts.published_date" );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
  AND `posts`.`published_date` IS NOT NULL
```

{% endcode %}

Conditions inside a join clause can be grouped using a function.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .join( "posts", function( j ) {
        j.on( function( j1 ) {
            j1.on( "users.id", "posts.author_id" )
                .orOn( "users.id", "posts.reviewer_id" );
        } );
        j.whereNotNull( "posts.published_date" );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON (
      `users`.`id` = `posts`.`author_id`
      OR `users`.`id` = `posts`.`reviewer_id`
  )
  AND `posts`.`published_date` IS NOT NULL
```

{% endcode %}

A preconfigured [`JoinClause`](/12.1.0/query-builder/building-queries/joins#joinclause) can also be passed to the join function. This allows you to extract shared pieces of code out to different functions.

{% code title="QueryBuilder" %}

```javascript
var j = query.newJoin( "contacts" )
    .on( "users.id", "posts.author_id" );

query.from( "users" ).join( j );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
```

{% endcode %}

## joinWhere <a href="#joinwhere" id="joinwhere"></a>

| Name     | Type                                                                                       | Required | Default   | Description                                                                                                                                                                                                                                                                                    |
| -------- | ------------------------------------------------------------------------------------------ | -------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| table    | string                                                                                     | `true`   | ​         | The raw SQL string to use as the table.                                                                                                                                                                                                                                                        |
| first    | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) \| Function | `false`  |           | The first column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) to join the table on.  Alternatively, a function can be passed to configure complex join statements.                                                                                                |
| operator | string                                                                                     | `false`  | `"="`     | The boolean operator for the join clause.                                                                                                                                                                                                                                                      |
| second   | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions)             | `false`  |           | The second column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) to join the table on.                                                                                                                                                                              |
| type     | string                                                                                     | `false`  | `"inner"` | The type of the join.  Passing this as an argument is discouraged for readability. Use the dedicated methods like [`leftJoin`](/12.1.0/query-builder/building-queries/joins#leftjoin) and [`rightJoin`](/12.1.0/query-builder/building-queries/joins#get) with a join function where possible. |

Adds a join to another table based on a `WHERE` clause instead of an `ON` clause. `WHERE` clauses introduce parameters and parameter bindings whereas `on` clauses join between columns and don't need parameter bindings.

For simple joins, this specifies a column on which to join the two tables:

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .joinWhere( "contacts", "contacts.balance", "<", 100 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `contacts`
  WHERE `contacts`.`balance` < ?
```

{% endcode %}

For complex joins, a function can be passed to `first`. This allows multiple `on` and `where` conditions to be applied to the join. See the documentation for [`join`](/12.1.0/query-builder/building-queries/joins#join) for more information.

## joinRaw <a href="#joinraw" id="joinraw"></a>

| Name     | Type                                                                                       | Required | Default   | Description                                                                                                                                                                                                                                                                                 |
| -------- | ------------------------------------------------------------------------------------------ | -------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| table    | string                                                                                     | `true`   | ​         | The raw SQL string to use as the table.                                                                                                                                                                                                                                                     |
| first    | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) \| Function | `false`  |           | The first column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) to join the table on.  Alternatively, a function can be passed to configure complex join statements.                                                                                             |
| operator | string                                                                                     | `false`  | `"="`     | The boolean operator for the join clause.                                                                                                                                                                                                                                                   |
| second   | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions)             | `false`  |           | The second column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) to join the table on.                                                                                                                                                                           |
| type     | string                                                                                     | `false`  | `"inner"` | The type of the join.  Passing this as an argument is discouraged for readability. Use the dedicated methods like [`leftJoinRaw`](/12.1.0/query-builder/building-queries/joins#leftjoinraw) and [`rightJoinRaw`](/12.1.0/query-builder/building-queries/joins#rightjoinraw) where possible. |
| where    | boolean                                                                                    | `false`  | `false`   | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use a closure to define the where clauses where possible.                                                                                                           |

Uses the raw SQL provided to as the table for the join clause. All the other functionality of `joinRaw` matches the [`join`](/12.1.0/query-builder/building-queries/joins#join) method. Additionally, there are [`leftJoinRaw`](/12.1.0/query-builder/building-queries/joins#leftjoinraw), [`rightJoinRaw`](/12.1.0/query-builder/building-queries/joins#rightjoinraw), and `crossJoinRaw` methods available.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .joinRaw( "posts (nolock)", "users.id", "posts.author_id" );
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT *
FROM [users]
JOIN posts (nolock)
  ON [users].[id] = [posts].[author_id]
```

{% endcode %}

{% hint style="warning" %}
Using `joinRaw` will most likely tie your code to a specific database, so think carefully before using the `joinRaw` method if you want your project to be database agnostic.
{% endhint %}

## joinSub <a href="#joinsub" id="joinsub"></a>

| Name     | Type                                                                                       | Required | Default   | Description                                                                                                                                                                                                                                                                                 |
| -------- | ------------------------------------------------------------------------------------------ | -------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| alias    | string                                                                                     | `true`   |           | The alias for the derived table.                                                                                                                                                                                                                                                            |
| input    | Function \| QueryBuilder                                                                   | `true`   | ​         | Either a `QueryBuilder` instance or a function to define the derived query.                                                                                                                                                                                                                 |
| first    | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) \| Function | `true`   |           | The first column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) to join the table on.  Alternatively, a function can be passed to configure complex join statements.                                                                                             |
| operator | string                                                                                     | `false`  | `"="`     | The boolean operator for the join clause.                                                                                                                                                                                                                                                   |
| second   | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions)             | `false`  |           | The second column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) to join the table on.                                                                                                                                                                           |
| type     | string                                                                                     | `false`  | `"inner"` | The type of the join.  Passing this as an argument is discouraged for readability. Use the dedicated methods like [`leftJoinSub`](/12.1.0/query-builder/building-queries/joins#leftjoinsub) and [`rightJoinSub`](/12.1.0/query-builder/building-queries/joins#rightjoinsub) where possible. |
| where    | boolean                                                                                    | `false`  | `false`   | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use a closure to define the where clauses where possible.                                                                                                           |

Adds a join to a derived table. All the functionality of the [`join`](/12.1.0/query-builder/building-queries/joins#join) method applies to constrain the query. The derived table can be defined using a `QueryBuilder` instance:

{% code title="QueryBuilder" %}

```javascript
var sub = query.newQuery()
    .select( "id" )
    .from( "contacts" )
    .whereNotIn( "id", [ 1, 2, 3 ] );

query.from( "users as u" )
    .joinSub( "c", sub, "u.id", "=", "c.id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users` AS `u`
JOIN (
  SELECT `id`
  FROM `contacts`
  WHERE `id` NOT IN (?, ?, ?)
) AS `c`
  ON `u`.`id` = `c`.`id`
```

{% endcode %}

Alternatively, a function may be used to define the derived table:

{% code title="QueryBuilder" %}

```javascript
query.from( "users as u" )
    .joinSub( "c", function ( q ) {
        q.select( "id" )
            .from( "contacts" )
            .whereNotIn( "id", [ 1, 2, 3 ] );
    }, "u.id", "=", "c.id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users` AS `u`
JOIN (
  SELECT `id`
  FROM `contacts`
  WHERE `id` NOT IN (?, ?, ?)
) AS `c`
  ON `u`.`id` = `c`.`id`
```

{% endcode %}

Complex join conditions are also possible by passing a function as the third parameter:

{% code title="QueryBuilder" %}

```javascript
query.from( "users as u" )
    .joinSub( "c", function ( q ) {
        q.select( "id" )
            .from( "contacts" )
            .whereNotIn( "id", [ 1, 2, 3 ] );
    }, function( j ) {
        j.on( "u.id", "c.id" );
        j.on( "u.type", "c.type" );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users` AS `u`
JOIN (
  SELECT `id`
  FROM `contacts`
  WHERE `id` NOT IN (?, ?, ?)
) AS `c`
  ON `u`.`id` = `c`.`id`
  AND `u`.`type` = `c`.`type`
```

{% endcode %}

## leftJoin <a href="#leftjoin" id="leftjoin"></a>

| Name | Type | Required | Default | Description |
| ---- | ---- | -------- | ------- | ----------- |

| table | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) \| [JoinClause](/12.1.0/query-builder/building-queries/joins#joinclause) | `true` | ​ | <p>The name of the table or a <a href="/pages/-LqPwKuMTnx51m1fvv9o"><code>Expression</code></a> object from which the query is based. Alternatively, a configured <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance can be passed.</p><p>(Note: a <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance may have a different join type than a <code>left</code> join. The <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance's join type will be used.)</p> |
| ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

| first | string \| Expression \| Function | `false` |   | The first column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) to join the table on. Alternatively, a function can be passed to configure complex join statements. |
| ----- | -------------------------------- | ------- | - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

| operator | string | `false` | `"="` | The boolean operator for the join clause. |
| -------- | ------ | ------- | ----- | ----------------------------------------- |

| second | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) | `false` |   | The second column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) to join the table on. |
| ------ | ------------------------------------------------------------------------------ | ------- | - | ----------------------------------------------------------------------------------------------------------------- |

| where | boolean | `false` | `false` | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use a closure to define the where clauses where possible. |
| ----- | ------- | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

{% code title="QueryBuilder" %}

```javascript
query.from( "posts" )
    .leftJoin( "users", "users.id", "posts.author_id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `posts`
LEFT JOIN `users`
  ON `users`.`id` = `posts`.`author_id`
```

{% endcode %}

## leftJoinRaw <a href="#leftjoinraw" id="leftjoinraw"></a>

| Name     | Type                                                                                       | Required | Default | Description                                                                                                                                                                                     |
| -------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| table    | string                                                                                     | `true`   | ​       | The raw SQL string to use as the table.                                                                                                                                                         |
| first    | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) \| Function | `false`  |         | The first column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) to join the table on.  Alternatively, a function can be passed to configure complex join statements. |
| operator | string                                                                                     | `false`  | `"="`   | The boolean operator for the join clause.                                                                                                                                                       |
| second   | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The second column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) to join the table on.                                                                               |
| where    | boolean                                                                                    | `false`  | `false` | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use a closure to define the where clauses where possible.               |

Uses the raw SQL provided to as the table for the left join clause. All the other functionality of `leftJoinRaw` matches the [`join`](/12.1.0/query-builder/building-queries/joins#join) method.

{% code title="QueryBuilder" %}

```javascript
query.from( "posts" )
    .leftJoinRaw( "users (nolock)", "users.id", "posts.author_id" );
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT *
FROM [posts]
LEFT JOIN users (nolock)
  ON [users].[id] = [posts].[author_id]
```

{% endcode %}

{% hint style="warning" %}
Using `leftJoinRaw` will most likely tie your code to a specific database, so think carefully before using the `leftJoinRaw` method if you want your project to be database agnostic.
{% endhint %}

## leftJoinSub <a href="#leftjoinsub" id="leftjoinsub"></a>

| Name     | Type                                                                                       | Required | Default | Description                                                                                                                                                                                     |
| -------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| alias    | string                                                                                     | `true`   |         | The alias for the derived table.                                                                                                                                                                |
| input    | Function \| QueryBuilder                                                                   | `true`   | ​       | Either a `QueryBuilder` instance or a function to define the derived query.                                                                                                                     |
| first    | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) \| Function | `true`   |         | The first column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) to join the table on.  Alternatively, a function can be passed to configure complex join statements. |
| operator | string                                                                                     | `false`  | `"="`   | The boolean operator for the join clause.                                                                                                                                                       |
| second   | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The second column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) to join the table on.                                                                               |
| where    | boolean                                                                                    | `false`  | `false` | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use a closure to define the where clauses where possible.               |

Adds a left join to a derived table. All the functionality of the [`joinSub`](/12.1.0/query-builder/building-queries/joins#joinsub) method applies to define and constrain the query.

{% code title="QueryBuilder" %}

```javascript
var sub = query.newQuery()
    .select( "id" )
    .from( "contacts" )
    .whereNotIn( "id", [ 1, 2, 3 ] );

query.from( "users as u" )
    .leftJoinSub( "c", sub, "u.id", "=", "c.id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users` AS `u`
LEFT JOIN (
  SELECT `id`
  FROM `contacts`
  WHERE `id` NOT IN (?, ?, ?)
) AS `c`
  ON `u`.`id` = `c`.`id`
```

{% endcode %}

## rightJoin <a href="#get" id="get"></a>

| Name | Type | Required | Default | Description |
| ---- | ---- | -------- | ------- | ----------- |

| table | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) \| [JoinClause](/12.1.0/query-builder/building-queries/joins#joinclause) | `true` | ​ | <p>The name of the table or a <a href="/pages/-LqPwKuMTnx51m1fvv9o"><code>Expression</code></a> object from which the query is based. Alternatively, a configured <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance can be passed.</p><p>(Note: a <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance may have a different join type than a <code>right</code> join. The <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance's join type will be used.)</p> |
| ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

| first | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) \| Function | `false` |   | The first column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) to join the table on. Alternatively, a function can be passed to configure complex join statements. |
| ----- | ------------------------------------------------------------------------------------------ | ------- | - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

| operator | string | `false` | `"="` | The boolean operator for the join clause. |
| -------- | ------ | ------- | ----- | ----------------------------------------- |

| second | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) | `false` |   | The second column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) to join the table on. |
| ------ | ------------------------------------------------------------------------------ | ------- | - | ----------------------------------------------------------------------------------------------------------------- |

| where | boolean | `false` | `false` | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use a closure to define the where clauses where possible. |
| ----- | ------- | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .rightJoin( "posts", "users.id", "posts.author_id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
RIGHT JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
```

{% endcode %}

## rightJoinRaw <a href="#rightjoinraw" id="rightjoinraw"></a>

| Name     | Type                                                                                       | Required | Default | Description                                                                                                                                                                                     |
| -------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| table    | string                                                                                     | `true`   | ​       | The raw SQL string to use as the table.                                                                                                                                                         |
| first    | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) \| Function | `false`  |         | The first column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) to join the table on.  Alternatively, a function can be passed to configure complex join statements. |
| operator | string                                                                                     | `false`  | `"="`   | The boolean operator for the join clause.                                                                                                                                                       |
| second   | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The second column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) to join the table on.                                                                               |
| where    | boolean                                                                                    | `false`  | `false` | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use a closure to define the where clauses where possible.               |

Uses the raw SQL provided to as the table for the right join clause. All the other functionality of `rightJoinRaw` matches the [`join`](/12.1.0/query-builder/building-queries/joins#join) method.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .rightJoinRaw( "posts (nolock)", "users.id", "posts.author_id" );
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT *
FROM [users]
LEFT JOIN posts (nolock)
  ON [users].[id] = [posts].[author_id]
```

{% endcode %}

{% hint style="warning" %}
Using `rightJoinRaw` will most likely tie your code to a specific database, so think carefully before using the `rightJoinRaw` method if you want your project to be database agnostic.
{% endhint %}

## rightJoinSub <a href="#rightjoinsub" id="rightjoinsub"></a>

| Name     | Type                                                                                       | Required | Default | Description                                                                                                                                                                                     |
| -------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| alias    | string                                                                                     | `true`   |         | The alias for the derived table.                                                                                                                                                                |
| input    | Function \| QueryBuilder                                                                   | `true`   | ​       | Either a `QueryBuilder` instance or a function to define the derived query.                                                                                                                     |
| first    | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) \| Function | `true`   |         | The first column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) to join the table on.  Alternatively, a function can be passed to configure complex join statements. |
| operator | string                                                                                     | `false`  | `"="`   | The boolean operator for the join clause.                                                                                                                                                       |
| second   | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The second column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) to join the table on.                                                                               |
| where    | boolean                                                                                    | `false`  | `false` | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use a closure to define the where clauses where possible.               |

Adds a right join to a derived table. All the functionality of the [`joinSub`](/12.1.0/query-builder/building-queries/joins#joinsub) method applies to define and constrain the query.

{% code title="QueryBuilder" %}

```javascript
var sub = query.newQuery()
    .select( "id" )
    .from( "contacts" )
    .whereNotIn( "id", [ 1, 2, 3 ] );

query.from( "users as u" )
    .rightJoinSub( "c", sub, "u.id", "=", "c.id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users` AS `u`
RIGHT JOIN (
  SELECT `id`
  FROM `contacts`
  WHERE `id` NOT IN (?, ?, ?)
) AS `c`
  ON `u`.`id` = `c`.`id`
```

{% endcode %}

## crossJoin <a href="#crossjoin" id="crossjoin"></a>

| Name | Type | Required | Default | Description |
| ---- | ---- | -------- | ------- | ----------- |

| table | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) \| [JoinClause](/12.1.0/query-builder/building-queries/joins#joinclause) | `true` | ​ | <p>The name of the table or a <a href="/pages/-LqPwKuMTnx51m1fvv9o"><code>Expression</code></a> object from which the query is based. Alternatively, a configured <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance can be passed.</p><p>(Note: a <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance may have a different join type than a <code>cross</code> join. The <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance's join type will be used.)</p> |
| ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).crossJoin( "posts" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
CROSS JOIN `posts`
```

{% endcode %}

## crossJoinRaw <a href="#crossjoinraw" id="crossjoinraw"></a>

| Name  | Type   | Required | Default | Description                             |
| ----- | ------ | -------- | ------- | --------------------------------------- |
| table | string | `true`   | ​       | The raw SQL string to use as the table. |

Uses the raw SQL provided to as the table for the cross join clause. Cross joins cannot be further constrained with `on` or `where` clauses.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).crossJoinRaw( "posts (nolock)" );
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT *
FROM [users]
CROSS JOIN posts (nolock)
```

{% endcode %}

{% hint style="warning" %}
Using `crossJoinRaw` will most likely tie your code to a specific database, so think carefully before using the `crossJoinRaw` method if you want your project to be database agnostic.
{% endhint %}

## crossJoinSub <a href="#crossjoinsub" id="crossjoinsub"></a>

| Name  | Type                     | Required | Default | Description                                                                 |
| ----- | ------------------------ | -------- | ------- | --------------------------------------------------------------------------- |
| alias | string                   | `true`   |         | The alias for the derived table.                                            |
| input | Function \| QueryBuilder | `true`   | ​       | Either a `QueryBuilder` instance or a function to define the derived query. |

Adds a cross join to a derived table. The derived table can be defined using a `QueryBuilder` instance or a function just as with [`joinSub`](/12.1.0/query-builder/building-queries/joins#joinsub). Cross joins cannot be constrained, however.

{% code title="QueryBuilder" %}

```javascript
var sub = query.newQuery()
    .select( "id" )
    .from( "contacts" )
    .whereNotIn( "id", [ 1, 2, 3 ] );

query.from( "users as u" ).crossJoinSub( "c", sub );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users` AS `u`
CROSS JOIN (
  SELECT `id`
  FROM `contacts`
  WHERE `id` NOT IN (?, ?, ?)
)
```

{% endcode %}

## crossApply <a href="#crossapply" id="crossapply"></a>

| Name     | Type                         | Required | Default | Description                                                                                   |
| -------- | ---------------------------- | -------- | ------- | --------------------------------------------------------------------------------------------- |
| name     | string                       | `true`   |         | The name for the cross apply table                                                            |
| tableDef | `function` \| `QueryBuilder` | `true`   |         | A QueryBuilder instance or a function that accepts a new query builder instance to configure. |

Adds a cross apply join using a derived table. The derived table can be defined using a `QueryBuilder` instance or a function just as with [`joinSub`](/12.1.0/query-builder/building-queries/joins#joinsub).

{% code title="QueryBuilder" %}

```javascript
qb.from( "users as u" )
    .select( [ "u.ID", "childCount.c" ] )
    .crossApply( "childCount", function( qb ) {
        qb.selectRaw( "count(*) c" )
            .from( "children" )
            .whereColumn( "children.parentID", "=", "users.ID" )
            .where( "children.someCol", "=", 0 );
    } )
    .where( "childCount.c", ">", 1 )
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT
    [u].[ID],
    [childCount].[c]
FROM [users] AS [u]
CROSS APPLY (
    SELECT count(*) c
    FROM [children]
    WHERE [children].[parentID] = [users].[ID]
    AND [children].[someCol] = ?
) AS [childCount]
WHERE [childCount].[c] > ?
```

{% endcode %}

## outerApply <a href="#outerapply" id="outerapply"></a>

| Name     | Type                         | Required | Default | Description                                                                                   |
| -------- | ---------------------------- | -------- | ------- | --------------------------------------------------------------------------------------------- |
| name     | string                       | `true`   |         | The name for the cross apply table                                                            |
| tableDef | `function` \| `QueryBuilder` | `true`   |         | A QueryBuilder instance or a function that accepts a new query builder instance to configure. |

Adds a outer apply join using a derived table. The derived table can be defined using a `QueryBuilder` instance or a function just as with [`joinSub`](/12.1.0/query-builder/building-queries/joins#joinsub).

{% code title="QueryBuilder" %}

```javascript
qb.from( "users as u" )
    .select( [ "u.ID", "childCount.c" ] )
    .outerApply( "childCount", function( qb ) {
        qb.selectRaw( "count(*) c" )
            .from( "children" )
            .whereColumn( "children.parentID", "=", "users.ID" )
            .where( "children.someCol", "=", 0 );
    } )
    .where( "childCount.c", ">", 1 )
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT
    [u].[ID],
    [childCount].[c]
FROM [users] AS [u]
OUTER APPLY (
    SELECT count(*) c
    FROM [children]
    WHERE [children].[parentID] = [users].[ID]
    AND [children].[someCol] = ?
) AS [childCount]
WHERE [childCount].[c] > ?
```

{% endcode %}

## newJoin <a href="#newjoin" id="newjoin"></a>

| Name  | Type                                                                           | Required | Default   | Description                                                                                                                             |
| ----- | ------------------------------------------------------------------------------ | -------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| table | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) | `true`   | ​         | The name of the table or a [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) object from which the query is based. |
| type  | string                                                                         | `false`  | `"inner"` | The type of the join.  Valid types are `inner`, `left`, `right`, or `cross`.                                                            |

Creates a new [`JoinClause`](/12.1.0/query-builder/building-queries/joins#joinclause). A [`JoinClause`](/12.1.0/query-builder/building-queries/joins#joinclause) is a specialized version of a `QueryBuilder`. You may call `on` or `orOn` to constrain the [`JoinClause`](/12.1.0/query-builder/building-queries/joins#joinclause). You may also call any [`where`](/12.1.0/query-builder/building-queries/wheres) methods.

Creating a [`JoinClause`](/12.1.0/query-builder/building-queries/joins#joinclause) directly is useful when you need to share a join between different queries. You can create and configure the [`JoinClause`](/12.1.0/query-builder/building-queries/joins#joinclause) in a function and pass it to queries as needed.

{% code title="QueryBuilder" %}

```javascript
var j = query.newJoin( "contacts" )
    .on( "users.id", "posts.author_id" );

query.from( "users" ).join( j );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
```

{% endcode %}

{% hint style="warning" %}
Although a [`JoinClause`](/12.1.0/query-builder/building-queries/joins#joinclause) can be passed to [`join`](/12.1.0/query-builder/building-queries/joins#join), [`leftJoin`](/12.1.0/query-builder/building-queries/joins#leftjoin), [`rightJoin`](/12.1.0/query-builder/building-queries/joins#get), and `crossJoin`, the type of the [`JoinClause`](/12.1.0/query-builder/building-queries/joins#joinclause) will override the type of the function.
{% endhint %}

{% code title="QueryBuilder" %}

```javascript
// This is still an inner join because
// the JoinClause is an inner join
var j = query.newJoin( "contacts", "inner" )
    .on( "users.id", "posts.author_id" );

query.from( "users" ).leftJoin( j );
```

{% endcode %}

{% code title="MySQL" %}

```sql
-- This is still an inner join because
-- the JoinClause is an inner join
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
```

{% endcode %}

## JoinClause

A `JoinClause` is a specialized version of a `QueryBuilder`. You may call `on` or `orOn` to constrain the `JoinClause`. You may also call any [`where`](/12.1.0/query-builder/building-queries/wheres) methods.

### on

| Name       | Type                                                                                       | Required | Default | Description                                                                                                                                                                               |
| ---------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| first      | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) \| Function | `false`  |         | The first column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions)of the condition.  Alternatively, a function can be passed to nest conditions with parenthesis. |
| operator   | string                                                                                     | `false`  | `"="`   | The boolean operator for the condition.                                                                                                                                                   |
| second     | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The second column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) of the condition.                                                                             |
| combinator | string                                                                                     | `false`  | `"and"` | The boolean combinator for the clause (e.g. "and" or "or").                                                                                                                               |

Applies a join condition to the `JoinClause`. An alias for `whereColumn`.

{% code title="QueryBuilder" %}

```javascript
var j = query.newJoin( "contacts" )
    .on( "users.id", "posts.author_id" );

query.from( "users" ).join( j );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
```

{% endcode %}

### orOn

| Name     | Type                                                                                       | Required | Default | Description                                                                                                                                                                               |
| -------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| first    | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) \| Function | `false`  |         | The first column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions)of the condition.  Alternatively, a function can be passed to nest conditions with parenthesis. |
| operator | string                                                                                     | `false`  | `"="`   | The boolean operator for the condition.                                                                                                                                                   |
| second   | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The second column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) of the condition.                                                                             |

Applies a join condition to the `JoinClause` using an `or` combinator. An alias for `orWhereColumn`.

{% code title="QueryBuilder" %}

```javascript
var j = query.newJoin( "contacts" )
    .on( "users.id", "posts.author_id" )
    .orOn( "users.id", "posts.reviewer_id" );

query.from( "users" ).join( j );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
  OR `users`.`id` = `posts`.`reviewer_id`
```

{% endcode %}

## Preventing Duplicate Joins

You can optionally configure qb to ignore duplicate joins.  With this setting turned on each `JoinClause` is inspected and checked if it matches any existing `JoinClause` instances on the query.  This is useful if you have a table shared between optional constraints and want to ensure it is only added once.

You can opt-in to this behavior by setting `preventDuplicateJoins = true` in your `moduleSettings` in `config/ColdBox.cfc`.

```javascript
moduleSettings = {
    "qb": {
         "preventDuplicateJoins": true  
    }
};
```


# Wheres

| Table of Contents                                                          |                                                                                  |                                                                          |
| -------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| [where](/12.1.0/query-builder/building-queries/wheres#where)               | [andWhere](/12.1.0/query-builder/building-queries/wheres#andwhere)               | [orWhere](/12.1.0/query-builder/building-queries/wheres#orwhere)         |
| [whereBetween](/12.1.0/query-builder/building-queries/wheres#wherebetween) | [whereNotBetween](/12.1.0/query-builder/building-queries/wheres#wherenotbetween) | [whereColumn](/12.1.0/query-builder/building-queries/wheres#wherecolumn) |
| [whereExists](/12.1.0/query-builder/building-queries/wheres#whereexists)   | [whereNotExists](/12.1.0/query-builder/building-queries/wheres#wherenotexists)   | [whereLike](/12.1.0/query-builder/building-queries/wheres#wherelike)     |
| [whereIn](/12.1.0/query-builder/building-queries/wheres#wherein)           | [whereNotIn](/12.1.0/query-builder/building-queries/wheres#wherenotin)           | [whereRaw](/12.1.0/query-builder/building-queries/wheres#whereraw)       |
| [whereNull](/12.1.0/query-builder/building-queries/wheres#wherenull)       | [whereNotNull](/12.1.0/query-builder/building-queries/wheres#wherenotnull)       |                                                                          |

## Where Methods

### where

| Name       | Type                                                                                       | Required | Default | Description                                                                                                                                                                                                                                                                                                 |
| ---------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) \| Function | `true`   |         | The name of the column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) with which to constrain the query. A function can be passed to begin a nested where statement.                                                                                                             |
| operator   | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The operator to use for the constraint (i.e. "=", "<", ">=", etc.). A value can be passed as the `operator` and the `value` left null as a shortcut for equals (e.g. where( "column", 1 ) == where( "column", "=", 1 ) ).                                                                                   |
| value      | any                                                                                        | `false`  |         | The value with which to constrain the column.  An [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) can be passed as well.  If a QueryBuilder or Function is passed, it will be used as a subselect expression.                                                                        |
| combinator | string                                                                                     | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the [`andWhere`](/12.1.0/query-builder/building-queries/wheres#andwhere) and [`orWhere`](/12.1.0/query-builder/building-queries/wheres#orwhere) methods instead. |

Adds a where clause to a query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "active", "=", 1 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `active` = ?
```

{% endcode %}

{% hint style="info" %}
Using the `where` method will parameterize the `value` passed.  If you want to constrain a column to another column, use the [`whereColumn`](/12.1.0/query-builder/building-queries/wheres#wherecolumn) method.
{% endhint %}

You can also pass an [Expression](/12.1.0/query-builder/building-queries/raw-expressions) as the value.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "last_logged_in", ">", query.raw( "NOW()" ) );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `last_logged_in` > NOW()
```

{% endcode %}

Any of the following operators can be used in a where clause.

| Valid Operators |                |             |
| --------------- | -------------- | ----------- |
| =               | <              | >           |
| <=              | >=             | <>          |
| !=              | like           | like binary |
| not like        | between        | ilike       |
| &               | \|             | ^           |
| <<              | >>             | rlike       |
| regexp          | not regexp     | \~          |
| \~\*            | !\~            | !\~\*       |
| similar to      | not similar to |             |

When using the `"="` constraint, you can use a shortcut and define the value as the second argument.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "active", 1 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `active` = ?
```

{% endcode %}

{% hint style="info" %}
You may also use [dynamic where{Column}](/12.1.0/query-builder/building-queries/wheres#dynamic-where-methods) statements to simplify this further.
{% endhint %}

To group where statements together, pass a function to the where clause as the only parameter.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( function( q ) {
        q.where( "active", 1 )
            .where( "last_logged_in", ">", dateAdd( "ww", -1, now() ) )
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE (
    `active` = ?
    AND
    `last_logged_in` > ?
)
```

{% endcode %}

{% hint style="info" %}
This grouping can be nested as many levels as you require.
{% endhint %}

A Function or QueryBuilder can be used as a subselect expression when passed to `value`.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "email", "foo" )
    .orWhere( "id", "=", function( q ) {
        q.select( q.raw( "MAX(id)" ) )
            .from( "users" )
            .where( "email", "bar" );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `email` = ?
  OR `id` = (
    SELECT MAX(id)
    FROM `users`
    WHERE `email` = ?
  )
```

{% endcode %}

### andWhere

| Name     | Type                                                                                       | Required | Default | Description                                                                                                                                                                                                                          |
| -------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| column   | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) \| Function | `true`   |         | The name of the column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) with which to constrain the query. A function can be passed to begin a nested where statement.                                      |
| operator | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The operator to use for the constraint (i.e. "=", "<", ">=", etc.). A value can be passed as the `operator` and the `value` left null as a shortcut for equals (e.g. where( "column", 1 ) == where( "column", "=", 1 ) ).            |
| value    | any                                                                                        | `false`  |         | The value with which to constrain the column.  An [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) can be passed as well.  If a QueryBuilder or Function is passed, it will be used as a subselect expression. |

This method is simply an alias for [`where`](/12.1.0/query-builder/building-queries/wheres#where) with the combinator set to `"and"`.

### orWhere

| Name     | Type                                                                                       | Required | Default | Description                                                                                                                                                                                                                          |
| -------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| column   | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) \| Function | `true`   |         | The name of the column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) with which to constrain the query. A function can be passed to begin a nested where statement.                                      |
| operator | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The operator to use for the constraint (i.e. "=", "<", ">=", etc.). A value can be passed as the `operator` and the `value` left null as a shortcut for equals (e.g. where( "column", 1 ) == where( "column", "=", 1 ) ).            |
| value    | any                                                                                        | `false`  |         | The value with which to constrain the column.  An [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) can be passed as well.  If a QueryBuilder or Function is passed, it will be used as a subselect expression. |

This method is simply an alias for [`where`](/12.1.0/query-builder/building-queries/wheres#where) with the combinator set to `"or"`.

### whereBetween

| Name       | Type                            | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | ------------------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| Expression            | `true`   |         | The name of the column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                                                                    |
| start      | any \| Function \| QueryBuilder | `true`   |         | The beginning value of the BETWEEN statement.  If a function or QueryBuilder is passed it is used as a subselect expression.                                                                                                                                           |
| end        | any \| Function \| QueryBuilder | `true`   |         | The end value of the BETWEEN statement. If a function or QueryBuilder is passed it is used as a subselect expression.                                                                                                                                                  |
| combinator | string                          | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods](/12.1.0/query-builder/building-queries/wheres#andwhere-and-orwhere) instead. |
| negate     | boolean                         | `false`  | `false` | False for BETWEEN, True for NOT BETWEEN.                                                                                                                                                                                                                               |

Adds a where between clause to the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereBetween( "id", 1, 2 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `id` BETWEEN ? AND ?
```

{% endcode %}

If a function or QueryBuilder is passed it is used as a subselect expression.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereBetween(
        "id",
        function( q ) {
            q.select( q.raw( "MIN(id)" ) )
                .from( "users" )
                .where( "email", "bar" );
        },
        builder.newQuery()
            .select( builder.raw( "MAX(id)" ) )
            .from( "users" )
            .where( "email", "bar" )
    );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `id` BETWEEN (
    SELECT MIN(id)
    FROM `users`
    WHERE `email` = ?
)
AND (
    SELECT MAX(id)
    FROM `users`
    WHERE `email` = ?
)
```

{% endcode %}

### whereNotBetween

| Name       | Type                            | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | ------------------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| Expression            | `true`   |         | The name of the column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                                                                    |
| start      | any \| Function \| QueryBuilder | `true`   |         | The beginning value of the BETWEEN statement.  If a function or QueryBuilder is passed it is used as a subselect expression.                                                                                                                                           |
| end        | any \| Function \| QueryBuilder | `true`   |         | The end value of the BETWEEN statement. If a function or QueryBuilder is passed it is used as a subselect expression.                                                                                                                                                  |
| combinator | string                          | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods](/12.1.0/query-builder/building-queries/wheres#andwhere-and-orwhere) instead. |

Adds a where not in clause to the query.  This behaves identically to the [`whereBetween`](/12.1.0/query-builder/building-queries/wheres#wherebetween) method with the `negate`flag set to `true`.  See the documentation for [`whereBetween`](/12.1.0/query-builder/building-queries/wheres#wherebetween) for usage and examples.

### whereColumn

| Name       | Type                                                                           | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | ------------------------------------------------------------------------------ | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| first      | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) | `true`   |         | The name of the first column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                                                              |
| operator   | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) | `true`   |         | The operator to use for the constraint (i.e. "=", "<", ">=", etc.). A value can be passed as the `operator` and the `value` left null as a shortcut for equals (e.g. where( "column", 1 ) == where( "column", "=", 1 ) ).                                              |
| second     | string \| Expression                                                           | `false`  |         | The name of the second column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                                                             |
| combinator | string                                                                         | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods](/12.1.0/query-builder/building-queries/wheres#andwhere-and-orwhere) instead. |

Adds a where clause to a query that compares two columns.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereColumn( "first_name", "=", "last_name" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `first_name` = `last_name`
```

{% endcode %}

Just as with `where`, when using `"="` as the operator you can use a shorthand passing the second column in as the operator and leaving the second column `null`.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereColumn( "first_name", "last_name" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `first_name` = `last_name`
```

{% endcode %}

`Expressions` can be passed in place of either column.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereColumn( "first_name", query.raw( "LOWER(first_name)" ) );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `first_name` = LOWER(first_name)
```

{% endcode %}

### whereExists

| Name       | Type                     | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | ------------------------ | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| query      | Function \| QueryBuilder | `true`   |         | A function or QueryBuilder instance to be used as the exists subquery.                                                                                                                                                                                                 |
| combinator | string                   | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/12.1.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead. |
| negate     | boolean                  | `false`  | `false` | False for EXISTS, True for NOT EXISTS.                                                                                                                                                                                                                                 |

Adds a where exists clause to the query.

It can be configured with a function.

{% code title="QueryBuilder" %}

```javascript
query.from( "orders" )
    .whereExists( function( q ) {
        q.select( q.raw( 1 ) )
            .from( "products" )
            .whereColumn( "products.id", "orders.id" );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `orders`
WHERE EXISTS (
    SELECT 1
    FROM `products`
    WHERE `products`.`id` = `orders`.`id`
)
```

{% endcode %}

It can also be configured with a QueryBuilder instance.

{% code title="QueryBuilder" %}

```javascript
var existsQuery = query.newQuery()
    .select( q.raw( 1 ) )
    .from( "products" )
    .whereColumn( "products.id", "orders.id" );

query.from( "orders" )
    .whereExists( existsQuery );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `orders`
WHERE EXISTS (
    SELECT 1
    FROM `products`
    WHERE `products`.`id` = `orders`.`id`
)
```

{% endcode %}

### whereNotExists

| Name       | Type                     | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | ------------------------ | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| query      | Function \| QueryBuilder | `true`   |         | A function or QueryBuilder instance to be used as the not exists subquery.                                                                                                                                                                                             |
| combinator | string                   | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/12.1.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead. |

Adds a where not in clause to the query.  This behaves identically to the [`whereExists`](/12.1.0/query-builder/building-queries/wheres#whereexists) method with the `negate`flag set to `true`.  See the documentation for [`whereExists`](/12.1.0/query-builder/building-queries/wheres#whereexists) for usage and examples.

### whereLike

| Name       | Type                                                                           | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | ------------------------------------------------------------------------------ | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) | `true`   |         | The name of the column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                                                                    |
| value      | any                                                                            | `false`  |         | The value with which to constrain the column.  An [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) can be passed as well.  If a QueryBuilder or Function is passed, it will be used as a subselect expression.                                   |
| combinator | string                                                                         | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/12.1.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead. |

A shortcut for calling [`where`](/12.1.0/query-builder/building-queries/wheres#where) with `"like"` set as the operator.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereLike( "username", "J%" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `username` LIKE ?
```

{% endcode %}

### whereNotLike

| Name       | Type                                                                           | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | ------------------------------------------------------------------------------ | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) | `true`   |         | The name of the column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                                                                    |
| value      | any                                                                            | `false`  |         | The value with which to constrain the column.  An [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) can be passed as well.  If a QueryBuilder or Function is passed, it will be used as a subselect expression.                                   |
| combinator | string                                                                         | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/12.1.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead. |

A shortcut for calling [`where`](/12.1.0/query-builder/building-queries/wheres#where) with `"not like"` set as the operator.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereNotLike( "username", "J%" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `username` NOT LIKE ?
```

{% endcode %}

### whereIn

| Name       | Type                                                                                                                | Required | Default | Description                                                                                                                                                                                                                                                                                                 |
| ---------- | ------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| Expression                                                                                                | `true`   |         | The name of the column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                                                                                                         |
| values     | string \| array \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) \| Function \| QueryBuilder | `true`   |         | A single value, list of values, or array of values to constrain a column with.  [`Expressions`](/12.1.0/query-builder/building-queries/raw-expressions) may be used in any place a value is used.  Alternatively, a function or QueryBuilder instance can be passed in to be used as a subquery expression. |
| combinator | string                                                                                                              | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/12.1.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead.                                      |
| negate     | boolean                                                                                                             | `false`  | `false` | False for IN, True for NOT IN.                                                                                                                                                                                                                                                                              |

Adds a where in clause to the query.

The values passed to `whereIn` can be a single value, a list of values, or an array of values.

{% code title="QueryBuilder" %}

```javascript
query.from( "orders" )
    .whereIn( "id", [ 1, 4, 66 ] );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `orders`
WHERE `id` IN (?, ?, ?)
```

{% endcode %}

{% hint style="warning" %}
Some database grammars have a hard limit on the number of parameters passed to a SQL statement.  Keep this in mind while writing your queries.
{% endhint %}

If a list of values is passed in, it is converted to an array of values using a single comma (`","`) delimiter.

{% code title="QueryBuilder" %}

```javascript
query.from( "orders" )
    .whereIn( "id", "1,4,66" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `orders`
WHERE `id` IN (?, ?, ?)
```

{% endcode %}

Any value in the list or array can also be passed using a [custom parameter type](/12.1.0/query-builder/building-queries/parameters-and-bindings#custom-parameter-types) to have more control over the parameter settings.

{% code title="QueryBuilder" %}

```javascript
query.from( "orders" )
    .whereIn( "id", [ 1, 4, { value = "66", cfsqltype = "CF_SQL_VARCHAR" } ] );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `orders`
WHERE `id` IN (?, ?, ?)
```

{% endcode %}

`Expressions` can be freely mixed in with other values.

{% code title="QueryBuilder" %}

```javascript
query.from( "orders" )
    .whereIn( "id", [ query.raw( "MAX(id)" ), 4, 66 ] );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `orders`
WHERE `id` IN (MAX(id), ?, ?)
```

{% endcode %}

A function or QueryBuilder instance can be passed to be used as a subquery expression instead of a list of values.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereIn( "id", function( q ) {
        q.select( "id" )
            .from( "users" )
            .where( "age", ">", 25 );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE IN (
    SELECT `id`
    FROM `users`
    WHERE `age` > ?
)
```

{% endcode %}

{% hint style="warning" %}
You may find a `whereExists` method performs better for you than a `whereIn` with a subquery.
{% endhint %}

### whereNotIn

| Name       | Type                                                                                                                | Required | Default | Description                                                                                                                                                                                                                                                                                                 |
| ---------- | ------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| Expression                                                                                                | `true`   |         | The name of the column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                                                                                                         |
| values     | string \| array \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) \| Function \| QueryBuilder | `true`   |         | A single value, list of values, or array of values to constrain a column with.  [`Expressions`](/12.1.0/query-builder/building-queries/raw-expressions) may be used in any place a value is used.  Alternatively, a function or QueryBuilder instance can be passed in to be used as a subquery expression. |
| combinator | string                                                                                                              | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/12.1.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead.                                      |

Adds a where not in clause to the query.  This behaves identically to the `whereIn` method with the `negate`flag set to `true`.  See the documentation for [`whereIn`](/12.1.0/query-builder/building-queries/wheres#wherein) for usage and examples.

### whereRaw

| Name          | Type   | Required | Default | Description                                                                                                                                                                                                                                                            |
| ------------- | ------ | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| sql           | string | `true`   |         | The raw SQL to add to the query.                                                                                                                                                                                                                                       |
| whereBindings | array  | `false`  | `[]`    | Any bindings needed for the raw SQL.  Bindings can be simple values or [custom parameters](/12.1.0/query-builder/building-queries/parameters-and-bindings#custom-parameter-types).                                                                                     |
| combinator    | string | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/12.1.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead. |

Shorthand to add a raw SQL statement to the where clauses.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereRaw(
        "id = ? OR email = ? OR is_admin = 1",
        [ 1, "foo" ]
    );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE id = ? OR email = ? OR is_admin = 1
```

{% endcode %}

### whereNull

| Name       | Type                 | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | -------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| Expression | `true`   |         | The name of the column to check if it is NULL.  Can also pass an [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions).                                                                                                                               |
| combinator | string               | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/12.1.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead. |
| negate     | boolean              | `false`  | `false` | False for NULL, True for NOT NULL.                                                                                                                                                                                                                                     |

Adds a where null clause to the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereNull( "id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `id` IS NULL
```

{% endcode %}

### whereNotNull

| Name       | Type                 | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | -------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| Expression | `true`   |         | The name of the column to check if it is NULL.  Can also pass an [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions).                                                                                                                               |
| combinator | string               | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/12.1.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead. |
| negate     | boolean              | `false`  | `false` | False for NULL, True for NOT NULL.                                                                                                                                                                                                                                     |

Adds a where not in clause to the query.  This behaves identically to the [`whereNull`](/12.1.0/query-builder/building-queries/wheres#wherenull) method with the `negate`flag set to `true`.  See the documentation for [`whereNull`](/12.1.0/query-builder/building-queries/wheres#wherenull) for usage and examples.

## Dynamic Where Methods

qb uses `onMissingMethod` to provide a few different helpers when working with `where...` methods.

### andWhere... and orWhere...

Every `where...` method in qb can be called prefixed with either `and` or `or`.  Doing so will call the original method using the corresponding combinator.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "username", "like", "j%" )
    .andWhere( function( q ) {
        q.where( "isSubscribed", 1 )
            .orWhere( "isOnFreeTrial", 1 );
     } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `username` LIKE ?
  AND (
    `isSubscribed` = ?
    OR
    `isOnFreeTrial` = ?
  )
```

{% endcode %}

### where{Column}

If you call a method starting with `where` that does not match an existing qb method, qb will instead call the `where` method using the rest of the method name as the first column name.  (The rest of the arguments will be shifted to account for this.)  This also applies to `andWhere{Column}` and `orWhere{Column}` method signatures.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereUsername( "like", "j%" )
    .whereActive( 1 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `username` LIKE ?
  AND `active` = ?
```

{% endcode %}


# Order By

The `orderBy` method seems simple but has a lot of depth depending on the type of arguments you pass in.

{% hint style="info" %}
Calling `orderBy` multiple times appends to the order list.
{% endhint %}

## Order By (String)

| Name      | Type   | Required | Default | Description                                                                                                                          |
| --------- | ------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| column    | any    | `true`   |         | The name of the column to order by. An [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) can be passed as well. |
| direction | string | `false`  | `"asc"` | The direction by which to order the query. Accepts `"asc"`or `"desc"`.                                                               |

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( "email" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY `email` ASC
```

{% endcode %}

Calling `orderBy` multiple times will append to the order list.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( "email" )
    .orderBy( "username", "desc" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY
  `email` ASC,
  `username` DESC
```

{% endcode %}

You can also provide an [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions).

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( query.raw( "DATE(created_at)" ) );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY DATE(created_at)
```

{% endcode %}

## Order By (List)

| Name      | Type   | Required | Default | Description                                                                                                                                                                                                     |           |
| --------- | ------ | -------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
| column    | any    | `true`   |         | The list of the columns to order by.  Each column can optionally declare it's sort direction after a pipe delimiter. (e.g. \`"height                                                                            | desc"\`). |
| direction | string | `false`  | `"asc"` | The direction by which to order the query. Accepts `"asc"`or `"desc"`.  This value will be used as the default value for all entries in the column list that fail to specify a direction for a specific column. |           |

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( "email|asc,username", "desc" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY
  `email` ASC,
  `username` DESC
```

{% endcode %}

## Order By (Array of Strings)

| Name      | Type   | Required | Default | Description                                                                                                                                                                                                      |           |
| --------- | ------ | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
| column    | any    | `true`   |         | The array of the columns to order by.  Each column can optionally declare it's sort direction after a pipe delimiter. (e.g. \`"height                                                                            | desc"\`). |
| direction | string | `false`  | `"asc"` | The direction by which to order the query. Accepts `"asc"`or `"desc"`.  This value will be used as the default value for all entries in the column array that fail to specify a direction for a specific column. |           |

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( [ "email|asc", "username" ], "desc" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY
  `email` ASC,
  `username` DESC
```

{% endcode %}

## Order By (Array of Structs)

| Name      | Type   | Required | Default | Description                                                                                                                                                                                                                                   |
| --------- | ------ | -------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column    | any    | `true`   |         | The array of the columns to order by.  Each column can optionally declare it's sort direction using a struct.  The struct should have a column key and an optional direction key. (e.g. `{ column = "favorite_color", direction = "desc" }`). |
| direction | string | `false`  | `"asc"` | The direction by which to order the query. Accepts `"asc"`or `"desc"`.  This value will be used as the default value for all entries in the column array that fail to specify a direction for a specific column.                              |

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( [
        { "column": "email", "direction": "asc" },
        "username"
    ], "desc" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY
  `email` ASC,
  `username` DESC
```

{% endcode %}

## Order By (Subquery)

| Name      | Type   | Required | Default | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| --------- | ------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column    | any    | `true`   |         | The name of the column to order by. An [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) can be passed as well. An array can be passed with any combination of simple values, array, struct, or list for each entry in the array (an example with all possible value styles: column = \[ "last\_name", \[ "age", "desc" ], { column = "favorite\_color", direction = "desc" }, "height\|desc" ];. The column argument can also just accept a comman delimited list with a pipe ( \| ) as the secondary delimiter denoting the direction of the order by. The pipe delimiter is also used when parsing the column argument when it is passed as an array and the entry in the array is a pipe delimited string. |
| direction | string | `false`  | `"asc"` | Ignored when using a Function or QueryBuilder instance.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |

You can order with a subquery using either a function or a QueryBuilder instance.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( function( q ) {
        q.selectRaw( "MAX(created_date)" )
            .from( "logins" )
            .whereColumn( "users.id", "logins.user_id" );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY (
    SELECT MAX(created_date)
    FROM `logins`
    WHERE `users`.`id` = `logins`.`user_id`
)
```

{% endcode %}

## Order By Raw

| Name       | Type   | Required | Default | Description                                |
| ---------- | ------ | -------- | ------- | ------------------------------------------ |
| expression | string | `true`   |         | The raw SQL expression to use.             |
| bindings   | array  | `false`  | `[]`    | Any bindings (`?`) used in the expression. |

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderByRaw( "CASE WHEN status = ? THEN 1 ELSE 0 END DESC", [ 1 ] );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY CASE WHEN status = ? THEN 1 ELSE 0 END DESC
```

{% endcode %}

## Order By Random

| Name         | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderByRandom();
```

{% endcode %}

{% tabs %}
{% tab title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY RAND()
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
SELECT *
FROM [users]
ORDER BY NEWID()
```

{% endtab %}

{% tab title="Postgres" %}

```sql
SELECT *
FROM "users"
ORDER BY RANDOM()
```

{% endtab %}

{% tab title="Oracle" %}

```sql
SELECT *
FROM "USERS"
ORDER BY DBMS_RANDOM.VALUE
```

{% endtab %}

{% tab title="SQLite" %}

```sql
SELECT *
FROM "users"
ORDER BY RANDOM()
```

{% endtab %}

{% tab title="Derby" %}

```sql
SELECT *
FROM "users"
ORDER BY RANDOM()
```

{% endtab %}
{% endtabs %}

## clearOrders

| Name         | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

Clears the currently configured orders for the query.  Usually used by downstream libraries like [Quick](https://quick.ortusbooks.com/).

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( "email" )
    .clearOrders();
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
```

{% endcode %}

## reorder

| Name      | Type   | Required | Default | Description                                                                                                                          |
| --------- | ------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| column    | any    | `true`   |         | The name of the column to order by. An [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) can be passed as well. |
| direction | string | `false`  | `"asc"` | The direction by which to order the query. Accepts `"asc"`or `"desc"`.                                                               |

Clears the currently configured orders for the query and sets the new orders passed in.  Any valid argument to [`orderBy`](/12.1.0/query-builder/building-queries/ordering-grouping-and-limit) can be passed here.  Usually used by downstream libraries like [Quick](https://quick.ortusbooks.com/).

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( "email" )
    .reorder( "username" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY `username` ASC
```

{% endcode %}


# Group By and Having

## groupBy

| Name   | Type            | Required | Default | Description                                                                                                                                                                              |
| ------ | --------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| groups | string \| array | `true`   |         | A single column name, a list of column names, or an array of column names to group by.  An [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) can be passed as well. |

Passing a single string will group by that one column.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .groupBy( "country" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
GROUP BY `country`
```

{% endcode %}

You can also pass a list of column names.  A single comma (`","`) will be used as the delimiter.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .groupBy( "country,city" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
GROUP BY `country`, `city`
```

{% endcode %}

An array of column names can be provided.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .groupBy( [ "country", "city" ] );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
GROUP BY `country`, `city`
```

{% endcode %}

Calling `groupBy` multiple times will to the current groups.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .groupBy( "country" )
    .groupBy( "city" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
GROUP BY `country`, `city`
```

{% endcode %}

An [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) can be passed in place of a column.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .groupBy( query.raw( "DATE(created_at)" ) );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
GROUP BY DATE(created_at)
```

{% endcode %}

## having

| Name       | Type                                                                           | Required | Default | Description                                                                                                                                                                                                               |
| ---------- | ------------------------------------------------------------------------------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| [Expression](/12.1.0/query-builder/building-queries/raw-expressions) | `true`   |         | The name of the column or [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                       |
| operator   | any                                                                            | `false`  |         | The operator to use for the constraint (i.e. "=", "<", ">=", etc.). A value can be passed as the `operator` and the `value` left null as a shortcut for equals (e.g. where( "column", 1 ) == where( "column", "=", 1 ) ). |
| value      | any                                                                            | `false`  |         | The value with which to constrain the column.  An [`Expression`](/12.1.0/query-builder/building-queries/raw-expressions) can be passed as well.                                                                           |
| combinator | string                                                                         | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andHaving` and `orHaving` methods instead.                                |

Adds a having clause to a query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .groupBy( "email" )
    .having( "email", ">", 1 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
GROUP BY `email`
HAVING `email` > ?
```

{% endcode %}

`Expressions` can be used in place of the column or the value.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .groupBy( "email" )
    .having( query.raw( "COUNT(email)" ), ">", 1 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
GROUP BY `email`
HAVING COUNT(email) > ?
```

{% endcode %}


# Limit, Offset, and Pagination

## limit

| Name  | Type    | Required | Default | Description                    |
| ----- | ------- | -------- | ------- | ------------------------------ |
| value | numeric | `true`   |         | The limit value for the query. |

Sets the limit value for the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .limit( 5 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
LIMIT 5
```

{% endcode %}

## take

| Name  | Type    | Required | Default | Description                    |
| ----- | ------- | -------- | ------- | ------------------------------ |
| value | numeric | `true`   |         | The limit value for the query. |

Sets the limit value for the query.  Alias for [`limit`](/12.1.0/query-builder/building-queries/limit-offset-and-pagination#limit).

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .take( 5 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
LIMIT 5
```

{% endcode %}

## offset

| Name  | Type    | Required | Default | Description                     |
| ----- | ------- | -------- | ------- | ------------------------------- |
| value | numeric | `true`   |         | The offset value for the query. |

Sets the offset value for the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .offset( 25 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
OFFSET 25
```

{% endcode %}

## forPage

| Name    | Type    | Required | Default | Description                                                                            |
| ------- | ------- | -------- | ------- | -------------------------------------------------------------------------------------- |
| page    | numeric | `true`   |         | The page number to retrieve.                                                           |
| maxRows | numeric | `true`   |         | The number of records per page.  If a number less than 0 is passed, 0 is used instead. |

Helper method to calculate the limit and offset given a page number and count per page.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .forPage( 3, 15 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
LIMIT 15
OFFSET 30
```

{% endcode %}

## simplePaginate & paginate

This method combines `forPage`, `count`, and `get` to create a pagination struct alongside the results. Information on the `simplePaginate` or `paginate` methods, including custom pagination collectors, can be found in the [Retreiving Results](/12.1.0/query-builder/executing-queries/retrieving-results#paginate) section of the documentation.


# Locks

qb includes a few methods to help you lock certain rows when executing `select` statements.

{% hint style="warning" %}
**Note:** For locks to work properly, they must be nested inside a `transaction`.  qb does not handle any of the transaction lifecycle for you.
{% endhint %}

## sharedLock

| Name         | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

A shared lock prevents the selected rows from being modified until your transaction is committed.

{% tabs %}
{% tab title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "id", 1 )
    .sharedLock();
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `id` = ?
LOCK IN SHARE MODE
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
SELECT *
FROM [users] WITH (ROWLOCK,HOLDLOCK)
WHERE [id] = ?
```

{% endtab %}

{% tab title="Postgres" %}

```sql
SELECT *
FROM "users"
WHERE "id" = ?
FOR SHARE
```

{% endtab %}

{% tab title="Oracle" %}

```sql
LOCK TABLE "USERS"
IN SHARE MODE NOWAIT;

SELECT *
FROM "USERS"
WHERE "ID" = ?
```

{% endtab %}
{% endtabs %}

## lockForUpdate

| Name       | Type    | Required | Default | Description |
| ---------- | ------- | -------- | ------- | ----------- |
| skipLocked | Boolean | `false`  | `false` |             |

A lock for update lock prevents the selected rows from being modified or selected with another shared lock until your transaction is committed.

The main difference between a `sharedLock` and `lockForUpdate` is that a `lockForUpdate` prevents other reads or selects as well as updates.

{% tabs %}
{% tab title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "id", 1 )
    .lockForUpdate();
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `id` = ?
FOR UPDATE
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
SELECT *
FROM [users] WITH (ROWLOCK,UPDLOCK,HOLDLOCK)
WHERE [id] = ?
```

{% endtab %}

{% tab title="Postgres" %}

```sql
SELECT *
FROM "users"
WHERE "id" = ?
FOR UPDATE
```

{% endtab %}

{% tab title="Oracle" %}

```sql
SELECT *
FROM "USERS"
WHERE "ID" = ?
FOR UPDATE
```

{% endtab %}
{% endtabs %}

When using the `skipLocked` flag, the query will skip over locked records and only return and lock available records.

{% tabs %}
{% tab title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "id", 1 )
    .lockForUpdate( skipLocked = true )
    .orderBy( "id" )
    .limit( 5 );
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `id` = ?
ORDER BY `id`
LIMIT 5
FOR UPDATE SKIP LOCKED
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
SELECT TOP 5 *
FROM [users] WITH (ROWLOCK,UPDLOCK,HOLDLOCK,READPAST)
WHERE [id] = ?
ORDER BY [id]
```

{% endtab %}

{% tab title="Postgres" %}

```sql
SELECT *
FROM "users"
WHERE "id" = ?
ORDER BY "id"
LIMIT 1
FOR UPDATE SKIP LOCKED
```

{% endtab %}
{% endtabs %}

## noLock

| Name         | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

`noLock` will instruct your grammar to ignore any shared locks when executing the query.

Currently this only makes a difference in SQL Server grammars.

{% tabs %}
{% tab title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "id", 1 )
    .noLock();
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="SQL Server" %}

```sql
SELECT *
FROM [users] WITH (NOLOCK)
WHERE [id] = ?
```

{% endtab %}
{% endtabs %}

## lock

| Name  | Type   | Required | Default | Description                                    |
| ----- | ------ | -------- | ------- | ---------------------------------------------- |
| value | string | `true`   |         | The custom lock directive to add to the query. |

The `lock` method will allow you to add a custom lock directive to your query.  Think of it as the `raw` method for lock directives.

These lock directives vary from grammar to grammar.

## clearLock

| Name         | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

Clears any lock directive on the query.


# Unions

The query builder also lets you create union statements on your queries using either `UNION` or `UNION ALL` strategies.

The `union` methods take either a Query Builder instance or a closure which you use to define a new QueryBuilder instance.

Union statements are added in the order in which the `union` methods are invoked, but the `union` statements can be in any order in your API call stack. This means you can safely declare your `union` method calls before the `select`, `from` and `orderBy` calls on the source Query Builder instance.

* `union()` — This method builds a SQL statement using the `UNION` clause which combines two SQL queries into a single result set containing all the matching rows. The two queries *must* have the same defined columns and compatible data types or the SQL engine will generate an error. The `union` clause only returns unique rows.
* `unionAll()` — This builds a SQL statement using the `UNION ALL` clause. This is the same as `union` but includes duplicate rows.&#x20;

{% hint style="danger" %}
**IMPORTANT:** The QueryBuilder instances passed to a `union` statement *cannot* contain a defined order. Any use of the `orderBy()` method on the unioned QueryBuilder instances will result in an `OrderByNotAllowed`exception. To order the results, add an `orderBy()` call to the parent source Query Builder instance.
{% endhint %}

## union

| Name  | Type                     | Required | Default | Description                                                                                                                               |
| ----- | ------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| input | Function \| QueryBuilder | `true`   |         | The function or QueryBuilder instance to use as the unioned query.                                                                        |
| all   | boolean                  | `false`  | `false` | Determines if statement should be a "UNION ALL". Passing this as an argument is discouraged. Use the dedicated `unionAll` where possible. |

Adds a UNION statement to the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .select( "name" )
    .where( "id", 1 )
    .union( function ( q ) {
        q.from( "users" )
            .select( "name" )
            .where( "id", 2 );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION
SELECT `name`
FROM `users`
WHERE `id` = ?
```

{% endcode %}

Adding multiple union statements will append it to the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .select( "name" )
    .where( "id", 1 )
    .union( function ( q ) {
        q.from( "users" )
            .select( "name" )
            .where( "id", 2 );
    } )
    .union( function ( q ) {
        q.from( "users" )
            .select("name")
            .where( "id", 3 );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION
SELECT `name`
FROM `users`
WHERE `id` = ?
```

{% endcode %}

It can also add union queries as QueryBuilder instances.

{% code title="QueryBuilder" %}

```javascript
var q1 = query.newQuery()
    .from( "users" )
    .select( "name" )
    .where( "id", 2 );
    
var q2 = query.newQuery()
    .from( "users" )
    .select( "name" )
    .where( "id", 3 );

query.from( "users" )
    .select( "name" )
    .where( "id", 1 )
    .union( q1 )
    .union( q2 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION
SELECT `name`
FROM `users`
WHERE `id` = ?
```

{% endcode %}

## unionAll

| Name  | Type                     | Required | Default | Description                                                        |
| ----- | ------------------------ | -------- | ------- | ------------------------------------------------------------------ |
| input | Function \| QueryBuilder | `true`   |         | The function or QueryBuilder instance to use as the unioned query. |

Adds a UNION ALL statement to the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .select( "name" )
    .where( "id", 1 )
    .unionAll( function( q ) {
        q.from( "users" )
            .select( "name" )
            .where( "id", 2 );
     } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION ALL
SELECT `name`
FROM `users`
WHERE `id` = ?
```

{% endcode %}

Adding multiple `unionAll` statements will append it to the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .select( "name" )
    .where( "id", 1 )
    .unionAll( function( q ) {
        q.from( "users" )
            .select( "name" )
            .where( "id", 2 );
     } )
    .unionAll( function( q ) {
        q.from( "users" )
            .select( "name" )
            .where( "id", 3 );
     } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION ALL
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION ALL
SELECT `name`
FROM `users`
WHERE `id` = ?
```

{% endcode %}

It can also add union queries as QueryBuilder instances.

{% code title="QueryBuilder" %}

```javascript
var q1 = query.newQuery()
    .from( "users" )
    .select( "name" )
    .where( "id", 2 );
    
var q2 = query.newQuery()
    .from( "users" )
    .select( "name" )
    .where( "id", 3 );

query.from( "users" )
    .select( "name" )
    .where( "id", 1 )
    .unionAll( q1 )
    .unionAll( q2 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION ALL
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION ALL
SELECT `name`
FROM `users`
WHERE `id` = ?
```

{% endcode %}


# Common Table Expressions (i.e. CTEs)

Common Table Expressions (CTEs) are powerful SQL concept that allow you to create re-usable temporal result sets, which can be referenced as a table within your SQL. CTEs are available in many common database engines and are available in latest versions of all of the support grammars.

CTEs come in two basic types:

* **Non-recursive** — These are statements that do not reference themselves, in simplified terms they are like a derived table that can be referenced by a user-defined name.
* **Recursive** — Recursive CTEs reference themselves and are generally used for creating hierarchical data—such as creating a parent/child relationship within a table.&#x20;

While all of the grammars currently support CTEs, there is enough difference between the various databases implementations of CTEs that unless your CTEs are fairly basic, using CTEs within your project will most likely tie your project to a specific database, unless you account for the differences in your code.

However, CTEs are can be extremely useful to solve certain use cases.

To add CTEs to your queries, you have two methods available:

* `with()` — Allows you to define a non-recursive CTE.
* `withRecursive()` — Allows you to define a recursive CTE.

{% hint style="info" %}
Some database engines require the `recursive` keyword anytime at least one of your CTEs is recursive, but some database engines (e.g. SQL Server and Oracle) do not require the keyword. qb will manage adding the keyword, if necessary. If your query does use recursion you should use the `withRecursive()`method to avoid issues when migrating grammars.
{% endhint %}

## with

| Name      | Type                     | Required | Default | Description                                                                                                                                              |
| --------- | ------------------------ | -------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| name      | string                   | `true`   |         | The name of the CTE.                                                                                                                                     |
| input     | QueryBuilder \| Function | `true`   |         | Either a QueryBuilder instance or a function to define the derived query.                                                                                |
| columns   | Array\<String>           | `false`  | `[]`    | An optional array containing the columns to include in the CTE.                                                                                          |
| recursive | boolean                  | `false`  | `false` | Determines if the CTE statement should be a recursive CTE. Passing this as an argument is discouraged. Use the dedicated `withRecursive` where possible. |

You can build a CTE using a function:

{% code title="QueryBuilder" %}

```javascript
// qb
query.with( "UserCTE", function ( q ) {
        q
            .select( [ "fName as firstName", "lName as lastName" ] )
            .from( "users" )
            .where( "disabled", 0 );
    } )
    .from( "UserCTE" )
    .get();
```

{% endcode %}

{% code title="MySQL" %}

```sql
WITH `UserCTE` AS (
    SELECT
        `fName` as `firstName`,
        `lName` as `lastName`
    FROM `users`
    WHERE `disabled` = 0
) SELECT * FROM `UserCTE`
```

{% endcode %}

Alternatively, you can use a QueryBuilder instance instead of a function:

{% code title="QueryBuilder" %}

```javascript
// qb
var cte = query
    .select( [ "fName as firstName", "lName as lastName" ] )
    .from( "users" )
    .where( "disabled", 0 );

query.with( "UserCTE", cte )
    .from( "UserCTE" )
    .get();
```

{% endcode %}

{% code title="MySQL" %}

```sql
WITH `UserCTE` AS (
    SELECT
        `fName` as `firstName`,
        `lName` as `lastName`
    FROM `users`
    WHERE `disabled` = 0
)
SELECT * FROM `UserCTE`
```

{% endcode %}

A single query can reference multiple CTEs:

{% code title="QueryBuilder" %}

```javascript
query.with( "UserCTE", function ( q ) {
        q.select( [ "id", "fName as firstName", "lName as lastName" ] )
            .from( "users" )
            .where( "disabled", 0 );
    } )
    .with( "BlogCTE", function ( q ) {
        q.from( "blogs" )
            .where( "disabled", 0 );
    } )
    .from( "BlogCTE as b" )
    .join( "UserCTE as u", "b.Creator", "u.id" )
    .get();
```

{% endcode %}

{% code title="MySQL" %}

```sql
WITH `UserCTE` AS (
    SELECT
        `id`,
        `fName` as `firstName`,
        `lName` as `lastName`
    FROM `users`
    WHERE `disabled` = 0
),
`BlogCTE` AS (
    SELECT *
    FROM `blogs`
    WHERE `disabled` = 0
)
SELECT *
FROM `BlogCTE` AS `b`
INNER JOIN `UserCTE` AS `u`
ON `b`.`Creator` = `u`.`id`
```

{% endcode %}

## withRecursive

| Name    | Type                     | Required | Default | Description                                                               |
| ------- | ------------------------ | -------- | ------- | ------------------------------------------------------------------------- |
| name    | string                   | `true`   |         | The name of the CTE.                                                      |
| input   | QueryBuilder \| Function | `true`   |         | Either a QueryBuilder instance or a function to define the derived query. |
| columns | Array\<String>           | `false`  | `[]`    | An optional array containing the columns to include in the CTE.           |

{% hint style="warning" %}
**IMPORTANT** — The way the SQL in a recursive CTEs are written, using them in your code is likely to lock in you in to a specific database engine, unless you structure your code to build the correct SQL based on the current grammar being used.
{% endhint %}

Here is an example of building a recursive CTE using SQL Server which would return all parent/child rows and show their generation/level depth:

{% code title="QueryBuilder" %}

```javascript
query
.withRecursive( "Hierarchy", function ( q ) {
    q.select( [ "Id", "ParentId", "Name", q.raw( "0 AS [Generation]" ) ] )
        .from( "Sample" )
        .whereNull( "ParentId" )
        // use recursion to join the child rows to their parents
        .unionAll( function ( q ) {
            q.select( [
                    "child.Id",
                    "child.ParentId",
                    "child.Name",
                    q.raw( "[parent].[Generation] + 1" )
                ] )
                .from( "Sample as child" )
                .join( "Hierarchy as parent", "child.ParentId", "parent.Id" );
        } );
    }, [ "Id", "ParentId", "Name", "Generation" ] )
    .from( "Hierarchy" )
    .get();
```

{% endcode %}

{% code title="SqlServer" %}

```sql
WITH [Hierarchy] ([Id], [ParentId], [Name], [Generation]) AS (
    SELECT
        [Id],
        [ParentId],
        [Name],
        0 AS [Generation]
    FROM [Sample]
    WHERE [ParentId] IS NULL
    UNION ALL
    SELECT
        [child].[Id],
        [child].[ParentId],
        [child].[Name],

[parent].[Generation] + 1
    FROM [Sample] AS [child]
    INNER JOIN [Hierarchy] AS [parent]
        ON [child].[ParentId] = [parent].[Id]
) SELECT * FROM [Hierarchy]
```

{% endcode %}


# Raw Expressions

Raw expressions are the qb escape hatch.  While qb strives to provide ways to execute the majority of queries, you will occasionally need to provide raw sql values that are not processed by qb.  These SQL snippets are called `raw` or `Expressions` in qb.

{% hint style="warning" %}
`raw` expressions are useful, but shoud be used only if there is not another way to accomplish the same action using other qb methods.  This is because a `raw` expression has the potential to use syntax specific to one database grammar or another, preventing you from easily switching from one grammar to another, one of the major benefits of using qb.
{% endhint %}

The first way to retrieve an `Expression` is to call the `raw` method on the `QueryBuilder` object.

## raw

| Name | Type   | Required | Default | Description                              |
| ---- | ------ | -------- | ------- | ---------------------------------------- |
| sql  | string | true     |         | The raw sql to wrap up in an Expression. |

The sql snippet passed to `raw` is not processed by qb at all.  With that in mind, it is important to follow all best practices and security recommendations with the sql you use with `raw`.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).select( query.raw( "MAX(created_date)" ) );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT MAX(created_date) FROM `users`
```

{% endcode %}

Expressions can be passed to most qb methods, like `select`, `from`, `where`, or `orderBy`, among others.  Additionally, qb provides some convenience methods to add raw values in different parts of the query:

* [selectRaw](/12.1.0/query-builder/building-queries/selects#get-3)
* [fromRaw](/12.1.0/query-builder/building-queries/from#get-2)
* [joinRaw](/12.1.0/query-builder/building-queries/joins#joinraw)
* [leftJoinRaw](/12.1.0/query-builder/building-queries/joins#leftjoinraw)
* [rightJoinRaw](/12.1.0/query-builder/building-queries/joins#rightjoinraw)
* [crossJoinRaw](/12.1.0/query-builder/building-queries/joins#crossjoinraw)
* [whereRaw](/12.1.0/query-builder/building-queries/wheres#whereraw)
* forRaw


# When / Conditionals

If you store the builder object in a variable, you can use `if` and `else` statements like you would expect.

{% code title="QueryBuilder" %}

```javascript
var q = query.from( "posts" );
if ( someFlag ) {
    q.orderBy( "published_date", "desc" );
}
```

{% endcode %}

This works, but breaks chainability. To keep chainability you can use the `when` helper method.

## `when`

| Name           | Type     | Required | Default                     | Description                                                                                                   |
| -------------- | -------- | -------- | --------------------------- | ------------------------------------------------------------------------------------------------------------- |
| condition      | boolean  | true     |                             | The condition to switch on.                                                                                   |
| onTrue         | Function | true     |                             | The callback to execute if the condition is true.  It is passed the `builder` object as the only parameter.   |
| onFalse        | Function | false    | function( q ) { return q; } | The callback to execute if the conditions is false.  It is passed the `builder` object as the only parameter. |
| withoutScoping | boolean  | false    | `false`                     | Flag to turn off the automatic scoping of where clauses during the callback.                                  |

The `when` helper is used to allow conditional statements when defining queries without using if statements and having to store temporary variables.

{% code title="QueryBuilder" %}

```javascript
query.from( "posts" )
    .when( someFlag, function( q ) {
        q.orderBy( "published_date", "desc" );
    } )
    .get();
```

{% endcode %}

You can pass a third argument to be called in the `else` case.

{% code title="QueryBuilder" %}

```javascript
query.from( "posts" )
    .when(
        someFlag,
        function( q ) {
            q.orderBy( "published_date", "desc" );
        },
        function( q ) {
            q.orderBy( "modified_date", "desc" );
        }
    );
```

{% endcode %}

`when` callbacks are automatically scoped and grouped.  That means that if a where clause is added inside the callback with an `OR` combinator the clauses will automatically be grouped (have parenthesis put around them.)  You can disable this feature by passing `withoutScoping = true` to the `when` callback.

```javascript
qb.from( "users" )
    .where( "active", 1 )
    .when( len( url.q ), function( q ) {
        q.where( "username", "LIKE", q & "%" )
            .orWhere( "email", "LIKE", q & "%" );   
    } );
```

```sql
SELECT *
FROM "users"
WHERE "active" = ?
    AND (
        "username" = ?
        OR "email" = ?
    )
```


# Query Parameters and Bindings

## Custom Parameter Types

When passing a parameter to qb, it will infer the sql type to be used.  If you pass a number, `NUMERIC` will be used. If it is a date, `TIMESTAMP`, and so forth. If you need more control, you can pass a struct with the parameters you would pass to [`cfqueryparam`](https://cfdocs.org/cfqueryparam).

{% hint style="success" %}
You can pass include any parameters you would use with [`cfqueryparam`](https://cfdocs.org/cfqueryparam) including `null`, `list`, etc.  This applies anywhere parameters are used including `where`, `update`, and `insert` methods.
{% endhint %}

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "id", "=", { value = 18, cfsqltype = "VARCHAR" } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `id` = ?
```

{% endcode %}

This can be used when inserting or updating records as well.

{% code title="QueryBuilder" %}

```javascript
query.table( "users" )
    .insert( {
        "id" = { value 1, cfsqltype = "VARCHAR" },
        "age" = 18,
        "updatedDate" = { value = now(), cfsqltype = "DATE" }
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
INSERT INTO `users`
    (`id`, `age`, `updatedDate`)
VALUES
    (?, ?, ?)
```

{% endcode %}

### Numeric SQL Types

qb will use a different SQL type for integers and decimals.  You can customize the SQL types by setting the `integerSqlType` and `decimalSqlType` settings.

```cfscript
moduleSettings = {
    "qb": {
        "integerSqlType": "INTEGER",
        "decimalSqlType": "DECIMAL"
    }
};
```

Additionally, qb automatically calculates a scale based on the value provided if the value is a floating point number.

## Bindings

Bindings are the values that will be sent as parameters to a prepared SQL statement.  This protects you from [SQL injection.](https://en.wikipedia.org/wiki/SQL_injection)  In CFML, this uses [`cfqueryparam`](https://cfdocs.org/cfqueryparam) to parameterize the values.

If you need to inspect the bindings for the current query you can retrieve them in order using the `getBindings` method.

{% hint style="info" %}
You can view the current SQL for the query with bindings inline for debugging purposes using the [`toSQL`](/12.1.0/query-builder/debugging#tosql) method.
{% endhint %}

{% hint style="danger" %}
&#x20;Use these methods only for debugging. Modifying the bindings directly will likely cause issues when executing your query.  Adding or removing bindings should be done using the public API.
{% endhint %}

### getBindings

| Name         | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

This method returns the current bindings in order to be used for the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .join( "logins", function( j ) {
        j.on( "users.id", "logins.user_id" );
        j.where( "logins.created_date", ">", dateAdd( "m", -1, "01 Jun 2019" ) );
    } )
    .where( "active", 1 );
```

{% endcode %}

{% code title="Result" %}

```sql
[
    { value = "01 May 2019", cfsqltype = "TIMESTAMP"  },
    { value = 1, cfsqltype = "INTEGER" }
]
```

{% endcode %}

You can also retrieve the bindings associated to their corresponding types.

### getRawBindings

| Name         | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

This method returns the current bindings  to be used for the query associated to their corresponding types.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .join( "logins", function( j ) {
        j.on( "users.id", "logins.user_id" );
        j.where( "logins.created_date", ">", dateAdd( "m", -1, "01 Jun 2019" ) );
    } )
    .where( "active", 1 );
```

{% endcode %}

{% code title="Result" %}

```sql
{
    "commonTables" = [],
    "select" = [],
    "join" = [
        { value = "01 May 2019", cfsqltype = "CF_SQL_TIMESTAMP"  },
    ],
    "where" = [
        { value = 1, cfsqltype = "CF_SQL_NUMERIC" }
    ],
    "union" = [],
    "insert" = [],
    "insertRaw" = [],
    "update" = []
};
```

{% endcode %}

### addBindings

Adds a single binding or an array of bindings to a query for a given type.

| Name        | Type                        | Required | Default   | Description                                                       |
| ----------- | --------------------------- | -------- | --------- | ----------------------------------------------------------------- |
| newBindings | `Struct` \| `Array<Struct>` | true     |           | A single binding or an array of bindings to add for a given type. |
| type        | `String`                    | false    | `"where"` | The type of binding to add.                                       |

### addBindingsFromBuilder

Adds all of the bindings from another builder instance.

| Name | Type           | Required | Default | Description                                                |
| ---- | -------------- | -------- | ------- | ---------------------------------------------------------- |
| qb   | `QueryBuilder` | true     |         | Another builder instance to copy all of the bindings from. |


# Executing Queries


# Retrieving Results

## get

| Name    | Type            | Required | Default | Description                                                                                                    |
| ------- | --------------- | -------- | ------- | -------------------------------------------------------------------------------------------------------------- |
| columns | string \| array | false    |         | A shortcut parameter to retrieve only these columns overriding any columns previously set on the QueryBuilder. |
| options | struct          | false    | `{}`    | Any additional `queryExecute` options.                                                                         |

The `get` method is the most common method used for retrieving results. It executes using the configured `QueryBuilder` and returns the results.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).get();
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT * FROM `users`
```

{% endcode %}

`get` can also take a list or array of columns to use as a shortcut. If any are passed, those columns will be used instead of any columns previously set on the `QueryBuilder`.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).get( [ "id", "name" ] );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT `id`, `name` FROM `users`
```

{% endcode %}

## first

| Name    | Type   | Required | Default | Description                            |
| ------- | ------ | -------- | ------- | -------------------------------------- |
| options | struct | `false`  | `{}`    | Any additional `queryExecute` options. |

If you just need to retrieve a single row from the database table, you may use the `first` method. This method will return a single record (a `Struct` by default). If no row is found an empty `Struct` will be returned by default.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).first();
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT * FROM `users`
 LIMIT(1)
```

{% endcode %}

## firstOrFail

| Name         | Type   | Required | Default | Description                                                                                                                                                         |
| ------------ | ------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| errorMessage | string | `false`  |         | An optional string error message or callback to produce a string error message. If a callback is used, it is passed the QueryBuilder instance as the only argument. |
| options      | struct | `false`  | `{}`    | Any additional `queryExecute` options.                                                                                                                              |

{% hint style="danger" %}
**throws:** `RecordNotFound`
{% endhint %}

Returns the first matching row for the configured query, just like [`first`](#first). If no records are found, it throws an `RecordNotFound` exception.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).firstOrFail();
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT * FROM `users`
 LIMIT(1)
```

{% endcode %}

## find

| Name     | Type     | Required | Default | Description                             |
| -------- | -------- | -------- | ------- | --------------------------------------- |
| id       | `any`    | true     |         | The id value to look up.                |
| idColumn | `string` | false    | `"id"`  | The name of the id column to constrain. |
| options  | `struct` | false    | `{}`    | Any additional `queryExecute` options.  |

Adds an id constraint to the query and returns the first record from the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).find( 1 );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT * FROM `users`
WHERE `id` = ?
LIMIT(1)
```

{% endcode %}

## findOrFail

| Name     | Type     | Required | Default | Description                             |
| -------- | -------- | -------- | ------- | --------------------------------------- |
| id       | `any`    | true     |         | The id value to look up.                |
| idColumn | `string` | false    | `"id"`  | The name of the id column to constrain. |
| options  | `struct` | false    | `{}`    | Any additional `queryExecute` options.  |

{% hint style="danger" %}
**Throws:** `RecordNotFound`
{% endhint %}

Adds an id constraint to the query and returns the first record from the query. If no record is found, it throws an `RecordNotFound` exception.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).find( 415015 );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT * FROM `users`
WHERE `id` = ?
LIMIT(1)
```

{% endcode %}

## values

| Name    | Type   | Required | Default | Description                                                                                                                |
| ------- | ------ | -------- | ------- | -------------------------------------------------------------------------------------------------------------------------- |
| column  | any    | `true`   |         | The name of the column to retrieve or an [Expression](/12.1.0/query-builder/building-queries/raw-expressions) to retrieve. |
| options | struct | `false`  | `{}`    | Any additional `queryExecute` options.                                                                                     |

If you don't even need an entire row, you may extract a single value from each record using the `values` method. The `values` method will return the column of your choosing as a simple array.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).values( "firstName" );
```

{% endcode %}

{% code title="Result" %}

```
[ "jon", "jane", "jill", ... ]
```

{% endcode %}

An expression can also be passed to `values`:

```javascript
qb.from( "users" ).values( qb.raw( "CONCAT(fname, ' ', lname) AS fullName" ) );
```

{% hint style="info" %}
The [`valuesRaw`](/12.1.0/query-builder/executing-queries/retrieving-results#valuesraw) function can make this pattern more ergonomic.
{% endhint %}

## valuesRaw

| Name    | Type   | Required | Default | Description                                                                                |
| ------- | ------ | -------- | ------- | ------------------------------------------------------------------------------------------ |
| column  | string | `true`   |         | The sql to use as an [Expression](/12.1.0/query-builder/building-queries/raw-expressions). |
| options | struct | `false`  | `{}`    | Any additional `queryExecute` options.                                                     |

The `values` method will return the expression given for each row as a simple array.

```javascript
query.from( "users" ).valuesRaw( "CONCAT(fname, ' ', lname) AS fullName" );
```

## value

| Name              | Type    | Required | Default        | Description                                                                                                                |
| ----------------- | ------- | -------- | -------------- | -------------------------------------------------------------------------------------------------------------------------- |
| column            | any     | `true`   |                | The name of the column to retrieve or an [Expression](/12.1.0/query-builder/building-queries/raw-expressions) to retrieve. |
| defaultValue      | string  | `false`  | (empty string) | The default value returned if there are no records returned for the query.                                                 |
| throwWhenNotFound | boolean | `false`  | `false`        | If `true`, it throws a `RecordCountException` if no records are returned from the query.                                   |
| options           | struct  | `false`  | `{}`           | Any additional `queryExecute` options.                                                                                     |

This method is similar to `values` except it only returns a single, simple value. Where `values` calls `get` under the hood, this method calls `first`.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).value( "firstName" );
```

{% endcode %}

{% code title="Result" %}

```
"jon"
```

{% endcode %}

If no records are returned from the query, one of two things will happen. If the `throwWhenNotFound` boolean is set to `true`, a `RecordCountException` will be thrown. Otherwise the `defaultValue` provided to the method will be returned.

An expression can also be passed to `value`:

```javascript
qb.from( "users" ).value( qb.raw( "CONCAT(fname, ' ', lname) AS fullName" ) );
```

{% hint style="info" %}
The [`valueRaw`](/12.1.0/query-builder/executing-queries/retrieving-results#valueraw) function can make this pattern more ergonomic.
{% endhint %}

## valueRaw

| Name              | Type    | Required | Default        | Description                                                                                |
| ----------------- | ------- | -------- | -------------- | ------------------------------------------------------------------------------------------ |
| column            | string  | `true`   |                | The sql to use as an [Expression](/12.1.0/query-builder/building-queries/raw-expressions). |
| defaultValue      | string  | `false`  | (empty string) | The default value returned if there are no records returned for the query.                 |
| throwWhenNotFound | boolean | `false`  | `false`        | If `true`, it throws a `RecordCountException` if no records are returned from the query.   |
| options           | struct  | `false`  | `{}`           | Any additional `queryExecute` options.                                                     |

The `value` method will return the expression given for the first row found.

```javascript
query.from( "users" ).valueRaw( "CONCAT(fname, ' ', lname) AS fullName" );
```

## chunk

| Name     | Type     | Default | Description                                       |
| -------- | -------- | ------- | ------------------------------------------------- |
| max      | numeric  |         | The number of results to return in each chunk.    |
| callback | Function |         | The function that will be called with each chunk. |
| options  | struct   | `{}`    | Any additional `queryExecute` options.            |

Large datasets can be broken up and retrieved in chunks. This allows you to work with a subset of results at once to keep your memory footprint under control.

`chunk` can be called on any query like you would call `get`. You can stop the retrieving and processing early by returning `false` from the callback.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).chunk( 100, function( users ) {
    // Process the users here
    // Returning false from the callback stops processing
} );
```

{% endcode %}

## paginate

| Name    | Type    | Required | Default | Description                                                                            |
| ------- | ------- | -------- | ------- | -------------------------------------------------------------------------------------- |
| page    | numeric | `false`  | `1`     | The page number to retrieve.                                                           |
| maxRows | numeric | `false`  | `25`    | The number of records per page.  If a number less than 0 is passed, 0 is used instead. |
| options | struct  | `false`  | `{}`    | Any additional `queryExecute` options.                                                 |

Generates a pagination struct along with the results of the executed query. It does this by calling both `count` and `forPage`.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .paginate();
```

{% endcode %}

{% code title="Results" %}

```javascript
{
    "pagination": {
        "maxRows": 25,
        "offset": 0,
        "page": 1,
        "totalPages": 2,
        "totalRecords": 45
    },
    "results": [ { /* ... */ }, ]
}
```

{% endcode %}

The behavior when a `maxRows` of 0 or lower is passed is determined by the `shouldMaxRowsOverrideToAll` callback function. The default callback returns all rows for values `<= 0`. You can customize this behavior by passing a new callback to the `shouldMaxRowsOverrideToAll` setting or `init` argument.

## simplePaginate

| Name    | Type    | Required | Default | Description                                                                            |
| ------- | ------- | -------- | ------- | -------------------------------------------------------------------------------------- |
| page    | numeric | `false`  | `1`     | The page number to retrieve.                                                           |
| maxRows | numeric | `false`  | `25`    | The number of records per page.  If a number less than 0 is passed, 0 is used instead. |
| options | struct  | `false`  | `{}`    | Any additional `queryExecute` options.                                                 |

Generates a simple pagination struct along with the results of the executed query. It does so without getting a `count` of the number of records the query would return.  This can be desirable for performance reasons if your query count is rather large.  It instead determines if there are more records by asking for one more row that your specified `maxRows`.  If the number of rows returned exceeds your specified `maxRows` then the pagination returns `hasMore: true`.  The `results` will always contain your specified `maxRows` (or less, if there aren't enough records).

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .simplePaginate();
```

{% endcode %}

{% code title="Results" %}

```javascript
{
    "pagination": {
        "maxRows": 25,
        "offset": 0,
        "page": 1,
        "hasMore": true
    },
    "results": [ { /* ... */ }, ]
}
```

{% endcode %}

The behavior when a `maxRows` of 0 or lower is passed is determined by the `shouldMaxRowsOverrideToAll` callback function. The default callback returns all rows for values `<= 0`. You can customize this behavior by passing a new callback to the `shouldMaxRowsOverrideToAll` setting or `init` argument.

### Custom Pagination Collectors

A pagination collector is the name given to the struct returned from calling the [`paginate`](/12.1.0/query-builder/executing-queries/retrieving-results#paginate) method. It can be a struct or a component. It needs one function defined and will be passed the following parameters.

#### generateWithResults

| Name         | Type    | Description                                                                                            |
| ------------ | ------- | ------------------------------------------------------------------------------------------------------ |
| totalRecords | numeric | The total records count.                                                                               |
| results      | any     | The results of the query execution.  It will be passed as whatever return format the user has defined. |
| page         | numeric | The current page number.                                                                               |
| maxRows      | numeric | The maximum number of rows retrieved per page.                                                         |

You can set your custom pagination collector either in the constructor using the `paginationCollector` argument or by calling `setPaginationCollector` on a query builder instance.

By default, qb ships with [`cbpaginator`](https://forgebox.io/view/cbpaginator) as its pagination collector. The return format of `cbpaginator` is the example shown above.

In qb 8.4.0 the `simplePaginate` method was added.  This uses a new method on the `paginationCollector`.

#### generateSimpleWithResults

| Name    | Type    | Description                                                                                            |
| ------- | ------- | ------------------------------------------------------------------------------------------------------ |
| results | any     | The results of the query execution.  It will be passed as whatever return format the user has defined. |
| page    | numeric | The current page number.                                                                               |
| maxRows | numeric | The maximum number of rows retrieved per page.                                                         |

{% hint style="info" %}
If you use a custom `paginationCollector`, ensure it has been updated with this new `generateSimpleWithResults` method before calling `simplePaginate`.
{% endhint %}


# Aggregates

The query builder also provides a variety of aggregate methods such as `count`, `max`, `min`, and `sum`. These methods take the headache out of setting up these common aggregate functions.

When executing any of the aggregate functions, any `where` restrictions on your query will still be applied.

Instead of returning a query, these methods return a simple value.

## exists

| Name    | Type    | Required | Default | Description                                                 |
| ------- | ------- | -------- | ------- | ----------------------------------------------------------- |
| options | struct  | `false`  | `{}`    | Any additional `queryExecute` options.                      |
| toSQL   | boolean | `false`  | `false` | Returns the query as SQL, if true, instead of executing it. |

Returns `true` if the query returns any rows.  Returns `false` otherwise.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).where( "username", "like", "jon%" ).exists();
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT COUNT(*) AS aggregate FROM `users` WHERE `username` LIKE 'jon%'
```

{% endcode %}

## existsOrFail

| Name         | Type     | Required | Default | Description                            |
| ------------ | -------- | -------- | ------- | -------------------------------------- |
| options      | `struct` | false    | `{}`    | Any additional `queryExecute` options. |
| errorMessage | `string` | false    |         | An optional string error message.      |

Returns `true` if the query returns any rows.  Throws a `RecordNotFound` exception otherwise.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).where( "username", "like", "jon%" ).existsOrFail();
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT COUNT(*) AS aggregate FROM `users` WHERE `username` LIKE 'jon%'
```

{% endcode %}

## count

| Name         | Type    | Required | Default | Description                                                          |
| ------------ | ------- | -------- | ------- | -------------------------------------------------------------------- |
| column       | string  | `false`  | `"*"`   | The column on which to count records.                                |
| defaultValue | any     | `false`  | `0`     | The default value for the `COUNT` query, if no records are returned. |
| options      | struct  | `false`  | `{}`    | Any additional `queryExecute` options.                               |
| toSQL        | boolean | `false`  | `false` | Returns the query as SQL, if true, instead of executing it.          |

Returns an integer number of rows returned by the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).count();
```

{% endcode %}

{% tabs %}
{% tab title="SQL (MySQL)" %}

```sql
SELECT COUNT(*) AS aggregate FROM `users`
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
SELECT COUNT(*) FROM [users]
```

{% endtab %}
{% endtabs %}

## max

| Name         | Type   | Required | Default | Description                                                        |
| ------------ | ------ | -------- | ------- | ------------------------------------------------------------------ |
| column       | string | `true`   |         | The column on which to find the max.                               |
| defaultValue | any    | `false`  |         | The default value for the `MAX` query, if no records are returned. |
| options      | struct | `false`  | `{}`    | Any additional `queryExecute` options.                             |

Returns the maximum value for the given column.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).max( "age" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT MAX(age) AS aggregate FROM `users`
```

{% endcode %}

## min

| Name         | Type   | Required | Default | Description                                                        |
| ------------ | ------ | -------- | ------- | ------------------------------------------------------------------ |
| column       | string | `true`   |         | The column on which to find the min.                               |
| defaultValue | any    | `false`  |         | The default value for the `MIN` query, if no records are returned. |
| options      | struct | `false`  | `{}`    | Any additional `queryExecute` options.                             |

Returns the minimum value for the given column.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).min( "age" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT MIN(age) AS aggregate FROM `users`
```

{% endcode %}

## sum

| Name         | Type   | Required | Default | Description                                                        |
| ------------ | ------ | -------- | ------- | ------------------------------------------------------------------ |
| column       | string | `true`   |         | The column to sum.                                                 |
| defaultValue | any    | `false`  | `0`     | The default value for the `SUM` query, if no records are returned. |
| options      | struct | `false`  | `{}`    | Any additional `queryExecute` options.                             |

Returns the sum of all returned rows for the given column.

{% code title="QueryBuilder" %}

```javascript
query.from( "employees" ).sum( "salary" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT SUM(salary) AS aggregate FROM `employees`
```

{% endcode %}

## sumRaw

| Name    | Type   | Required | Default | Description                            |
| ------- | ------ | -------- | ------- | -------------------------------------- |
| column  | string | `true`   |         | The column to sum.                     |
| options | struct | `false`  | `{}`    | Any additional `queryExecute` options. |

Returns the sum of all returned rows for the expression.

{% code title="QueryBuilder" %}

```javascript
query.from( "accounts" ).sumRaw( "netAdditions + netTransfers" )
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT SUM(netAdditions + netTransfers) AS aggregate FROM `accounts`
```

{% endcode %}

## columnList

| Name       | Type    | Required | Default | Description                                                     |
| ---------- | ------- | -------- | ------- | --------------------------------------------------------------- |
| asQuery    | boolean | `false`  | `false` | Flag to retrieve the columnList as a query instead of an array. |
| datasource | string  | `false`  |         | Optional datasource to from which to retrieve the columnList.   |

Retrieves the columns for the configured table.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).columnList();
```

{% endcode %}

{% code title="Result" %}

```json
[ "id", "firstName", "lastName", "username", "email", "password" ]
```

{% endcode %}


# Inserts, Updates, and Deletes

The following methods all have the same return value:

```javascript
{
    "result": "Value of the `result` parameter to `queryExecute`",
    "query": "Return value of running `queryExecute` - a CFML query object"
}
```

{% hint style="info" %}
`insert`, `update`, and `delete` actions always return a query object for `query`, regardless of your configured `returnFormat`.
{% endhint %}

## insert

| Name    | Type                     | Required | Default | Description                                                                               |
| ------- | ------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------- |
| values  | struct \| array\<struct> | `true`   |         | A struct or array of structs to insert in to the table.                                   |
| options | struct                   | `false`  | `{}`    | Any additional `queryExecute` options.                                                    |
| toSQL   | boolean                  | `false`  | `false` | If `true`, returns the raw SQL string instead of running the query. Useful for debugging. |

{% hint style="warning" %}
This call must come after setting the query's table using [`from`](/12.1.0/query-builder/building-queries/from#get) or [`table`](/12.1.0/query-builder/building-queries/from#get-1).
{% endhint %}

You can insert a single record by passing a struct:

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .insert( {
        "name" = "Robert",
        "email" = "robert@test.com",
        "age" = 55
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
INSERT INTO `users` (`age`, `email`, `name`)
VALUES (?, ?, ?)
```

{% endcode %}

You can specify any [query param](/12.1.0/query-builder/building-queries/parameters-and-bindings#custom-parameter-types) options such as the SQL type by passing a struct with the parameters you would pass to [`cfqueryparam`](https://cfdocs.org/cfqueryparam).

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .insert( {
        "name" = "Robert",
        "email" = "robert@test.com",
        "age" = { value = 55, cfsqltype = "CF_SQL_INTEGER" }
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
INSERT INTO `users` (`age`, `email`, `name`)
VALUES (?, ?, ?)
```

{% endcode %}

Raw values can be supplied to an insert statement.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .insert( {
        "name" = "Robert",
        "email" = "robert@test.com",
        "updatedDate" = query.raw( "NOW()" )
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
INSERT INTO `users` (`age`, `email`, `updatedDate`)
VALUES (?, ?, NOW())
```

{% endcode %}

Multiple rows can be inserted in a batch by passing an array of structs to `insert`.

{% hint style="info" %}
This is not the same as looping over and array and calling `insert` in the loop. Using an array with `insert` will batch the inserts in one SQL call. Looping over an array and calling `insert` each time will create a SQL request for each item in the array. Bottom line, pass your array to `insert`!
{% endhint %}

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).insert( [
    { "email" = "john@example.com", "name" = "John Doe" },
    { "email" = "jane@example.com", "name" = "Jane Doe" }
] );
```

{% endcode %}

{% tabs %}
{% tab title="MySQL" %}

```sql
INSERT INTO `users` (`email`, `name`)
VALUES (?, ?), (?, ?)
```

{% endtab %}

{% tab title="Oracle" %}

```sql
INSERT ALL
INTO "USERS" ("EMAIL", "NAME") VALUES (?, ?)
INTO "USERS" ("EMAIL", "NAME") VALUES (?, ?)
SELECT 1 FROM dual
```

{% endtab %}
{% endtabs %}

## insertIgnore

| Name    | Type                     | Required | Default | Description                                                                               |
| ------- | ------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------- |
| values  | struct \| array\<struct> | true     |         | A struct or array of structs to insert in to the table.                                   |
| target  | array\<string>           | false    | `[]`    | An array of key column names to match on. (SQL Server and Oracle grammars only.)          |
| options | struct                   | false    | `{}`    | Any additional `queryExecute` options.                                                    |
| toSQL   | boolean                  | false    | `false` | If `true`, returns the raw SQL string instead of running the query. Useful for debugging. |

{% hint style="warning" %}
This call must come after setting the query's table using [`from`](/12.1.0/query-builder/building-queries/from#get) or [`table`](/12.1.0/query-builder/building-queries/from#get-1).
{% endhint %}

Inserts data into a table while ignoring duplicate key conflicts.

{% hint style="info" %}
`target` is only required for `SQLServerGrammar` and `OracleGrammar`
{% endhint %}

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .insertIgnore(
        values = [
            { "email" = "foo", "name" = "bar" },
            { "email" = "baz", "name" = "bam" }
        ],
        target = [ "email" ]
    );
```

{% endcode %}

{% tabs %}
{% tab title="MySQL" %}

```sql
INSERT IGNORE INTO `users` (`email`, `name`)
VALUES (?, ?), (?, ?)
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
MERGE [users] AS [qb_target]
USING (VALUES (?, ?), (?, ?)) AS [qb_src] ([email], [name])
ON [qb_target].[email] = [qb_src].[email]
WHEN NOT MATCHED BY TARGET THEN
INSERT ([email], [name]) VALUES ([email], [name]);
```

{% endtab %}

{% tab title="Postgres" %}

```sql
INSERT INTO "users" ("email", "name")
VALUES (?, ?), (?, ?)
ON CONFLICT DO NOTHING
```

{% endtab %}

{% tab title="Oracle" %}

```sql
MERGE INTO "USERS" "QB_TARGET"
USING (SELECT ?, ? FROM dual UNION ALL SELECT ?, ? FROM dual) "QB_SRC"
ON "QB_TARGET"."EMAIL" = "QB_SRC"."EMAIL"
WHEN NOT MATCHED THEN
INSERT ("EMAIL", "NAME")
VALUES ("QB_SRC"."EMAIL", "QB_SRC"."NAME")
```

{% endtab %}
{% endtabs %}

## insertUsing

| Name    | Type                     | Required | Default | Description                                                                                                                                |
| ------- | ------------------------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| source  | function \| QueryBuilder | true     |         | A callback or builder instance to serve as the source of the insert.                                                                       |
| columns | array\<string>           | false    |         | An array of column names that will be inserted. If no columns are passed, the columns will be derived from the source columns and aliases. |
| options | struct                   | false    | `{}`    | Any additional `queryExecute` options.                                                                                                     |
| toSQL   | boolean                  | false    | `false` | If `true`, returns the raw SQL string instead of running the query. Useful for debugging.                                                  |

{% hint style="warning" %}
This call must come after setting the query's table using [`from`](/12.1.0/query-builder/building-queries/from#get) or [`table`](/12.1.0/query-builder/building-queries/from#get-1).
{% endhint %}

Inserts data into a table using a subquery as the source.

```javascript
qb.from( "users" )
    .insertUsing( function( q ) {
        q.from( "activeDirectoryUsers" )
            .select( [ "email", "modifiedDate AS createdDate" ] )
            .where( "active", 1 );
    } );
```

```sql
INSERT INTO `users` (`email`, `createdDate`)
SELECT `email`, `modifiedDate` AS `createdDate`
FROM `activeDirectoryUsers`
WHERE `active` = ?
```

You can also pass in an array of column names to avoid aliasing in your source query.

```javascript
qb.from( "users" )
    .insertUsing(
        columns = [ "email", "createdDate" ],
        source = function( q ) {
            q.from( "activeDirectoryUsers" )
                 .select( [ "email", "modifiedDate" ] )
                 .where( "active", 1 );
        }
    );
```

```sql
INSERT INTO `users` (`email`, `createdDate`)
SELECT `email`, `modifiedDate`
FROM `activeDirectoryUsers`
WHERE `active` = ?
```

Alternatively, the source can be defined as a QueryBuilder object:

```cfscript
qb.from( "users" )
    .insertUsing(
        qb.newQuery()
            .from( "activeDirectoryUsers" )
            .select( [ "email", "modifiedDate AS createdDate" ] )
            .where( "active", 1 )
    );
```

```sql
INSERT INTO `users` (`email`, `createdDate`)
SELECT `email`, `modifiedDate` AS `createdDate`
FROM `activeDirectoryUsers`
WHERE `active` = ?
```

## update

| Name    | Type    | Required | Default | Description                                                                                                                                           |
| ------- | ------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| values  | struct  | `false`  | `{}`    | A struct of column and value pairs to update. These column and value pairs are appended to any already set with the [`addUpdate`](#addupdate) method. |
| options | struct  | `false`  | `{}`    | Any additional `queryExecute` options.                                                                                                                |
| toSQL   | boolean | `false`  | `false` | If `true`, returns the raw SQL string instead of running the query. Useful for debugging.                                                             |

{% hint style="warning" %}
This call must come after setting the query's table using [`from`](/12.1.0/query-builder/building-queries/from#get) or [`table`](/12.1.0/query-builder/building-queries/from#get-1).
{% endhint %}

Updates a table with a struct of column and value pairs.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .update( {
        "email" = "foo",
        "name" = "bar"
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
UPDATE `users`
SET `email` = ?,
    `name` = ?
```

{% endcode %}

You can specify any [query param](/12.1.0/query-builder/building-queries/parameters-and-bindings#custom-parameter-types) options such as the SQL type by passing a struct with the parameters you would pass to [`cfqueryparam`](https://cfdocs.org/cfqueryparam).

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .update( {
        "email" = "foo",
        "name" = "bar",
        "updatedDate" = { value = now(), cfsqltype = "CF_SQL_TIMESTAMP" }
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
UPDATE `users`
SET `email` = ?,
    `name` = ?,
    `updatedDate` = ?
```

{% endcode %}

Any constraining of the update query should be done using the appropriate [WHERE](/12.1.0/query-builder/building-queries/wheres) statement before calling `update`.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereId( 1 )
    .update( {
        "email" = "foo",
        "name" = "bar"
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
UPDATE `users`
SET `email` = ?,
    `name` = ?
WHERE `Id` = ?
```

{% endcode %}

You can update a column based on another column using a raw expression.

{% code title="QueryBuilder" %}

```javascript
query.from( "hits" )
    .where( "page", "someUrl" )
    .update( {
        "count" = query.raw( "count + 1" )
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
UPDATE `hits`
SET `count` = count + 1
WHERE `page` = ?
```

{% endcode %}

### Updating Null values

Null values can be inserted by using queryparam syntax:

```sql
query.from("user")
		.whereId( 10 )
		.update( {
			manager_FK = { value = "", null=true },
		} )
```

if you are using full null support the following (easier) syntax is also allowed:

```sql
query.from("user")
		.whereId( 10 )
		.update( {
			manager_FK = { value = null },
		} )
```

### Updating with Subselects

Subselects can be used to update values by passing a closure as the value

```sql
qb.table( "employees" )
    .update( {
		    "departmentName" = function( q ) {
		        q.from( "departments" )
		            .select( "name" )
		            .whereColumn( "employees.departmentId", "departments.id" );
		    } )
		} );
```

{% tabs %}
{% tab title="MySQL" %}

```sql
UPDATE `employees`
SET `departmentName` = (
    SELECT `name`
    FROM `departments`
    WHERE `employees`.`departmentId` = `departments`.`id`
)
```

{% endtab %}
{% endtabs %}

You can also pass a builder instance in place of the closure.

```sql
qb.table( "employees" )
    .update( {
		    "departmentName" = qb.newQuery()
		        .from( "departments" )
		        .select( "name" )
		        .whereColumn( "employees.departmentId", "departments.id" )
		    } )
		} );
```

### Updating with Joins

qb will correctly format `JOIN` clauses in your `UPDATE` statements for your database grammar.

{% hint style="danger" %}
`OracleGrammar` **does not support** `JOIN` clauses in`UPDATE` statements. Consider using [subselects](#updating-with-subselects) in your `UPDATE` statement instead.
{% endhint %}

```sql
qb.table( "employees" )
    .join( "departments", "departments.id", "employees.departmentId" )
    .update( {
        "employees.departmentName": qb.raw( "departments.name" )
    } );
```

{% tabs %}
{% tab title="MySQL" %}

```sql
UPDATE `employees`
INNER JOIN `departments`
    ON `departments`.`id` = `employees`.`departmentId`
SET `employees`.`departmentName` = departments.name
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
UPDATE [employees]
SET [employees].[departmentName] = departments.name
FROM [employees]
INNER JOIN [departments]
    ON [departments].[id] = [employees].[departmentId]
```

{% endtab %}

{% tab title="Postgres" %}

```sql
UPDATE "employees"
SET "employees"."departmentName" = departments.name
FROM "departments"
WHERE "departments"."id" = "employees"."departmentId"
```

{% endtab %}
{% endtabs %}

## addUpdate

| Name   | Type   | Required | Default | Description                                                     |
| ------ | ------ | -------- | ------- | --------------------------------------------------------------- |
| values | struct | `true`   |         | A struct of column and value pairs to add to the update clause. |

Adds values to a later [`update`](#update), similar to [`addSelect`](/12.1.0/query-builder/building-queries/selects#get-2).

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereId( 1 )
    .addUpdate( {
        "email" = "foo",
        "name" = "bar"
    } )
    .when( true, function( q ) {
        q.addUpdate( {
            "foo": "yes"
        } );
    } )
    .when( false, function( q ) {
        q.addUpdate( {
            "bar": "no"
        } );
    } )
    .update();
```

{% endcode %}

{% code title="MySQL" %}

```sql
UPDATE `users`
SET `email` = ?,
    `foo` = ?,
    `name` = ?
WHERE `Id` = ?
```

{% endcode %}

## updateOrInsert

| Name    | Type    | Required | Default | Description                                                                               |
| ------- | ------- | -------- | ------- | ----------------------------------------------------------------------------------------- |
| values  | struct  | `true`   |         | A struct of column and value pairs to either update or insert.                            |
| options | boolean | `false`  | `{}`    | Any additional `queryExecute` options.                                                    |
| toSql   | boolean | `false`  | `false` | If `true`, returns the raw SQL string instead of running the query. Useful for debugging. |

Performs an update statement if the configured query returns `true` for `exists`. Otherwise, performs an insert statement.

If an update statement is performed qb applies a `limit( 1 )` to the update statement.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "email", "foo" )
    .updateOrInsert( {
        "email" = "foo",
        "name" = "baz"
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
UPDATE `users`
SET `email` = ?,
    `name` = ?
WHERE `email` = ?
LIMIT 1
```

{% endcode %}

If the configured query returns 0 records, then an insert statement is performed.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "email", "foo" )
    .updateOrInsert( {
        "email" = "foo",
        "name" = "baz"
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
INSERT INTO `users` (`email`, `name`)
VALUES (?, ?)
```

{% endcode %}

## upsert

| Name            | Type                                       | Required | Default | Description                                                                                                                                                                                                                                                                    |
| --------------- | ------------------------------------------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| values          | struct \| array\<struct> \| array\<string> | `true`   |         | A struct or array of structs to insert into or update on the table. If a `source` is provided, this should be an array of column names to update instead.                                                                                                                      |
| target          | string \| array\<string>                   | `true`   |         | A column name or array of column names to match the values to the table. If a match is found, the record will be updated. Otherwise, a new record will be inserted. Most database grammars required these columns to have either a primary key or a unique index.              |
| update          | array \| struct                            | `false`  | `null`  | Either an array of columns to update using the current `value` matched or a struct containing the column names as keys and the corresponding to update. If blank, it will update all the columns in the passed in `value`.                                                     |
| source          | function \| QueryBuilder                   | `false`  | `null`  | A callback function or QueryBuilder object to use as the source for the upsert. When using this parameter, `values` must be an array of column names to update.                                                                                                                |
| deleteUnmatched | any                                        | `false`  | `false` | <p>Boolean flag or callback to delete any unmatched source records as part the upsert. (SQL Server only.)<br><br>If a callback is passed, it will be called with a <code>QueryBuilder</code> instance that can be restricted for the <code>DELETE UNMATCHED</code> clause.</p> |
| options         | boolean                                    | `false`  | `{}`    | Any additional `queryExecute` options.                                                                                                                                                                                                                                         |
| toSql           | boolean                                    | `false`  | `false` | If `true`, returns the raw SQL string instead of running the query. Useful for debugging.                                                                                                                                                                                      |

An upsert is a batch operation that either inserts or updates a row depending on if a target match is found. If a row is matched with the target column(s), then the matched row is updated. Otherwise a new row is inserted.

{% hint style="warning" %}
In most database grammars, the target columns are required to be primary key or unique indexes.
{% endhint %}

```sql
qb.table( "users" )
    .upsert(
        values = [
            {
                "username": "johndoe",
                "active": 1,
                "createdDate": "2021-09-08 12:00:00",
                "modifiedDate": "2021-09-08 12:00:00"
            },
            {
                "username": "janedoe",
                "active": 1,
                "createdDate": "2021-09-10 10:42:13",
                "modifiedDate": "2021-09-10 10:42:13"
            },
        ],
        target = [ "username" ],
        update = [ "active", "modifiedDate" ],
    );
```

{% tabs %}
{% tab title="MySQL" %}

```sql
INSERT INTO `users`
    (`active`, `createdDate`, `modifiedDate`, `username`)
VALUES
    (?, ?, ?, ?),
    (?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
    `active` = VALUES(`active`),
    `modifiedDate` = VALUES(`modifiedDate`)
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
MERGE [users] AS [qb_target]
USING (VALUES (?, ?, ?, ?), (?, ?, ?, ?)) AS [qb_src]
    ([active], [createdDate], [modifiedDate], [username])
ON [qb_target].[username] = [qb_src].[username]
WHEN MATCHED THEN UPDATE
    SET [active] = [qb_src].[active],
        [modifiedDate] = [qb_src].[modifiedDate]
WHEN NOT MATCHED BY TARGET THEN INSERT
    ([active], [createdDate], [modifiedDate], [username])
    VALUES
    ([active], [createdDate], [modifiedDate], [username])
```

{% endtab %}

{% tab title="Postgres" %}

```sql
INSERT INTO "users"
    ("active", "createdDate", "modifiedDate", "username")
VALUES
    (?, ?, ?, ?),
    (? ,? ,? ,?)
ON CONFLICT ("username") DO UPDATE
    "active" = EXCLUDED."active",
    "modifiedDate" = EXCLUDED."modifiedDate"
```

{% endtab %}

{% tab title="Oracle" %}

```sql
MERGE INTO "USERS" "QB_TARGET"
USING (
    SELECT ?, ?, ?, ? FROM dual
    UNION ALL
    SELECT ?, ?, ?, ? FROM dual
) "QB_SRC"
ON "QB_TARGET"."USERNAME" = "QB_SRC"."USERNAME"
WHEN MATCHED THEN UPDATE
    SET "ACTIVE" = "QB_SRC"."ACTIVE",
        "MODIFIEDDATE" = "QB_SRC"."MODIFIEDDATE"
WHEN NOT MATCHED THEN INSERT
    ("ACTIVE", "CREATEDDATE", "MODIFIEDDATE", "USERNAME")
    VALUES
    ("QB_SRC"."ACTIVE", "QB_SRC"."CREATEDDATE", "QB_SRC"."MODIFIEDDATE", "QB_SRC"."USERNAME")
```

{% endtab %}
{% endtabs %}

The update clause in a upsert can also accept raw values, making it very useful for tracking data like statistics.

```sql
qb.table( "stats" )
    .upsert(
        values = [
            { "postId": 1, "viewedDate": "2021-09-08", "views": 1 },
            { "postId": 2, "viewedDate": "2021-09-08", "views": 1 }
        ],
        target = [ "postId", "viewedDate" ],
        update = { "views": qb.raw( "stats.views + 1" ) }
    );
```

{% tabs %}
{% tab title="MySQL" %}

```sql
INSERT INTO `stats`
    (`postId`, `viewedDate`, `views`)
VALUES
    (?, ?, ?),
    (?, ?, ?)
ON DUPLICATE KEY UPDATE
    `views` = stats.views + 1
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
MERGE [stats] AS [qb_target]
USING (VALUES (?, ?, ?), (?, ?, ?)) AS [qb_src]
    ([postId], [viewedDate], [views])
ON [qb_target].[postId] = [qb_src].[postId]
    AND [qb_target].[viewedDate] = [qb_src].[viewedDate]
WHEN MATCHED THEN UPDATE
    SET [views] = stats.views + 1
WHEN NOT MATCHED BY TARGET THEN INSERT
    ([postId], [viewedDate], [views])
    VALUES
    ([postId], [viewedDate], [views])
```

{% endtab %}

{% tab title="Postgres" %}

```sql
INSERT INTO "stats"
    ("postId", "viewedDate", "views")
VALUES
    (?, ?, ?),
    (?, ?, ?)
ON CONFLICT ("postId", "viewedDate") DO UPDATE
    "views" = stats.views + 1
```

{% endtab %}

{% tab title="Oracle" %}

```sql
MERGE INTO "STATS" "QB_TARGET"
USING (
    SELECT ?, ?, ? FROM dual
    UNION ALL
    SELECT ?, ?, ? FROM dual
) "QB_SRC"
ON "QB_TARGET"."POSTID" = "QB_SRC"."POSTID"
    AND "QB_TARGET"."VIEWEDDATE" = "QB_SRC"."VIEWEDDATE"
WHEN MATCHED THEN UPDATE
    SET "VIEWS" = stats.views + 1
WHEN NOT MATCHED THEN INSERT
    ("POSTID", "VIEWEDDATE", "VIEWS")
    VALUES
    ("QB_SRC"."POSTID", "QB_SRC"."VIEWEDDATE", "QB_SRC"."VIEWS")
```

{% endtab %}
{% endtabs %}

A source callback or QueryBuilder instance can be used instead of explicit values. This allows you to do upserts across tables or subqueries.

To do this, provide a `source` that is either a function to configure a new QueryBuilder instance or an already configured QueryBuilder instance. Then specify the columns that will be affected as an array of strings to `values`.

```sql
qb.table( "stats" )
    .upsert(
        source = function( q ) {
            q.from( "activeDirectoryUsers" )
                .select( [
                    "username",
                    "active",
                    "createdDate",
                    "modifiedDate"
                ] );
        },
        values = [ "username", "active", "createdDate", "modifiedDate" ],
        target = [ "username" ],
        update = [ "active", "modifiedDate" ]
    );
```

{% tabs %}
{% tab title="MySQL" %}

```sql
INSERT INTO `users`
    (`username`, `active`, `createdDate`, `modifiedDate`)
SELECT `username`, `active`, `createdDate`, `modifiedDate`
FROM `activeDirectoryUsers`
ON DUPLICATE KEY UPDATE
    `active` = VALUES(`active`),
    `modifiedDate` = VALUES(`modifiedDate`)
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
MERGE [users] AS [qb_target]
USING (
    SELECT [username], [active], [createdDate], [modifiedDate]
    FROM [activeDirectoryUsers]
) AS [qb_src]
ON [qb_target].[username] = [qb_src].[username]
WHEN MATCHED THEN UPDATE
    SET [active] = [qb_src].[active],
        [modifiedDate] = [qb_src].[modifiedDate]
WHEN NOT MATCHED BY TARGET THEN INSERT
    ([username], [active], [createdDate], [modifiedDate])
VALUES ([username], [active], [createdDate], [modifiedDate]);
```

{% endtab %}

{% tab title="Postgres" %}

```sql
INSERT INTO "users"
("username", "active", "createdDate", "modifiedDate")
SELECT "username", "active", "createdDate", "modifiedDate"
FROM "activeDirectoryUsers"
ON CONFLICT ("username") DO UPDATE
    "active" = EXCLUDED."active",
    "modifiedDate" = EXCLUDED."modifiedDate"
```

{% endtab %}

{% tab title="Oracle" %}

```sql
MERGE INTO "USERS" "QB_TARGET"
USING (
    SELECT "USERNAME", "ACTIVE", "CREATEDADATE", "MODIFIEDDATE"
    FROM "ACTIVEDIRECTORYUSERS"
) "QB_SRC"
ON "QB_TARGET"."USERNAME" = "QB_SRC"."USERNAME"
WHEN MATCHED THEN UPDATE
    SET "ACTIVE" = "QB_SRC"."ACTIVE",
        "MODIFIEDDATE" = "QB_SRC"."MODIFIEDDATE"
WHEN NOT MATCHED THEN INSERT
    ("USERNAME", "ACTIVE", "CREATEDDATE", "MODIFIEDDATE")
    VALUES
    (
        "QB_SRC"."USERNAME",
        "QB_SRC"."ACTIVE",
        "QB_SRC"."CREATEDDATE",
        "QB_SRC"."MODIFIEDDATE"
    )
```

{% endtab %}
{% endtabs %}

## delete

| Name     | Type    | Required | Default | Description                                                                                                                                                                   |
| -------- | ------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| id       | any     | `false`  |         | A convenience argument for \`where( "id", "=", arguments.id ). The query can be constrained by normal [WHERE](/12.1.0/query-builder/building-queries/wheres) methods as well. |
| idColumn | string  | `false`  | `"id"`  | The name of the id column for the delete shorthand.                                                                                                                           |
| options  | boolean | `false`  | `{}`    | Any additional `queryExecute` options.                                                                                                                                        |
| toSql    | boolean | `false`  | `false` | If `true`, returns the raw SQL string instead of running the query. Useful for debugging.                                                                                     |

Deletes all records that the query returns.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "email", "foo" )
    .delete();
```

{% endcode %}

{% code title="MySQL" %}

```sql
DELETE FROM `users`
WHERE `email` = ?
```

{% endcode %}

The `id` argument is a convenience to delete a single record by id.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .delete( 1 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
DELETE FROM `users`
WHERE `id` = ?
```

{% endcode %}

## returning

| Name    | Type            | Required | Default | Description                                                                                   |
| ------- | --------------- | -------- | ------- | --------------------------------------------------------------------------------------------- |
| columns | string \| array | `true`   |         | A single column, a list or columns, or an array of columns to return from the inserted query. |

{% hint style="danger" %}
`returning` is only supported in `PostgresGrammar`, `SqlServerGrammar`, and `SQLiteGrammar`. Using this method on unsupported grammars will result in an `UnsupportedOperation` exception. Be aware that using this method constrains your grammar choices.
{% endhint %}

Specifies columns to be returned from the insert query.

<pre class="language-javascript" data-title="QueryBuilder"><code class="lang-javascript">query.from( "users" )
    .returning( "id" )
    .insert( {
        "email" = "foo",
        "name" = "bar"
<strong>    } );
</strong></code></pre>

{% tabs %}
{% tab title="SQL Server" %}

```sql
INSERT INTO [users] ([email], [name])
OUTPUT INSERTED.[id]
VALUES (?, ?)
```

{% endtab %}

{% tab title="Postgres" %}

```sql
INSERT INTO "users" ("email", "name")
VALUES (?, ?)
RETURNING "id"
```

{% endtab %}

{% tab title="SQLite" %}

```sql
INSERT INTO "users" ("email", "name")
VALUES (?, ?)
RETURNING "id"
```

{% endtab %}
{% endtabs %}

The `returning` function also applies to `update` and `delete` calls.

{% code title="QueryBuilder" %}

```javascript
query.table( "users" )
    .returning( [ "id", "modifiedDate" ] )
    .where( "id", 1 )
    .update( { "email": "john@example.com" } );
```

{% endcode %}

{% tabs %}
{% tab title="SQL Server" %}

```sql
UPDATE [users]
SET [email] = ?
OUTPUT INSERTED.[id], INSERTED.[modifiedDate]
WHERE [id] = ?
```

{% endtab %}

{% tab title="Postgres" %}

```sql
UPDATE "users"
SET "email" = ?
WHERE "id" = ?
RETURNING "id", "modifiedDate"
```

{% endtab %}

{% tab title="SQLite" %}

```sql
UPDATE "users"
SET "email" = ?
WHERE "id" = ?
RETURNING "id", "modifiedDate"
```

{% endtab %}
{% endtabs %}

<pre class="language-javascript" data-title="QueryBuilder"><code class="lang-javascript"><strong>query.table( "users" )
</strong>    .returning( "id" )
    .where( "active", 0 )
    .delete();
</code></pre>

{% tabs %}
{% tab title="SQL Server" %}

```sql
DELETE FROM [users]
OUTPUT DELETED.[id]
WHERE [active] = ?
```

{% endtab %}

{% tab title="Postgres" %}

```sql
DELETE FROM "users" WHERE "active" = ?
RETURNING "id"
```

{% endtab %}

{% tab title="SQLite" %}

```sql
DELETE FROM "users" WHERE "active" = ?
RETURNING "id"
```

{% endtab %}
{% endtabs %}

You can also use `raw` Expressions in a `returning` call. This is especially useful for SQL Server returning both the old and new values from an `update` call.

{% code title="QueryBuilder" %}

```javascript
qb.from( "users" )
    .where( "id", 1 )
    .returningRaw( [
        "DELETED.modifiedDate AS oldModifiedDate",
        "INSERTED.modifiedDate AS newModifiedDate"
    ] )
    .update( { "email": "john@example.com" } );
```

{% endcode %}

{% tabs %}
{% tab title="SQL Server" %}

```sql
UPDATE [users]
SET [email] = ?
OUTPUT
    DELETED.modifiedDate AS oldModifiedDate,
    INSERTED.modifiedDate AS newModifiedDate
WHERE [id] = ?
```

{% endtab %}
{% endtabs %}

## returningAll

| Name         | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

Shortcut method for `returning( "*" )`.

<pre class="language-javascript" data-title="QueryBuilder"><code class="lang-javascript">query.from( "users" )
    .returningAll()
    .insert( {
        "email" = "foo",
        "name" = "bar"
<strong>    } );
</strong></code></pre>

{% tabs %}
{% tab title="SQL Server" %}

```sql
INSERT INTO [users] ([email], [name])
OUTPUT INSERTED.*
VALUES (?, ?)
```

{% endtab %}

{% tab title="Postgres" %}

```sql
INSERT INTO "users" ("email", "name")
VALUES (?, ?)
RETURNING *
```

{% endtab %}

{% tab title="SQLite" %}

```sql
INSERT INTO "users" ("email", "name")
VALUES (?, ?)
RETURNING *
```

{% endtab %}
{% endtabs %}


# Options and Utilities


# Query Options and Utilities

Each query execution method allows for the passing of an options struct. This is the same struct you would pass to [`queryExecute`](https://cfdocs.org/queryexecute).

## Default Options

qb allows you to specify default options when creating the QueryBuilder instance using the `defaultOptions` argument.

You can set `defaultOptions` for the default QueryBuilder (`QueryBuilder@qb`) in your `config/ColdBox.cfc` file under `moduleSettings`.

```javascript
moduleSettings = {
    "qb": {
        "defaultOptions": {
            "timeout": 60
        }
    }
};
```

You can also combine this with WireBox to create custom QueryBuilder instances pointing to different datasources and even different grammars.

{% hint style="info" %}
When mapping to components provided by modules, such as qb, use the [`afterAspectsLoad`](https://coldbox.ortusbooks.com/digging-deeper/interceptors/core-interception-points/application-life-cycle-events) interception point inside your `config/WireBox.cfc` to ensure all modules are fully loaded and available.
{% endhint %}

{% code title="config/WireBox.cfc" %}

```javascript
component {

    function afterAspectsLoad() {
        binder.map( "MyCustomQueryBuilder" )
            .to( "qb.models.Query.QueryBuilder" )
            .initArg( name = "grammar", ref = "AutoDiscover@qb" )
            .initArg( name = "defaultOptions", value = {
                "datasource": "my_custom_datasource" 
            } );
    }

}
```

{% endcode %}

## Retrieving results from alternative datasources

In `Application.cfc` you can specify your default datasource which will be used by qb. If you want to retrieve data from other datasources you can specify this in all retrieval functions by using the extra options parameter such as:

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .get( options = { datasource: "MyOtherDatasourceName" } );
```

{% endcode %}

If you also want to use a non-default SQL Grammar you have to specify this when creating your `QueryBuilder`.

{% code title="QueryBuilder" %}

```javascript
var query = wirebox.getInstance( "QueryBuilder@qb" )
    .setGrammar( wirebox.getInstance( "SqlServerGrammar@qb" ) );
```

{% endcode %}

## Replacing or Inlining Bindings

qb can inline the query bindings into the SQL string that it has built up.  This is used by other tools like [`toSQL`](/12.1.0/query-builder/debugging#tosql) or [`dump`](/12.1.0/query-builder/debugging#dump) to provide a richer debugging experience.  It is also publicly available for other libraries to use, such as [CommandBox Migrations](https://forgebox.io/view/commandbox-mgirations).

### replaceBindings

Replace the question marks (?) in a sql string with the bindings provided.

| Name     | Type            | Required | Default Value | Description                                                                                                                                      |
| -------- | --------------- | -------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| sql      | `String`        | true     |               | The SQL with question marks (`?`) to replace with bindings.                                                                                      |
| bindings | `Array<Struct>` | true     |               | The bindings to use when replacing the question marks (`?`) in the provided SQL string.                                                          |
| inline   | `boolean`       | false    | `false`       | Flag to inline the bindings value or not.  If `true`, a SQL-executable value will be replaced.  If `false`, the binding struct will be replaced. |

## withoutWrappingValues

Helper method to disable wrapping identifiers only for the given query.

```cfscript
qb.from( "users" ).select( [ "id", "email" ] ).withoutWrappingValues().get();
```

```sql
SELECT id, email FROM users
```

## withWrappingValues

Helper method to enable wrapping identifiers only for the given query.

```cfscript
qb.from( "users" ).select( [ "id", "email" ] ).withWrappingValues().get();
```

```sql
-- MySQL
SELECT `id`, `email` FROM `users`

-- SQL Server
SELECT [id], [email] FROM [users]

-- Postgres, SQLite, Oracle
SELECT "id", "email" FROM "users"
```


# Clone and Reset

## Clone

At times you may need to duplicate a query.  Using `clone` you have a performant way to duplicate a query without using the `duplicate` method.

{% code title="QueryBuilder" %}

```javascript
var q1 = query.from( "users" ).where( "firstName", "like", "Jo%" );
var q2 = q1.clone();
q2.getFrom(); // "users"
```

{% endcode %}

## Reset

When you need to remove all configuration for a query, you can call the `reset` method.

{% code title="QueryBuilder" %}

```javascript
var q1 = query.from( "users" ).where( "firstName", "like", "Jo%" );
var q2 = q1.reset();
q2.getColumns(); // "*"
```

{% endcode %}


# Return Format

`returnFormat` refers to the transformation your executed query makes (if any) before being returned to you. You can choose one of three return formats:

* `"array"`
* `"query"`
* `"none"`
* A custom function

By default, qb returns an array of structs as the result of your query. This is the same as specifying `array` as your `returnFormat`:

{% code title="config/ColdBox.cfc" %}

```javascript
moduleSettings = {
    "qb": {
        "returnFormat": "array"
    }
};
```

{% endcode %}

You can get the original query object that CFML generates by setting the `returnFormat` to `query`:

{% code title="config/ColdBox.cfc" %}

```javascript
moduleSettings = {
    "qb": {
        "returnFormat": "query"
    }
};
```

{% endcode %}

This setting can be overridden on a per-instance basis by calling `setReturnFormat()`:

{% code title="setReturnFormat" %}

```javascript
var qb = wirebox.getInstance( "QueryBuilder@qb" );

qb
   .setReturnFormat( 'query' )
   .from( 'users' )
   .get()
```

{% endcode %}

If you want complete control over your return result, you can provide a function as a `returnFormat`. The results of the function will be returned as the results of the builder.

{% code title="config/ColdBox.cfc" %}

```javascript
moduleSettings = {
    "qb": {
        "returnFormat": function( q ) {
            return application.wirebox.getInstance(
                "name" = "Collection",
                "initArguments" = { "collection": q }
            );
        }
    }
};
```

{% endcode %}


# Column Formatter

Available as an advanced option for framework authors, qb will call out to a column formatter prior to processing a column as part of the SQL query.  This allows frameworks like Quick to define queries using aliases and transform them to columns during execution.

You can provide your own column formatter function to qb through the `init` method or by calling `setColumnFormatter`.  It is a function that takes a column string and returns a string

```javascript
query.setColumnFormatter( function( column ) {
    return lcase( arguments.column );
} );
```


# Interception Points

Two interception points are available from QB: `preQBExecute` and `postQBExecute`. These fire before and after the `queryExecute` call, respectively.

## preQBExecute

The following information is available in the `interceptData` struct:

| Name         | Type   | Description                                             |
| ------------ | ------ | ------------------------------------------------------- |
| sql          | String | The SQL string to execute.                              |
| bindings     | Struct | The struct of bindings (keys and values) for the query. |
| options      | Struct | Any options to pass along to `queryExecute`.            |
| returnObject | String | The type to return: `query` or `result`.                |

## postQBExecute

The following information is available in the `interceptData` struct:

| Name         | Type          | Description                                             |
| ------------ | ------------- | ------------------------------------------------------- |
| sql          | String        | The SQL string to execute.                              |
| bindings     | Struct        | The struct of bindings (keys and values) for the query. |
| options      | Struct        | Any options to pass along to `queryExecute`.            |
| returnObject | String        | The type to return: `query` or `result`.                |
| query        | Query \| null | The query object or `null` if there isn't one.          |
| result       | Struct        | The query result struct.                                |


# Debugging

## Debugging a Single Query

### toSQL

| Name         | Type              | Required | Default  | Description                                                                                                                                                                                                                                                      |
| ------------ | ----------------- | -------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| showBindings | boolean \| string | `false`  | ​`false` | If `true`, the bindings for the query will be substituted back in where the question marks (`?`) appear as `cfqueryparam` structs.  If `inline`, the binding value will be substituted back creating a query that can be copy and pasted to run in a SQL client. |

Returns the SQL that would be executed for the current query.

{% code title="QueryBuilder" %}

```javascript
var q = query.from( "users" )
    .where( "active", "=", 1 );

writeOutput( q.toSQL() );
```

{% endcode %}

{% code title="Result" %}

```sql
SELECT * FROM "users" WHERE "active" = ?
```

{% endcode %}

The bindings for the query are represented by question marks (`?`) just as when using `queryExecute`.  qb can replace each question mark with the corresponding `cfqueryparam`-compatible struct by passing `showBindings = true` to the method.

{% code title="QueryBuilder" %}

```javascript
var q = query.from( "users" )
    .where( "active", "=", 1 );

writeOutput( q.toSQL( showBindings = true ) );
```

{% endcode %}

{% code title="Result" %}

```sql
SELECT * FROM "users" WHERE "active" = {"value":1,"cfsqltype":"CF_SQL_NUMERIC","null":false}
```

{% endcode %}

If you want to show the SQL that would be executed for the `update`, `insert`, `updateOrInsert`, or `delete` methods, you can pass a `toSQL = true` flag to those methods.  Please see those individual methods for more information.

To get back a SQL string that can be copied and pasted into a SQL client to run can be retrieved by passing `showBindings = "inline"`.

{% code title="QueryBuilder" %}

```cfscript
var q = query.from( "users" )
    .where( "active", "=", 1 );

writeOutput( q.toSQL( showBindings = "inline" ) );
```

{% endcode %}

{% code title="Result" %}

```sql
SELECT * FROM "users" WHERE "active" = 1
```

{% endcode %}

### tap

| Name     | Type     | Required | Default | Description                                              |
| -------- | -------- | -------- | ------- | -------------------------------------------------------- |
| callback | Function | `true`   | ​       | A function to execute with a clone of the current query. |

Executes a callback with a clone of the current query passed to it.  Any changes to the passed query is ignored and the original query returned.

While not strictly a debugging method, `tap` makes it easy to see the changes to a query after each call without introducing temporary variables.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .tap( function( q ) {
        writeOutput( q.toSQL() & "<br>" );
    } )
    .where( "active", "=", 1 )
    .tap( function( q ) {
        writeOutput( q.toSQL() & "<br>" );
    } );
```

{% endcode %}

{% code title="Result" %}

```sql
SELECT * FROM "users"
SELECT * FROM "users" WHERE "active" = ?
```

{% endcode %}

### dump

| Name         | Type              | Required | Default | Description                                                                                                                                                                                                                                                      |
| ------------ | ----------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| showBindings | boolean \| string | `false`  | `false` | If `true`, the bindings for the query will be substituted back in where the question marks (`?`) appear as `cfqueryparam` structs.  If `inline`, the binding value will be substituted back creating a query that can be copy and pasted to run in a SQL client. |

A shortcut for the most common use case of `tap`.  This forwards on the SQL for the current query to `writeDump`.  You can pass along any `writeDump` argument to `dump` and it will be forward on.  Additionally, the `showBindings` argument will be forwarded on to the `toSQL` call.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .dump()
    .where( "active", "=", 1 )
    .dump( label = "after where", showBindings = true, abort = true )
    .get();
```

{% endcode %}

{% code title="Result" %}

```sql
SELECT * FROM "users"
SELECT * FROM "users" WHERE "active" = ?
```

{% endcode %}

### pretend

A `QueryBuilder` instance can be put into pretend mode by calling the `pretend` method.  In this mode, the `QueryBuilder` will turn all query operations into no-ops. A log of the SQL that would have been executed can be retrieved from the query log.

Once a `QueryBuilder` instance has been set to pretend mode, it cannot be unset.  Instead, you will need to obtain a [new query](/12.1.0/query-builder/new-query).

### queryLog

Each instance of a `QueryBuilder` maintains a log of queries it executed.  This can be accessed by calling `getQueryLog`. This will return an array of structs like so:

```json
[
  {
    "sql": "SELECT * FROM `users` WHERE `active` = ?",
    "bindings": [ { "value": 1, "sqltype": "bit" } ],
    "options": { "datasource": "main" },
    "returnObject": "array",
    "pretend": false,
    "result": {},
    "executionTime": 21
  }
]
```

This can be very useful in combination with the [`pretend`](#pretend) feature to see what SQL will be executed before actually executing it.

## Debugging All Queries

### [sqlCommenter](/12.1.0/query-builder/debugging/sqlcommenter)

You can add contextual information as a comment to all executed queries using sqlCommenter, [a specification from Google](https://google.github.io/sqlcommenter/).

{% hint style="info" %}
For more information, check out the [dedicated sqlCommenter page](/12.1.0/query-builder/debugging/sqlcommenter).
{% endhint %}

{% content-ref url="/pages/X3oNqa1hvF9Bw01SeFxc" %}
[sqlCommenter](/12.1.0/query-builder/debugging/sqlcommenter)
{% endcontent-ref %}

### cbDebugger

Starting in [cbDebugger](https://forgebox.io/view/cbdebugger) 2.0.0 you can view all your qb queries for a request.  This is enabled by default if you have qb installed.  Make sure your debug output is configured correctly and scroll to the bottom of the page to find the debug output.

![](/files/-M6W633AL1y6DjHAk6pO)

### LogBox Appender

qb is set to log all queries to a debug log out of the box.  To enable this behavior, configure LogBox to allow debug logging from qb's grammar classes.

{% code title="config/ColdBox.cfc" %}

```sql
logbox = {
    debug = [ "qb.models.Grammars" ]
};
```

{% endcode %}

{% hint style="info" %}
qb can be quite chatty when executing many database queries.  Make sure that this logging is only enabled for your development environments using [ColdBox's environment controls](https://coldbox.ortusbooks.com/getting-started/configuration/coldbox.cfc/configuration-directives/environments).
{% endhint %}

### ColdBox Interception Points

ColdBox Interception Points can also be used for logging, though you may find it easier to use LogBox.  See the documentation for [qb's Interception Points](/12.1.0/query-builder/options-and-utilities/interception-points) for more information.


# sqlCommenter

qb supports the [sqlCommenter specification by Google](https://google.github.io/sqlcommenter/) for appending contextual information to executed queries.

sqlCommenter support is **off** by default, but can be activated by setting the `sqlCommenter.enabled` setting.

```cfscript
moduleSettings = {
    "qb": {
        "sqlCommenter": {
            "enabled": true
        }
    }
};
```

Once enabled, qb will append a comment on to every **non-commented** query. This happens as the query is ran, so you will not see this output when calling [`toSQL()`](#tosql) or [`dump()`](#dump).

{% hint style="warning" %}
sqlCommenter will only add a comment to **non-commented** queries.  If you query contains a comment anywhere in it, sqlCommenter will ignore it.
{% endhint %}

An example query with a sqlCommenter comment looks like this:

{% code overflow="wrap" %}

```sql
SELECT * FROM foo /*action='index',dbDriver='mysql-connector-java-8.0.25%20%28Revision%3A%2008be9e9b4cba6aa115f9b27b215887af40b159e0%29',event='Main.index',framework='coldbox-6.0.0',handler='Main',route='%2F'*/
```

{% endcode %}

### Configuring sqlCommenter

The default configuration structure for sqlCommenter is as follows:

```cfscript
settings = {
    "sqlCommenter": {
        "enabled": false,
        "commenters": [
            { "class": "FrameworkCommenter@qb", "properties": {} },
            { "class": "RouteInfoCommenter@qb", "properties": {} },
            { "class": "DBInfoCommenter@qb", "properties": {} }
        ]
    }
};
```

When the `enabled` flag is `false`, no comments will be appended.

The `commenters` array are the different components that will add contextual information to each query.  You define them by defining a struct with a `class` key pointing to a WireBox mapping and a `properties` key containing a struct of any necessary properties.

### Commenters

Each Commenter must implement the `ICommenter` interface. (The `implements` keyword is not required.). They will be called with the `sql` being commented and the current `datasource`.  It should return a struct of key/value pairs that will become comments.

Here is an example of the `FrameworkCommenter@qb`:

```cfscript
component singleton accessors="true" {

    property name="coldboxVersion" inject="coldbox:coldboxSetting:version";

    property name="properties";

    /**
     * Returns a struct of key/value comment pairs to append to the SQL.
     *
     * @sql         The SQL to append the comments to. This is provided if you need to
     *              inspect the SQL to make any decisions about what comments to return.
     * @datasource  The datasource that will execute the query. If null, the default datasource will be used.
     *              This can be used to make decisions about what comments to return.
     */
    public struct function getComments( required string sql, string datasource ) {
        return { "version": "coldbox-#variables.coldboxVersion#" };
    }

}
```

You may use any. all, or none of the `commenters` provided by qb.  You may also create your own for your application.  You may even see commenters pop up on [ForgeBox](https://forgebox.io) for popular use cases.

For example, if you use `cbauth` (or `cbsecurity` using `cbauth`), this commenter will add the current user ID to each query.

```cfscript
component singleton accessors="true" {

    property name="auth" inject="AuthenticationService@cbauth";

    property name="properties";

    /**
     * Returns a struct of key/value comment pairs to append to the SQL.
     *
     * @sql         The SQL to append the comments to. This is provided if you need to
     *              inspect the SQL to make any decisions about what comments to return.
     * @datasource  The datasource that will execute the query. If null, the default datasource will be used.
     *              This can be used to make decisions about what comments to return.
     */
    public struct function getComments( required string sql, string datasource ) {
        return { "userId": variables.auth.getUserId() };
    }

}
```

### Parsing Commented SQL

The comment generated by sqlCommenter is escaped and url-encoded.  It can be reversed by calling the `SQLCommenter.parseCommentedSQL` method with the full query or the `SQLCommenter.parseCommentString` method with just the comment.

#### parseCommentedSQL

| Name | Type   | Required | Default | Description                        |
| ---- | ------ | -------- | ------- | ---------------------------------- |
| sql  | string | `true`   | ​       | The commented SQL string to parse. |

Parses a commented SQL string into the SQL and a struct of the key/value pair comments.

{% code overflow="wrap" %}

```cfscript
getInstance( "ColdBoxSQLCommenter@qb" )
    .parseCommentedSQL( "SELECT * FROM foo /*action='index',dbDriver='mysql-connector-java-8.0.25%20%28Revision%3A%2008be9e9b4cba6aa115f9b27b215887af40b159e0%29',event='Main.index',framework='coldbox-6.0.0',handler='Main',route='%2F'*/" );
```

{% endcode %}

{% code title="Result" %}

```json
{
    "sql": "SELECT * FROM foo",
    "comments": {
        "action": "index",
        "dbDriver": "mysql-connector-java-8.0.25 (Revision: 08be9e9b4cba6aa115f9b27b215887af40b159e0)",
        "event": "Main.index",
        "framework": "coldbox-6.0.0",
        "handler": "Main",
        "route": "/"
    }
}
```

{% endcode %}

#### parseCommentString

| Name          | Type   | Required | Default | Description                                |
| ------------- | ------ | -------- | ------- | ------------------------------------------ |
| commentString | string | `true`   | ​       | The comment string to parse into a struct. |

Parses a comment string into a struct.

{% code overflow="wrap" %}

```cfscript
getInstance( "ColdBoxSQLCommenter@qb" )
    .parseCommentString(
        "/*action='index',dbDriver='mysql-connector-java-8.0.25%20%28Revision%3A%2008be9e9b4cba6aa115f9b27b215887af40b159e0%29',event='Main.index',framework='coldbox-6.0.0',handler='Main',route='%2F'*/"
    );
```

{% endcode %}

{% code title="Result" %}

```json
{
    "action": "index",
    "dbDriver": "mysql-connector-java-8.0.25 (Revision: 08be9e9b4cba6aa115f9b27b215887af40b159e0)",
    "event": "Main.index",
    "framework": "coldbox-6.0.0",
    "handler": "Main",
    "route": "/"
}
```

{% endcode %}

### Integration with non-ColdBox applications

Out of the box, qb includes a `ColdBoxSQLCommenter`. Since sqlCommenter adds contextual information, some level of framework or application integration is necessary.  You can create your own `sqlCommenter` instance by extending the `qb.models.SQLCommenter.SQLCommenter` abstract component. If you create a `SQLCommenter` for a specific framework, consider sharing it with others on [ForgeBox](https://forgebox.io).


# Overview

QB ships with a schema builder to help you build your database objects. This provides a few benefits:

* The syntax is expressive and fluent, making it easy to understand what is being executed
* The syntax is database-agnostic. Specific quirks are isolated in a Grammar file, making it easy to migrate between engines.

You start with a `SchemaBuilder` object. The `SchemaBuilder` takes the same Grammar that a `QueryBuilder` takes.  It can additionally take a struct of default query options forwarded on to `queryExecute` and a `defaultSchema` to use when calling `hasTable` and `hasColumn`. (A `schema` argument passed to those methods still takes precendence.)

```javascript
// manually
var schema = new qb.models.schema.SchemaBuilder(
    grammar = new qb.models.grammars.MySQLGrammar(),
    defaultOptions = { datasource: "my_datasource" }
    defaultSchema = ""
);

// WireBox
var schema = wirebox.getInstance( "SchemaBuilder@qb" );
```

> Note: the `SchemaBuilder` is a transient, and a new one should be created for each operation.

The `SchemaBuilder` has four main methods to start your database object creation:

### [`create`](https://github.com/ortus/qb/tree/b0b49b9b35032508e73231da3a39856a7bc9d21b/schema/schema/create.md)

Create a new table in the database.

| Argument | Type     | Required | Default | Description                                                                                         |
| -------- | -------- | -------- | ------- | --------------------------------------------------------------------------------------------------- |
| table    | string   | `true`   |         | The name of the table to create.                                                                    |
| callback | function | `true`   |         | A callback function used to define the table body. It is passed a `Blueprint` as the only argument. |
| options  | struct   | `false`  | `{}`    | Options to pass to `queryExecute`.                                                                  |
| execute  | boolean  | `false`  | `true`  | Run the query immediately after building it.                                                        |

The majority of the work comes from calling methods on the `Blueprint` object. A `Blueprint` defines the [columns](https://github.com/ortus/qb/tree/b0b49b9b35032508e73231da3a39856a7bc9d21b/schema/schema/columns.md) and [indexes](https://github.com/ortus/qb/tree/b0b49b9b35032508e73231da3a39856a7bc9d21b/schema/schema/indexes.md) for your tables.

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.increments( "id" );
    table.string( "email" );
    table.string( "password" );
    table.timestamp( "created_date" ).nullable();
    table.timestamp( "modified_date" ).nullable();
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
    `email` VARCHAR(255) NOT NULL,
    `password` VARCHAR(255) NOT NULL,
    `created_date` TIMESTAMP,
    `modified_date` TIMESTAMP,
    CONSTRAINT `pk_users_id` PRIMARY KEY (`id`)
)
```

### [`alter`](https://github.com/ortus/qb/tree/b0b49b9b35032508e73231da3a39856a7bc9d21b/schema/schema/alter.md)

Alter an existing table in the database.

| Argument | Type     | Required | Default | Description                                                                                                   |
| -------- | -------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------- |
| table    | string   | `true`   |         | The name of the table to alter.                                                                               |
| callback | function | `true`   |         | A callback function used to define the changes to the table. It is passed a `Blueprint` as the only argument. |
| options  | struct   | `false`  | `{}`    | Options to pass to `queryExecute`.                                                                            |
| execute  | boolean  | `false`  | `true`  | Run the query immediately after building it.                                                                  |

In addition to using the [columns](https://github.com/ortus/qb/tree/b0b49b9b35032508e73231da3a39856a7bc9d21b/schema/schema/columns.md) and [indexes](https://github.com/ortus/qb/tree/b0b49b9b35032508e73231da3a39856a7bc9d21b/schema/schema/indexes.md) off of the passed-in `Blueprint` object, the `Blueprint` contains helpers such as `addConstraint`, `removeConstraint`, `addColumn`, `renameColumn`, and `dropColumn` to assist in altering existing tables.

**Example:**

**SchemaBuilder**

```javascript
schema.alter( "users", function( table ) {
    table.addConstraint( table.unique( "username" ) );
    table.dropColumn( "last_logged_in" );
} );
```

**SQL (MySQL)**

```sql
ALTER TABLE `users` ADD CONSTRAINT `unq_users_username` UNIQUE (`username`);
ALTER TABLE `users` DROP COLUMN `last_logged_in`;
```

### [`drop` and `dropIfExists`](https://github.com/ortus/qb/tree/b0b49b9b35032508e73231da3a39856a7bc9d21b/schema/schema/drop.md)

Drop a table from the database.

| Argument | Type    | Required | Default | Description                                  |
| -------- | ------- | -------- | ------- | -------------------------------------------- |
| table    | string  | `true`   |         | The name of the table to drop.               |
| options  | struct  | `false`  | `{}`    | Options to pass to `queryExecute`.           |
| execute  | boolean | `false`  | `true`  | Run the query immediately after building it. |

**Example:**

**SchemaBuilder**

```javascript
schema.drop( "user_logins" );
```

**SQL (MySQL)**

```sql
DROP TABLE `user_logins`
```

## Additionally, there are a few utility methods defined on `SchemaBuilder` as well:

### `rename`

Rename a table from an old name to a new name

| Argument | Type    | Required | Default | Description                                  |
| -------- | ------- | -------- | ------- | -------------------------------------------- |
| from     | string  | `true`   |         | The old table name.                          |
| to       | string  | `true`   |         | The new table name.                          |
| options  | struct  | `false`  | `{}`    | Options to pass to `queryExecute`.           |
| execute  | boolean | `false`  | `true`  | Run the query immediately after building it. |

**Example:**

**SchemaBuilder**

```javascript
schema.rename( "posts", "blog_posts" );
```

**SQL (MySQL)**

```sql
RENAME TABLE `posts` TO `blog_posts`
```

### `hasTable`

Check if a table exists in the database.

| Argument | Type    | Required | Default | Description                                  |
| -------- | ------- | -------- | ------- | -------------------------------------------- |
| name     | string  | `true`   |         | The name of the table to check.              |
| options  | struct  | `false`  | `{}`    | Options to pass to `queryExecute`.           |
| execute  | boolean | `false`  | `true`  | Run the query immediately after building it. |

**Example:**

**SchemaBuilder**

```javascript
schema.hasTable( "users" );
```

**SQL (MySQL)**

```sql
SELECT 1
FROM `information_schema`.`tables`
WHERE `table_name` = 'users'
```

### `hasColumn`

Check if a column exists in a table in the database.

| Argument | Type    | Required | Default | Description                                       |
| -------- | ------- | -------- | ------- | ------------------------------------------------- |
| table    | string  | `true`   |         | The name of the table to check for the column in. |
| column   | string  | `true`   |         | The column to check for in the table.             |
| options  | struct  | `false`  | `{}`    | Options to pass to `queryExecute`.                |
| execute  | boolean | `false`  | `true`  | Run the query immediately after building it.      |

**Example:**

**SchemaBuilder**

```javascript
schema.hasColumn( "users", "last_logged_in" );
```

**SQL (MySQL)**

```sql
SELECT 1
FROM `information_schema`.`columns`
WHERE `table_name` = 'users'
    AND `column_name` = 'last_logged_in'
```

### pretend


# Creating Tables and Views

## create

This method allows you to create a table object.

| Argument | Type     | Required | Default | Description                                                                                         |
| -------- | -------- | -------- | ------- | --------------------------------------------------------------------------------------------------- |
| table    | string   | `true`   |         | The name of the table to create.                                                                    |
| callback | function | `true`   |         | A callback function used to define the table body. It is passed a `Blueprint` as the only argument. |
| options  | struct   | `false`  | `{}`    | Options to pass to `queryExecute`.                                                                  |
| execute  | boolean  | `false`  | `true`  | Run the query immediately after building it.                                                        |

The majority of the work comes from calling methods on the `Blueprint` object. A `Blueprint` defines the [columns](/12.1.0/schema-builder/columns) and [indexes](/12.1.0/schema-builder/column-modifiers) for your tables.

Example:

```javascript
schema.create( "users", function( table ) {
    table.increments( "id" );
    table.string( "email" );
    table.string( "password" );
    table.timestamp( "created_date" );
    table.timestamp( "modified_date" );
    table.timestamp( "last_logged_in" ).nullable();
} );
```

This would convert to the following SQL in MySQL:

```sql
CREATE TABLE `users` (
    `id` INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `email` VARCHAR(255) NOT NULL,
    `password` VARCHAR(255) NOT NULL,
    `created_date` TIMESTAMP NOT NULL,
    `modified_date` TIMESTAMP NOT NULL,
    `last_logged_in` TIMESTAMP,
    CONSTRAINT `pk_users_id` PRIMARY KEY (`id`)
)
```

Only one table can be created at a time. If you wanted to create multiple tables, you would call `create` multiple times.

The `callback` argument is where you define the schema of your table. It is passed a `Blueprint` object. This is commonly aliased as `table` in the callback. `Blueprint` defines the field, index and constraint methods to build your table. You can find a comprehensive list of all available methods here for [columns](https://github.com/ortus/qb/tree/b0b49b9b35032508e73231da3a39856a7bc9d21b/schema/columns.md) and here for [indexes and constraints](/12.1.0/schema-builder/column-modifiers).

## createAs

This method allows you to create a table using a query.  It is similar to a view except that the data is inserted once at table creation.

{% hint style="warning" %}
This is an `UnsupportedOperation` on `DerbyGrammar`.
{% endhint %}

| Argument     | Type     | Required | Default | Description                                                                                            |
| ------------ | -------- | -------- | ------- | ------------------------------------------------------------------------------------------------------ |
| newTableName | string   | `true`   |         | The name of the table to create.                                                                       |
| callback     | function | `true`   |         | A callback function used to define the table body. It is passed a `QueryBuilder` as the only argument. |
| options      | struct   | `false`  | `{}`    | Options to pass to `queryExecute`.                                                                     |
| execute      | boolean  | `false`  | `true`  | Run the query immediately after building it.                                                           |

Like with a `view`, the columns are defined by the data returned by the query.  The data returned by the query will be inserted into the table.

## createView

This method allows you to create a view using a query.

| Argument | Type     | Required | Default | Description                                                                                            |
| -------- | -------- | -------- | ------- | ------------------------------------------------------------------------------------------------------ |
| view     | string   | `true`   |         | The name of the view to create.                                                                        |
| callback | function | `true`   |         | A callback function used to define the table body. It is passed a `QueryBuilder` as the only argument. |
| options  | struct   | `false`  | `{}`    | Options to pass to `queryExecute`.                                                                     |
| execute  | boolean  | `false`  | `true`  | Run the query immediately after building it.                                                           |


# Columns

The `Blueprint` object has many column types available to construct your table schema. Additionally, you can modify the columns created [with an additional set of methods](/12.1.0/schema-builder/column-modifiers) and [indexes](/12.1.0/schema-builder/column-modifiers).

## bigIncrements

Create an auto-incrementing column using an unsigned `BIGINT` type. This column is also set as the primary key for the table.

| Argument  | Type   | Required | Default | Description                                                                                                                                     |
| --------- | ------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| name      | string | `true`   |         | The name for the column.                                                                                                                        |
| indexName | string | `false`  |         | The name for the primary key index.  If no name is passed in, the name will be dynamically created based off of the table name and column name. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.bigIncrements( "id" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    CONSTRAINT `pk_users_id` PRIMARY KEY (`id`)
)
```

## bigInteger

Create a column using a `BIGINT` equivalent type for your database.

| Argument  | Type    | Required | Default | Description                   |
| --------- | ------- | -------- | ------- | ----------------------------- |
| name      | string  | `true`   |         | The name for the column.      |
| precision | numeric | `false`  |         | The precision for the column. |

**Example (no precision):**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.bigInteger( "salary" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `salary` BIGINT NOT NULL
)
```

**Example (with precision):**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.bigInteger( "salary", 5 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `salary` BIGINT(5) NOT NULL
)
```

## bit

Create a column using a `BIT` equivalent type for your database. The length can be specified as the second argument.

| Argument | Type    | Required | Default | Description                |
| -------- | ------- | -------- | ------- | -------------------------- |
| name     | string  | `true`   |         | The name for the column.   |
| length   | numeric | `false`  | 1       | The length for the column. |

**Example (default length):**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.bit( "is_active" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `is_active` BIT(1) NOT NULL
)
```

**Example (custom length):**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.bit( "is_active", 2 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `is_active` BIT(2) NOT NULL
)
```

## boolean

Create a column using a `BOOLEAN` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.boolean( "is_subscribed" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `is_subscribed` TINYINT(1) NOT NULL
)
```

## char

Create a column using a `CHAR` equivalent type for your database.

| Argument | Type    | Required | Default | Description                |
| -------- | ------- | -------- | ------- | -------------------------- |
| name     | string  | `true`   |         | The name for the column.   |
| length   | numeric | `false`  | 1       | The length for the column. |

**Example (default length):**

**SchemaBuilder**

```javascript
schema.create( "students", function( table ) {
    table.char( "grade" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `students` (
    `grade` CHAR(1) NOT NULL
)
```

**Example (custom length):**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.char( "tshirt_size", 4 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `tshirt_size` CHAR(4) NOT NULL
)
```

## date

Create a column using a `DATE` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.date( "birthday" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `birthday` DATE NOT NULL
)
```

## datetime

Create a column using a `DATETIME` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.datetime( "hire_date" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `hire_date` DATETIME NOT NULL
)
```

## datetimeTz

Create a column using a timezone-specific `DATETIME` equivalent type for your database.

{% hint style="info" %}
Some databases do not have the concept of a timezone-specific datetime.  Those databases will use a normal `DATETIME` type.
{% endhint %}

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.datetimeTz( "posted_date" );
} );
```

**SQL (SQL Server)**

```sql
CREATE TABLE [posts] (
    [posted_date] DATETIMEOFFSET NOT NULL
)
```

## decimal

Create a column using a `DECIMAL` equivalent type for your database. The length and precision can be specified as the second and third arguments.

| Argument  | Type    | Required | Default | Description                  |
| --------- | ------- | -------- | ------- | ---------------------------- |
| name      | string  | `true`   |         | The name for the column.     |
| length    | numeric | `false`  | 10      | The length of the column.    |
| precision | numeric | `false`  | 0       | The precision of the column. |

**Example (with defaults):**

**SchemaBuilder**

```javascript
schema.create( "weather", function( table ) {
    table.decimal( "temperature" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `weather` (
    `temperature` DECIMAL(10,0) NOT NULL
)
```

**Example (with length):**

**SchemaBuilder**

```javascript
schema.create( "weather", function( table ) {
    table.decimal( "temperature", 4 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `weather` (
    `temperature` DECIMAL(4,0) NOT NULL
)
```

**Example (with precision):**

**SchemaBuilder**

```javascript
schema.create( "weather", function( table ) {
    table.decimal( name = "temperature", precision = 2 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `weather` (
    `temperature` DECIMAL(10,2) NOT NULL
)
```

## enum

Create a column using a `ENUM` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.enum( "tshirt_size", [ "S", "M", "L", "XL", "XXL" ] );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `tshirt_size` ENUM(`S`, `M`, `L`, `XL`, `XXL`) NOT NULL
)
```

## float

Create a column using a `FLOAT` equivalent type for your database. The length and precision can be specified as the second and third arguments.

| Argument  | Type    | Required | Default | Description                  |
| --------- | ------- | -------- | ------- | ---------------------------- |
| name      | string  | `true`   |         | The name for the column.     |
| length    | numeric | `false`  | 10      | The length of the column.    |
| precision | numeric | `false`  | 0       | The precision of the column. |

**Example (with defaults):**

**SchemaBuilder**

```javascript
schema.create( "weather", function( table ) {
    table.float( "temperature" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `weather` (
    `temperature` FLOAT(10,0) NOT NULL
)
```

**Example (with length):**

**SchemaBuilder**

```javascript
schema.create( "weather", function( table ) {
    table.float( "temperature", 4 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `weather` (
    `temperature` FLOAT(4,0) NOT NULL
)
```

**Example (with precision):**

**SchemaBuilder**

```javascript
schema.create( "weather", function( table ) {
    table.float( name = "temperature", precision = 2 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `weather` (
    `temperature` FLOAT(10,2) NOT NULL
)
```

## guid

**SQL Server**: Create a column using a `uniqueidentifier`.

**MySQL** and Others: Create a column using a `CHAR` equivalent type for your database and a length of 36. Used in conjunction with the Lucee `createGUID` method or Java's `java.util.UUID.randomUUID()`.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.guid( "id" ).primaryKey();
} );
```

**MySQL (SQL Server)**

```sql
CREATE TABLE `games` (
    `id` uniqueidentifier NOT NULL,
    CONSTRAINT `pk_games_id` PRIMARY KEY (`id`)
)
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `id` VARCHAR(36) NOT NULL,
    CONSTRAINT `pk_games_id` PRIMARY KEY (`id`)
)
```

## increments

Create an auto-incrementing column using an unsigned `INTEGER` type. This column is also set as the primary key for the table.

| Argument  | Type   | Required | Default | Description                                                                                                                                     |
| --------- | ------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| name      | string | `true`   |         | The name for the column.                                                                                                                        |
| indexName | string | `false`  |         | The name for the primary key index.  If no name is passed in, the name will be dynamically created based off of the table name and column name. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.increments( "id" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
    CONSTRAINT `pk_users_id` PRIMARY KEY (`id`)
)
```

## integer

Create a column using a `INTEGER` equivalent type for your database.

| Argument  | Type    | Required | Default | Description                   |
| --------- | ------- | -------- | ------- | ----------------------------- |
| name      | string  | `true`   |         | The name for the column.      |
| precision | numeric | `false`  |         | The precision for the column. |

**Example (no precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.integer( "score" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` INTEGER NOT NULL
)
```

**Example (with precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.integer( "score", 3 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` INTEGER(3) NOT NULL
)
```

## json

Create a column using a `JSON` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.json( "options" ).nullable();
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `options` JSON
)
```

## jsonb

Create a column using a `JSONB` equivalent type for your database.

{% hint style="info" %}
Currently, only `PostgresGrammar` makes a distinction between `json` and `jsonb`.
{% endhint %}

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.jsonb( "options" ).nullable();
} );
```

**Postgres**

```sql
CREATE TABLE "users" (
    "options" JSONB
)
```

## lineString

Create a column using a `LINESTRING` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.lineString( "positions" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `positions` LINESTRING NOT NULL
)
```

## longText

Create a column using a `LONGTEXT` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.longText( "body" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `posts` (
    `body` LONGTEXT NOT NULL
)
```

## mediumIncrements

Create an auto-incrementing column using an unsigned `MEDIUMINT` type. This column is also set as the primary key for the table.

| Argument  | Type   | Required | Default | Description                                                                                                                                     |
| --------- | ------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| name      | string | `true`   |         | The name for the column.                                                                                                                        |
| indexName | string | `false`  |         | The name for the primary key index.  If no name is passed in, the name will be dynamically created based off of the table name and column name. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.mediumIncrements( "id" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
    CONSTRAINT `pk_users_id` PRIMARY KEY (`id`)
)
```

## mediumInteger

Create a column using a `MEDIUMINT` equivalent type for your database.

| Argument  | Type    | Required | Default | Description                   |
| --------- | ------- | -------- | ------- | ----------------------------- |
| name      | string  | `true`   |         | The name for the column.      |
| precision | numeric | `false`  | 10      | The precision for the column. |

**Example (no precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.mediumInteger( "score" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` MEDIUMINT NOT NULL
)
```

**Example (with precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.mediumInteger( "score", 5 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` MEDIUMINT(5) NOT NULL
)
```

## mediumText

Create a column using a `MEDIUMTEXT` equivalent type for your database. For databases that distinguish between unicode and non-unicode fields, creates a non-unicode field.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.mediumText( "body" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `posts` (
    `body` MEDIUMTEXT NOT NULL
)
```

**SQL (MSSQL)**

```sql
CREATE TABLE `posts` (
    `body` VARCHAR(MAX) NOT NULL
)
```

## money

Create a column using a `MONEY` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "transactions", function( table ) {
    table.money( "amount" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `transactions` (
    `amount` INTEGER NOT NULL
)
```

**SQL (MSSQL)**

```sql
CREATE TABLE [transactions] (
    [amount] MONEY NOT NULL
)
```

## morphs

Creates the necessary columns for a polymorphic relationship. It takes the name provided and creates an `_id` and an `_type` column.

If you want different names for your polymorphic relationship columns, feel free to call other schema builder methods individually.

| Argument | Type   | Required | Default | Description                             |
| -------- | ------ | -------- | ------- | --------------------------------------- |
| name     | string | `true`   |         | The prefix for the polymorphic columns. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "tags", function( table ) {
    table.morphs( "taggable" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `tags` (
    `taggable_id` INTEGER UNSIGNED NOT NULL,
    `taggable_type` VARCHAR(255) NOT NULL,
    INDEX `taggable_index` (`taggable_id`, `taggable_type`)
)
```

## nullableMorphs

Creates the necessary columns for a polymorphic relationship. It takes the name provided and creates an `_id` and an `_type` column. The only difference between this method and `morphs` is that the columns created here are nullable.

If you want different names for your polymorphic relationship columns, feel free to call other schema builder methods individually.

| Argument | Type   | Required | Default | Description                             |
| -------- | ------ | -------- | ------- | --------------------------------------- |
| name     | string | `true`   |         | The prefix for the polymorphic columns. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "tags", function( table ) {
    table.nullableMorphs( "taggable" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `tags` (
    `taggable_id` INTEGER UNSIGNED,
    `taggable_type` VARCHAR(255),
    INDEX `taggable_index` (`taggable_id`, `taggable_type`)
)
```

## nullableTimestamps

Creates the `createdDate` and `modifiedDate` `TIMESTAMP` columns. It creates the columns as nullable.

If you want different names for your timestamp columns, feel free to call other schema builder methods individually.

| Argument     | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.nullableTimestamps();
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `posts` (
    `createdDate` TIMESTAMP,
    `modifiedDate` TIMESTAMP
)
```

## point

Create a column using a `POINT` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.point( "position" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `position` POINT NOT NULL
)
```

## polygon

Create a column using a `POLYGON` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.polygon( "positions" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `positions` POLYGON NOT NULL
)
```

## raw

An escape hatch to directly insert any sql in to the statement.

| Argument | Type   | Required | Default | Description                                    |
| -------- | ------ | -------- | ------- | ---------------------------------------------- |
| sql      | string | `true`   |         | The sql to insert directly into the statement. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.raw( "`profile_image` BLOB NOT NULL" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `profile_image` BLOB NOT NULL
)
```

## smallIncrements

Create an auto-incrementing column using an unsigned `SMALLINT` type. This column is also set as the primary key for the table.

| Argument  | Type   | Required | Default | Description                                                                                                                                     |
| --------- | ------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| name      | string | `true`   |         | The name for the column.                                                                                                                        |
| indexName | string | `false`  |         | The name for the primary key index.  If no name is passed in, the name will be dynamically created based off of the table name and column name. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.smallIncrements( "id" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `id` SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
    CONSTRAINT `pk_users_id` PRIMARY KEY (`id`)
)
```

## smallInteger

Create a column using a `SMALLINT` equivalent type for your database.

| Argument  | Type    | Required | Default | Description                   |
| --------- | ------- | -------- | ------- | ----------------------------- |
| name      | string  | `true`   |         | The name for the column.      |
| precision | numeric | `false`  |         | The precision for the column. |

**Example (no precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.smallInteger( "score" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` SMALLINT NOT NULL
)
```

**Example (with precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.smallInteger( "score", 3 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` SMALLINT(3) NOT NULL
)
```

## smallMoney

Create a column using a `SMALLMONEY` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "transactions", function( table ) {
    table.smallMoney( "amount" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `transactions` (
    `amount` INTEGER NOT NULL
)
```

**SQL (MSSQL)**

```sql
CREATE TABLE [transactions] (
    [amount] SMALLMONEY NOT NULL
)
```

## softDeletes

Creates a nullable `deletedDate` `TIMESTAMP` column.

If you want different names for your timestamp column, feel free to call other schema builder methods individually.

| Argument     | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.softDeletes();
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `posts` (
    `deletedDate` TIMESTAMP
)
```

## softDeletesTz

Creates a nullable `deletedDate` timezone-specific `TIMESTAMP` column.

If you want different names for your timestamp column, feel free to call other schema builder methods individually.

| Argument     | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.softDeletesTz();
} );
```

**SQL (SQL Server)**

```sql
CREATE TABLE [posts] (
    [deletedDate] DATETIMEOFFSET
)
```

## string

Create a column using a `VARCHAR` equivalent type for your database. For databases that distinguish between unicode- and non-unicode string data types, this function will create a non-unicode string.

| Argument | Type    | Required | Default | Description               |
| -------- | ------- | -------- | ------- | ------------------------- |
| name     | string  | `true`   |         | The name for the column.  |
| length   | numeric | `false`  | 255     | The length of the column. |

**Example (with defaults):**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.string( "username" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `username` VARCHAR(255) NOT NULL
)
```

**Example (with length):**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.string( "username", 50 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `username` VARCHAR(50) NOT NULL
)
```

## text

Create a column using a `TEXT` equivalent type for your database. For databases that distinguish between unicode- and non-unicode string data types, this function will create a non-unicode text field.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.text( "body" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `posts` (
    `body` TEXT NOT NULL
)
```

## time

Create a column using a `TIME` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "recurring_tasks", function( table ) {
    table.time( "fire_time" );
} );
```

**SQL (Postgres)**

```sql
CREATE TABLE "recurring_tasks" (
    "fire_time" TIME NOT NULL
)
```

## timeTz

Create a column using a timezone-specific `TIME` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "recurring_tasks", function( table ) {
    table.timeTz( "fire_time" );
} );
```

**SQL (Postgres)**

```sql
CREATE TABLE "recurring_tasks" (
    "fire_time" TIME WITH TIME ZONE NOT NULL
)
```

## timestamp

Create a column using a `TIMESTAMP` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.timestamp( "created_at" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `created_at` TIMESTAMP NOT NULL
)
```

## timestamps

Creates the `createdDate` and `modifiedDate` `TIMESTAMP` columns.

If you want different names for your timestamp columns, feel free to call other schema builder methods individually.

| Argument     | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.timestamps();
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `posts` (
    `createdDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `modifiedDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
)
```

## timestampTz

Create a column using a timezone-specific `TIMESTAMP` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.timestampTz( "posted_date" );
} );
```

**SQL (Postgres)**

```sql
CREATE TABLE "posts" (
    "posted_date" TIMESTAMP WITH TIME ZONE NOT NULL
)
```

## timestampsTz

Creates the `createdDate` and `modifiedDate` timezone-specific `TIMESTAMP` columns.

If you want different names for your timestamp columns, feel free to call other schema builder methods individually.

| Argument     | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.timestampsTz();
} );
```

**SQL (Postgres)**

```sql
CREATE TABLE "posts" (
    "createdDate" TIMESTAMP WITH TIME ZONE NOT NULL,
    "modifiedDate" TIMESTAMP WITH TIME ZONE NOT NULL
)
```

## tinyIncrements

Create an auto-incrementing column using an unsigned `TINYINT` type. This column is also set as the primary key for the table.

| Argument  | Type   | Required | Default | Description                                                                                                                                     |
| --------- | ------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| name      | string | `true`   |         | The name for the column.                                                                                                                        |
| indexName | string | `false`  |         | The name for the primary key index.  If no name is passed in, the name will be dynamically created based off of the table name and column name. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.tinyIncrements( "id" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `id` TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
    CONSTRAINT `pk_users_id` PRIMARY KEY (`id`)
)
```

## tinyInteger

Create a column using a `TINYINT` equivalent type for your database.

| Argument  | Type    | Required | Default | Description                   |
| --------- | ------- | -------- | ------- | ----------------------------- |
| name      | string  | `true`   |         | The name for the column.      |
| precision | numeric | `false`  |         | The precision for the column. |

**Example (no precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.tinyInteger( "score" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` TINYINT NOT NULL
)
```

**Example (with precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.tinyInteger( "score", 3 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` TINYINT(3) NOT NULL
)
```

## unicodeLongText

Create a column using a `LONGTEXT` equivalent type for your database. For databases that distinguish between unicode- and non-unicode string data types, this function will create a unicode text field.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.longText( "body" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `posts` (
    `body` LONGTEXT NOT NULL
)
```

**SQL (MSSQL)**

```sql
CREATE TABLE [posts] (
    [body] NVARCHAR(MAX) NOT NULL
)
```

## unicodeMediumText

Create a unicode-enabled column using a `MEDIUMTEXT` equivalent type for your database. For databases that distinguish between unicode- and non-unicode string data types, this function will create a unicode text field.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.unicodeMediumText( "body" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `posts` (
    `body` MEDIUMTEXT NOT NULL
)
```

**SQL (MSSQL)**

```sql
CREATE TABLE [posts] (
    [body] NVARCHAR(MAX) NOT NULL
)
```

## unicodeString

Create a column using a `NVARCHAR` equivalent type for your database. For databases that distinguish between unicode- and non-unicode string data types, this function will create a unicode string.

| Argument | Type    | Required | Default | Description               |
| -------- | ------- | -------- | ------- | ------------------------- |
| name     | string  | `true`   |         | The name for the column.  |
| length   | numeric | `false`  | 255     | The length of the column. |

**Example (with defaults):**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.unicodeString( "username" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `username` VARCHAR(255) NOT NULL
)
```

**SQL (MSSQL)**

```sql
CREATE TABLE [users] (
    [username] NVARCHAR(255) NOT NULL
)
```

**Example (with length):**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.unicodeString( "username", 50 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `username` VARCHAR(50) NOT NULL
)
```

**SQL (MSSQL)**

```sql
CREATE TABLE [users] (
    [username] NVARCHAR(50) NOT NULL
)
```

## unicodeText

Create a column using a `NTEXT` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.unicodeText( "body" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `posts` (
    `body` TEXT NOT NULL
)
```

**SQL (MSSQL)**

```sql
CREATE TABLE [posts] (
    [body] NVARCHAR(MAX) NOT NULL
)
```

## unsignedBigInteger

Create a column using a `UNSIGNED BIGINT` equivalent type for your database.

| Argument  | Type    | Required | Default | Description                   |
| --------- | ------- | -------- | ------- | ----------------------------- |
| name      | string  | `true`   |         | The name for the column.      |
| precision | numeric | `false`  |         | The precision for the column. |

**Example (no precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.unsignedBigInteger( "score" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` BIGINT UNSIGNED NOT NULL
)
```

**Example (with precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.unsignedBigInteger( "score", 3 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` BIGINT(3) UNSIGNED NOT NULL
)
```

## unsignedInteger

Create a column using a `UNSIGNED INTEGER` equivalent type for your database.

| Argument  | Type    | Required | Default | Description                   |
| --------- | ------- | -------- | ------- | ----------------------------- |
| name      | string  | `true`   |         | The name for the column.      |
| precision | numeric | `false`  |         | The precision for the column. |

**Example (no precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.unsignedInteger( "score" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` INTEGER UNSIGNED NOT NULL
)
```

**Example (with precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.unsignedInteger( "score", 3 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` INTEGER(3) UNSIGNED NOT NULL
)
```

## unsignedMediumInteger

Create a column using a `UNSIGNED MEDIUMINT` equivalent type for your database.

| Argument  | Type    | Required | Default | Description                   |
| --------- | ------- | -------- | ------- | ----------------------------- |
| name      | string  | `true`   |         | The name for the column.      |
| precision | numeric | `false`  |         | The precision for the column. |

**Example (no precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.unsignedMediumInteger( "score" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` MEDIUMINT UNSIGNED NOT NULL
)
```

**Example (with precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.unsignedMediumInteger( "score", 3 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` MEDIUMINT(3) UNSIGNED NOT NULL
)
```

## unsignedSmallInteger

Create a column using a `UNSIGNED SMALLINT` equivalent type for your database.

| Argument  | Type    | Required | Default | Description                   |
| --------- | ------- | -------- | ------- | ----------------------------- |
| name      | string  | `true`   |         | The name for the column.      |
| precision | numeric | `false`  |         | The precision for the column. |

**Example (no precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.unsignedSmallInteger( "score" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` SMALLINT UNSIGNED NOT NULL
)
```

**Example (with precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.unsignedSmallInteger( "score", 3 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` SMALLINT(3) UNSIGNED NOT NULL
)
```

## unsignedTinyInteger

Create a column using a `UNSIGNED TINYINT` equivalent type for your database.

| Argument  | Type    | Required | Default | Description                   |
| --------- | ------- | -------- | ------- | ----------------------------- |
| name      | string  | `true`   |         | The name for the column.      |
| precision | numeric | `false`  |         | The precision for the column. |

**Example (no precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.unsignedTinyInteger( "score" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` TINYINT UNSIGNED NOT NULL
)
```

**Example (with precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.unsignedTinyInteger( "score", 3 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` TINYINT(3) UNSIGNED NOT NULL
)
```

## uuid

Creates a column using a `CHAR` equivalent type for your database and a length of 35. Used in conjunction with the CFML `createUUID` method.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.uuid( "id" ).primaryKey();
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `id` VARCHAR(35) NOT NULL,
    CONSTRAINT `pk_games_id` PRIMARY KEY (`id`)
)
```


# Column Modifiers

When [creating a column](/12.1.0/schema-builder/columns) from the `Blueprint` object, a `Column` object is returned. This `column` gives you access to a few modifier commands to further configure the column.

## comment

Attach a comment to the column.

| Argument | Type   | Required | Default | Description       |
| -------- | ------ | -------- | ------- | ----------------- |
| comment  | string | `true`   |         | The comment text. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.integer( "age" ).comment( "Do not lie about your age" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `age` INTEGER NOT NULL COMMENT `Do not lie about your age`
)
```

## default

Sets a default value for the column.

**Note:** The value is not escaped, allowing you to specify functions like `NOW()` or literals like `1`. To specify a literal string, wrap the value in quotes.

| Argument | Type   | Required | Default | Description        |
| -------- | ------ | -------- | ------- | ------------------ |
| value    | string | `true`   |         | The default value. |

**Example:**

**SchemaBuilder**

```
schema.create( "users", function( table ) {
    table.boolean( "is_active" ).default( 1 );
    table.timestamp( "created_date" ).default( "NOW()" );
    tablVIRTUAL NOT NULLe.string( "country" ).default( "'USA'" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `is_active` TINYINT(1) DEFAULT 1,
    `created_date` TIMESTAMP DEFAULT NOW(),
    `country` VARCHAR(255) DEFAULT 'USA'
)
```

## nullable

Sets the column to allow null values.

| Argument     | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

All columns are created as `NOT NULL` by default. As such, there is no `notNull` method.

**Example:**

**SchemaBuilder**

```
schema.create( "users", function( table ) {
    table.timestamp( "last_logged_in" ).nullable()
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `last_logged_in` TIMESTAMP
)
```

## primaryKey

Adds the column as a primary key for the table.

| Argument  | Type   | Required | Default                                                   | Description                                     |
| --------- | ------ | -------- | --------------------------------------------------------- | ----------------------------------------------- |
| indexName | string | `false`  | A derived name built from the table name and column name. | The name to use for the primary key constraint. |

The `primaryKey` method returns a [`TableIndex` instance.](https://github.com/ortus/qb/tree/b0b49b9b35032508e73231da3a39856a7bc9d21b/schema/schema/indexes.md) Additional methods can be chained off of it.

**Example:**

**SchemaBuilder**

```
schema.create( "users", function( table ) {
    table.uuid( "id" ).primaryKey();
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `id` CHAR(35) NOT NULL,
    CONSTAINT `pk_users_id` PRIMARY KEY (`id`)
)
```

## references

Creates a foreign key constraint for the column.

| Argument | Type   | Required | Default | Description        |
| -------- | ------ | -------- | ------- | ------------------ |
| value    | string | `true`   |         | The default value. |

**IMPORTANT:** Additional configuration of the foreign constraint is done by calling methods on the returned [`TableIndex` instance.](https://github.com/ortus/qb/tree/b0b49b9b35032508e73231da3a39856a7bc9d21b/schema/schema/indexes.md)

**Example:**

**SchemaBuilder**

```
schema.create( "users", function( table ) {
    table.unsignedInteger( "country_id" ).references( "id" ).onTable( "countries" ).onDelete( "cascade" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `country_id` INTEGER UNSIGNED NOT NULL,
    CONSTRAINT `fk_users_country_id` FOREIGN KEY (`country_id`) REFERENCES `countries` (`id`) ON UPDATE NO ACTION ON DELETE CASCADE
)
```

## unsigned

Sets the column as unsigned.

| Argument     | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

**Example:**

**SchemaBuilder**

```
schema.create( "users", function( table ) {
    table.integer( age" ).unsigned();
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `age` INTEGER UNSIGNED NOT NULL
)
```

## unique

Sets the column to have the UNIQUE constraint.

| Argument     | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

**Example:**

**SchemaBuilder**

```
schema.create( "email", function( table ) {
    table.string( email" ).unique();
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `email` VARCHAR(255) NOT NULL UNIQUE
)
```

## withCurrent

Sets the column to have the a default value of `CURRENT_TIMESTAMP`.

| Argument     | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.timestamp( "posted_date" ).withCurrent();
} );
```

**SQL (Postgres)**

```sql
CREATE TABLE "posts" (
    "posted_date" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
)
```

## storedAs

Creates a stored computed column.  Computed columns are defined as expressions between other columns and/or constant values.  Stored computed columns are saved in the database to avoid computing on every query.

{% hint style="info" %}
Your database grammar may not differentiate between stored computed columns and virtual computed columns.  Research your grammar's implementation for more details.
{% endhint %}

| Argument   | Type   | Required | Default | Description                                 |
| ---------- | ------ | -------- | ------- | ------------------------------------------- |
| expression | string | `true`   |         | The SQL used to define the computed column. |

{% tabs %}
{% tab title="SchemaBuilder" %}

```javascript
schema.create( "products", function( table ) {
    table.integer( "price" );
    table.integer( "tax" ).storedAs( "price * 0.0675" );
} );
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="MySQL" %}

```sql
CREATE TABLE `products` (
    `price` INTEGER NOT NULL,
    `tax` INTEGER GENERATED ALWAYS AS (price * 0.0675) STORED NOT NULL
)
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
CREATE TABLE [products] (
    [price] INTEGER NOT NULL,
    [tax] AS (price * 0.0675) PERSISTED
)
```

{% endtab %}

{% tab title="Postgres" %}

```sql
CREATE TABLE "products" (
    "price" INTEGER NOT NULL,
    "tax" INTEGER NOT NULL GENERATED ALWAYS AS (price * 0.0675) STORED
)
```

{% endtab %}

{% tab title="Oracle" %}

```sql
CREATE TABLE "PRODUCTS" (
    "PRICE" NUMBER(10, 0) NOT NULL,
    "TAX" NUMBER(10, 0) GENERATED ALWAYS AS (price * 0.0675)
)
```

{% endtab %}
{% endtabs %}

## virtualAs

Creates a virtual computed column.  Computed columns are defined as expressions between other columns and/or constant values.  Virtual computed columns are computed on every query.

{% hint style="info" %}
Your database grammar may not differentiate between stored computed columns and virtual computed columns.  Research your grammar's implementation for more details.
{% endhint %}

| Argument   | Type   | Required | Default | Description                                 |
| ---------- | ------ | -------- | ------- | ------------------------------------------- |
| expression | string | `true`   |         | The SQL used to define the computed column. |

{% tabs %}
{% tab title="SchemaBuilder" %}

```javascript
schema.create( "products", function( table ) {
    table.integer( "price" );
    table.integer( "tax" ).virtualAs( "price * 0.0675" );
} );
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="MySQL" %}

```sql
CREATE TABLE `products` (
    `price` INTEGER NOT NULL,
    `tax` INTEGER GENERATED ALWAYS AS (price * 0.0675) VIRTUAL NOT NULL
)
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
CREATE TABLE [products] (
    [price] INTEGER NOT NULL,
    [tax] AS (price * 0.0675)
)
```

{% endtab %}

{% tab title="Postgres" %}

```sql
CREATE TABLE "products" (
    "price" INTEGER NOT NULL,
    "tax" INTEGER GENERATED ALWAYS AS (price * 0.0675) STORED
)
```

{% endtab %}

{% tab title="Oracle" %}

```sql
CREATE TABLE "PRODUCTS" (
    "PRICE" NUMBER(10, 0) NOT NULL,
    "TAX" NUMBER(10, 0) GENERATED ALWAYS AS (price * 0.0675) VIRTUAL
)
```

{% endtab %}
{% endtabs %}


# Column Constraints

A `TableIndex` can be created directly from a [`Blueprint`](/12.1.0/schema-builder/creating-table-constraints) or from a existing [`Column`](/12.1.0/schema-builder/column-modifiers). The `TableIndex` includes methods for further configuring the index which is required when defining foreign keys.

## references

Set the referencing column for a foreign key relationship. For example, `id` for a `country_id` column.

| Argument | Type | Required | Default | Description                                                             |
| -------- | ---- | -------- | ------- | ----------------------------------------------------------------------- |
| columns  | any  | `true`   |         | A column or array of columns that represents the foreign key reference. |

**Example:**

**SchemaBuilder**

```
schema.create( "users", function( table ) {
    table.unsignedInteger( "country_id" ).references( "id" ).onTable( "countries" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `country_id` INTEGER UNSIGNED NOT NULL,
    CONSTRAINT `fk_users_country_id` FOREIGN KEY (`country_id`) REFERENCES `countries` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION
)
```

## onTable

Sets the referencing table for a foreign key relationship. For example, `countries` for a `country_id` column.

| Argument | Type   | Required | Default | Description                 |
| -------- | ------ | -------- | ------- | --------------------------- |
| table    | string | `true`   |         | The referencing table name. |

**Example:**

**SchemaBuilder**

```
schema.create( "users", function( table ) {
    table.unsignedInteger( "country_id" ).references( "id" ).onTable( "countries" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `country_id` INTEGER UNSIGNED NOT NULL,
    CONSTRAINT `fk_users_country_id` FOREIGN KEY (`country_id`) REFERENCES `countries` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION
)
```

## onUpdate

Set the strategy for updating foreign keys when the parent key is updated.

| Argument | Type   | Required | Default | Description                                                                                    |
| -------- | ------ | -------- | ------- | ---------------------------------------------------------------------------------------------- |
| option   | string | `true`   |         | The strategy to use. Available values are: RESTRICT, CASCADE, SET NULL, NO ACTION, SET DEFAULT |

**Example:**

**SchemaBuilder**

```
schema.create( "users", function( table ) {
    table.unsignedInteger( "country_id" )
        .references( "id" )
        .onTable( "countries" )
        .onUpdate( "CASCADE" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `country_id` INTEGER UNSIGNED NOT NULL,
    CONSTRAINT `fk_users_country_id` FOREIGN KEY (`country_id`) REFERENCES `countries` (`id`) ON UPDATE CASCADE ON DELETE NO ACTION
)
```

## onDelete

Set the strategy for updating foreign keys when the parent key is deleted.

| Argument | Type   | Required | Default | Description                                                                                    |
| -------- | ------ | -------- | ------- | ---------------------------------------------------------------------------------------------- |
| option   | string | `true`   |         | The strategy to use. Available values are: RESTRICT, CASCADE, SET NULL, NO ACTION, SET DEFAULT |

**Example:**

**SchemaBuilder**

```
schema.create( "users", function( table ) {
    table.unsignedInteger( "country_id" )
        .references( "id" )
        .onTable( "countries" )
        .onDelete( "SET NULL" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `country_id` INTEGER UNSIGNED NOT NULL,
    CONSTRAINT `fk_users_country_id` FOREIGN KEY (`country_id`) REFERENCES `countries` (`id`) ON UPDATE NO ACTION ON DELETE SET NULL
)
```


# Creating Table Constraints

Sometimes you want to add constraints on a table level, rather than a column level. The following methods will let you accomplish that.

## index

Create a generic index from one or more columns.

| Argument | Type            | Required | Default                                                           | Description                                            |
| -------- | --------------- | -------- | ----------------------------------------------------------------- | ------------------------------------------------------ |
| columns  | string or array | `true`   |                                                                   | The column or array of columns that make up the index. |
| name     | string          | `false`  | A generated name consisting of the table name and column name(s). | The name of the index constraint.                      |
|          |                 |          |                                                                   |                                                        |

**Example:**

**SchemaBuilder**

```
schema.create( "users", function( table ) {
    table.string( "first_name" );
    table.string( "last_name" );
    table.index( [ "first_name", "last_name" ], "idx_users_full_name" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `first_name` VARCHAR(255) NOT NULL,
    `last_name` VARCHAR(255) NOT NULL,
    INDEX `idx_users_full_name` (`first_name`, `last_name`)
)
```

## foreignKey

Create a foreign key constraint from one or more columns. Follow up this call with calls to the `TableIndex`'s [`references`](broken://pages/-LA-U_axqzow_9OdzTRT#references) and [`onTable`](broken://pages/-LA-U_axqzow_9OdzTRT#onTable) methods.

| Argument | Type            | Required | Default                                                           | Description                                                                    |
| -------- | --------------- | -------- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| columns  | string or array | `true`   |                                                                   | The column or array of columns that references a key or keys on another table. |
| name     | string          | `false`  | A generated name consisting of the table name and column name(s). | The name of the foreign key constraint.                                        |

**Example:**

**SchemaBuilder**

```
schema.create( "users", function( table ) {
    table.unsignedInteger( "country_id" );
    table.foreignKey( "country_id" ).references( "id" ).onTable( "countries" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `country_id` INTEGER UNSIGNED NOT NULL,
    CONSTRAINT `fk_users_country_id` FOREIGN KEY (`country_id`) REFERENCES `countries` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION
)
```

## primaryKey

Create a primary key constraint from one or more columns.

| Argument | Type            | Required | Default                                                           | Description                                                  |
| -------- | --------------- | -------- | ----------------------------------------------------------------- | ------------------------------------------------------------ |
| columns  | string or array | `true`   |                                                                   | The column or array of columns that make up the primary key. |
| name     | string          | `false`  | A generated name consisting of the table name and column name(s). | The name of the primary key constraint.                      |
|          |                 |          |                                                                   |                                                              |

**Example:**

**SchemaBuilder**

```
schema.create( "posts_users", function( table ) {
    table.unsignedInteger( "post_id" ).references( "id" ).onTable( "posts" );
    table.unsignedInteger( "user_id" ).references( "id" ).onTable( "users" );
    table.primaryKey( [ "post_id", "user_id" ], "pk_posts_users" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `posts_users` (
    `post_id` VARCHAR(255) NOT NULL,
    `user_id` VARCHAR(255) NOT NULL,
    INDEX `idx_users_full_name` (`first_name`, `last_name`),
    CONSTRAINT `fk_posts_users_post_id` FOREIGN KEY (`post_id`) REFERENCES `posts` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION,
    CONSTRAINT `fk_posts_users_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION,
    CONSTRAINT ""pk_users_first_name_last_name"" PRIMARY KEY (""first_name"", ""last_name"")
)
```

## unique

Create a unique constraint from one or more columns.

| Argument | Type            | Required | Default                                                           | Description                                                        |
| -------- | --------------- | -------- | ----------------------------------------------------------------- | ------------------------------------------------------------------ |
| columns  | string or array | `true`   |                                                                   | The column or array of columns that make up the unique constraint. |
| name     | string          | `false`  | A generated name consisting of the table name and column name(s). | The name of the unique constraint.                                 |

**Example:**

**SchemaBuilder**

```
schema.create( "users", function( table ) {
    table.increments( "id" );
    table.string( "username ");
    table.unique( "username" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
    UNIQUE (`username`)
)
```


# Altering Tables and Views

## alter

The alter method loads up an existing table in order to make modifications. These modifications may include adding, renaming, or dropping columns and constraints.

To begin altering an existing table, call the `alter` method off of the `SchemaBuilder`. This method takes a callback as the second parameter that is passed a `Blueprint` object, much like the [`create`](/12.1.0/schema-builder/create) method.

| Argument | Type     | Required | Default | Description                                                                                                       |
| -------- | -------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------- |
| table    | string   | `true`   |         | The name of the table to alter.                                                                                   |
| callback | function | `true`   |         | A callback function used to define the alterations to the table. It is passed a `Blueprint` as the only argument. |
| options  | struct   | `false`  | `{}`    | Options to pass to `queryExecute`.                                                                                |
| execute  | boolean  | `false`  | `true`  | Run the query immediately after building it.                                                                      |

> Calling multiple methods inside a single `alter` callback creates multiple SQL statements to be executed. qb takes care of this execution for you by default.

The following methods off of `Blueprint` let you modify the table inside the callback:

### addColumn

Add a new column to an existing table. Takes a `Column` instance as the only argument.

Any instance of `Column` is valid like those returned by the [column methods](/12.1.0/schema-builder/columns) (`integer`, `string`, etc.) as well as the [column modifier methods](/12.1.0/schema-builder/column-modifiers) (`unsigned`, `nullable`, etc.).

| Argument | Type     | Required | Default | Description                          |
| -------- | -------- | -------- | ------- | ------------------------------------ |
| column   | `Column` | `true`   |         | A column object to add to the table. |

**Example:**

**SchemaBuilder**

```javascript
schema.alter( "users", function( table ) {
    table.addColumn( table.boolean( "is_active" ) );
} );
```

**SQL (MySQL)**

```sql
ALTER TABLE `users` ADD `is_active` TINYINT(1) NOT NULL
```

### raw

An escape hatch to directly insert any sql in to the statement.

| Argument | Type   | Required | Default | Description                                    |
| -------- | ------ | -------- | ------- | ---------------------------------------------- |
| sql      | string | `true`   |         | The sql to insert directly into the statement. |

**Example:**

**SchemaBuilder**

```javascript
schema.alter( "registrars", function ( table ) {
    table.addColumn(
        table.raw( "HasDNSSecAPI bit NOT NULL CONSTRAINT DF_registrars_HasDNSSecAPI DEFAULT (0)" )
    );
} );
```

**SQL (MySQL)**

```sql
ALTER TABLE `registrars`
ADD HasDNSSecAPI bit NOT NULL
CONSTRAINT DF_registrars_HasDNSSecAPI DEFAULT (0)
```

### dropColumn

Drop a column on an existing table.

| Argument | Type   | Required | Default | Description                     |
| -------- | ------ | -------- | ------- | ------------------------------- |
| name     | string | `true`   |         | The name of the column to drop. |

**Example:**

**SchemaBuilder**

```javascript
schema.alter( "users", function( table ) {
    table.dropColumn( "username" );
} );
```

**SQL (MySQL)**

```sql
ALTER TABLE `users` DROP COLUMN `username`
```

### modifyColumn

Modify an existing column on a table.

| Argument | Type     | Required | Default | Description                                  |
| -------- | -------- | -------- | ------- | -------------------------------------------- |
| name     | string   | `true`   |         | The name of the column to modify.            |
| column   | `Column` | `true`   |         | A column object to replace the named column. |

**Example:**

**SchemaBuilder**

```javascript
schema.alter( "users", function( table ) {
    table.modifyColumn( "name", table.string( "username" ) );
} );
```

**SQL (MySQL)**

```sql
ALTER TABLE `users` CHANGE `name` `username` VARCHAR(255) NOT NULL
```

### renameColumn

Rename a column on a table. A full `Column` instance is required as the second argument for Grammars that need to redeclare the column definition when renaming.

| Argument | Type     | Required | Default | Description                                              |
| -------- | -------- | -------- | ------- | -------------------------------------------------------- |
| name     | string   | `true`   |         | The current name of a column.                            |
| column   | `Column` | `true`   |         | A column object with the new column name and definition. |

**Example:**

**SchemaBuilder**

```javascript
schema.alter( "users", function( table ) {
    table.renameColumn( "name", table.string( "username" ) );
} );
```

**SQL (MySQL)**

```sql
ALTER TABLE `users` CHANGE `name` `username` VARCHAR(255) NOT NULL
```

### addConstraint

Add an index or key to an existing table. Any `TableIndex` instance is valid, like those created by the [index methods](broken://pages/-LA-U_axqzow_9OdzTRT) (`unique`, `index`, `primaryKey`, etc.).

| Argument   | Type         | Required | Default | Description                                    |
| ---------- | ------------ | -------- | ------- | ---------------------------------------------- |
| constraint | `TableIndex` | `true`   |         | The `TableIndex` instance to add to the table. |

**Example:**

**SchemaBuilder**

```javascript
schema.alter( "users", function( table ) {
    table.addConstraint( table.unique( "username" ) );
} );
```

**SQL (MySQL)**

```sql
ALTER TABLE `users` ADD CONSTRAINT `unq_users_username` UNIQUE (`username`)
```

### dropConstraint

Drop an existing table constraint.

| Argument | Type                   | Required | Default | Description                                                                                                               |
| -------- | ---------------------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------- |
| name     | string OR `TableIndex` | `true`   |         | The name of the constraint to drop. You can alternatively pass a `TableIndex` instance to use the dynamic name generated. |

**Example:**

**SchemaBuilder**

```javascript
schema.alter( "users", function( table ) {
    table.dropConstraint( "unq_users_full_name" );
    table.dropConstraint( table.unique( "username" ) );
} );
```

**SQL (MySQL)**

```sql
ALTER TABLE `users` DROP INDEX `unq_users_full_name`
ALTER TABLE `users` DROP INDEX `unq_users_username`
```

### dropIndex

Drop an existing index.

| Argument | Type                   | Required | Default | Description                                                                                                          |
| -------- | ---------------------- | -------- | ------- | -------------------------------------------------------------------------------------------------------------------- |
| name     | string OR `TableIndex` | `true`   |         | The name of the index to drop. You can alternatively pass a `TableIndex` instance to use the dynamic name generated. |

**Example:**

**SchemaBuilder**

```javascript
schema.alter( "users", function( table ) {
    table.dropIndex( "idx_username" );
    table.dropIndex( table.index( "username" ) );
} );
```

**SQL (MySQL)**

```sql
ALTER TABLE `users` DROP INDEX `idx_username`
ALTER TABLE `users` DROP INDEX `idx_users_username`
```

**SQL (SQL Server)**

```sql
DROP INDEX [users].[idx_username]
DROP INDEX [users].[idx_users_username]
```

### renameConstraint

Rename an existing table constraint.

| Argument | Type                   | Required | Default | Description                                                                                                                                |
| -------- | ---------------------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| oldName  | string OR `TableIndex` | `true`   |         | The old or current name of the constraint to rename. You can alternatively pass a `TableIndex` instance to use the dynamic name generated. |
| newName  | string OR `TableIndex` | `true`   |         | The new name of the constraint.  You can alternatively pass a `TableIndex` instance to use the dynamic name generated.                     |

**Example:**

**SchemaBuilder**

```javascript
schema.alter( "users", function( table ) {
    table.renameConstraint( "unq_users_first_name_last_name", "unq_users_full_name" );
} );
```

**SQL (MySQL)**

```sql
ALTER TABLE `users` RENAME INDEX `unq_users_first_name_last_name` TO `unq_users_full_name`
```

## renameTable

Rename an existing table.

| Argument | Type   | Required | Default | Description                                     |
| -------- | ------ | -------- | ------- | ----------------------------------------------- |
| oldName  | string | `true`   |         | The old or current name of the table to rename. |
| newName  | string | `true`   |         | The new name of the table.                      |

**Example:**

**SchemaBuilder**

```javascript
schema.renameTable( "workers", "employees" );
```

**SQL (MySQL)**

```sql
RENAME TABLE `workers` TO `employees`
```

## rename

An alias for `renameTable`.

| Argument | Type   | Required | Default | Description                                     |
| -------- | ------ | -------- | ------- | ----------------------------------------------- |
| oldName  | string | `true`   |         | The old or current name of the table to rename. |
| newName  | string | `true`   |         | The new name of the table.                      |

**Example:**

**SchemaBuilder**

```javascript
schema.rename( "workers", "employees" );
```

**SQL (MySQL)**

```sql
RENAME TABLE `workers` TO `employees`
```

## alterView

Shortcut method frop `dropView` and `createView` together.

| Argument | Type     | Required | Default | Description                                                                                            |
| -------- | -------- | -------- | ------- | ------------------------------------------------------------------------------------------------------ |
| view     | string   | `true`   |         | The name of the view to drop and create.                                                               |
| callback | function | `true`   |         | A callback function used to define the table body. It is passed a `QueryBuilder` as the only argument. |
| options  | struct   | `false`  | `{}`    | Options to pass to `queryExecute`.                                                                     |
| execute  | boolean  | `false`  | `true`  | Run the query immediately after building it.                                                           |


# Dropping Tables and Views

Dropping tables straightforward in `qb`.

> For dropping columns or constraints, see [Alter](/12.1.0/schema-builder/alter).

## drop

Drop a table from the database.

| Argument | Type    | Required | Default | Description                                  |
| -------- | ------- | -------- | ------- | -------------------------------------------- |
| table    | string  | `true`   |         | The name of the table to drop.               |
| options  | struct  | `false`  | `{}`    | Options to pass to `queryExecute`.           |
| execute  | boolean | `false`  | `true`  | Run the query immediately after building it. |

**Example:**

**SchemaBuilder**

```javascript
schema.drop( "user_logins" );
```

**SQL (MySQL)**

```sql
DROP TABLE `user_logins`
```

## dropIfExists

Drop a table from the database if it exists.

| Argument | Type    | Required | Default | Description                                  |
| -------- | ------- | -------- | ------- | -------------------------------------------- |
| table    | string  | `true`   |         | The name of the table to drop.               |
| options  | struct  | `false`  | `{}`    | Options to pass to `queryExecute`.           |
| execute  | boolean | `false`  | `true`  | Run the query immediately after building it. |

**Example:**

**SchemaBuilder**

```javascript
schema.dropIfExists( "user_logins" );
```

**SQL (MySQL)**

```sql
DROP TABLE IF EXISTS `user_logins`
```

## dropView

Drop a table from the database.

| Argument | Type    | Required | Default | Description                                  |
| -------- | ------- | -------- | ------- | -------------------------------------------- |
| view     | string  | `true`   |         | The name of the view to drop.                |
| options  | struct  | `false`  | `{}`    | Options to pass to `queryExecute`.           |
| execute  | boolean | `false`  | `true`  | Run the query immediately after building it. |

**Example:**

**SchemaBuilder**

```javascript
schema.view( "user_logins" );
```

**SQL (MySQL)**

```sql
DROP VIEW `user_logins`
```

## truncate

Truncates the data from a table.

| Argument | Type    | Required | Default | Description                                  |
| -------- | ------- | -------- | ------- | -------------------------------------------- |
| table    | string  | `true`   |         | The name of the table to truncate the data.  |
| options  | struct  | `false`  | `{}`    | Options to pass to `queryExecute`.           |
| execute  | boolean | `false`  | `true`  | Run the query immediately after building it. |

**Example:**

**SchemaBuilder**

```javascript
schema.truncate( "user_logins" );
```

**SQL (MySQL)**

```sql
TRUNCATE TABLE `user_logins`
```


# Debugging

### pretend

A `SchemaBuilder` instance can be put into pretend mode by calling the `pretend` method.  In this mode, the `SchemaBuilder` will turn all query operations into no-ops. A log of the SQL that would have been executed can be retrieved from the query log.

Once a `SchemaBuilder` instance has been set to pretend mode, it cannot be unset.  Instead, you will need to obtain a new `SchemaBuilder` instance.

### queryLog

Each instance of a `SchemaBuilder` maintains a log of queries it executed.  This can be accessed by calling `getQueryLog`. This will return an array of structs like so:

```json
[
  {
    "sql": "CREATE TABLE `users` (`id` INT PRIMARY KEY AUTO_INCREMENT, `email` VARCHAR NOT NULL)",
    "bindings": [],
    "options": { "datasource": "main" },
    "returnObject": "array",
    "pretend": false,
    "result": {},
    "executionTime": 21
  }
]
```

This can be very useful in combination with the [`pretend`](#pretend) feature to see what SQL will be executed before actually executing it.


# Introduction

## Introduction

qb is a fluent query builder for CFML. It is **heavily** inspired by [Eloquent](https://laravel.com/docs/5.3/eloquent) from [Laravel](https://laravel.com/).

Using qb, you can:

* Quickly scaffold simple queries
* Make complex, out-of-order queries possible
* Abstract away differences between database engines

## Requirements

* BoxLang 1+
* Adobe ColdFusion 2021+
* Lucee 5+

qb supports five database grammars:

* MySQL (`MySQLGrammar@qb`)
* Oracle (`OracleGrammar@qb`)
* Postgres (`PostgresGrammar@qb`)
* Microsoft SQL Server (`SqlServerGrammar@qb`)
* SQLite (`SQLiteGrammar@qb`)
* Derby (`DerbyGrammar@qb`)

### Discussion & Help

The Box modules discussion group and community can be found here:

<https://community.ortussolutions.com/c/box-modules/qb/27>

## Installation

Installation is easy through [CommandBox](https://www.ortussolutions.com/products/commandbox) and [ForgeBox](https://www.coldbox.org/forgebox). Simply type `box install qb` to get started.

## Code Samples

Compare these two examples:

```cfscript
// Plain old CFML
var results = queryExecute( "SELECT * FROM users" );

// qb
var qb = wirebox.getInstance( "QueryBuilder@qb" );
var results = qb.from( "users" ).get();
```

The differences become even more stark when we introduce more complexity:

```cfscript
// Plain old CFML
var results = queryExecute(
    "SELECT * FROM posts WHERE published_at IS NOT NULL AND author_id IN ?",
    [ { value = "5,10,27", cfsqltype = "CF_SQL_NUMERIC", list = true } ]
);

// qb
var qb = wirebox.getInstance( "QueryBuilder@qb" );
var results = qb.from( "posts" )
    .whereNotNull( "published_at" )
    .whereIn( "author_id", [ 5, 10, 27 ] )
    .get();
```

With qb you can easily handle setting order by statements before the columns you want or join statements after a where clause:

```cfscript
var qb = wirebox.getInstance( "QueryBuilder@qb" );
var results = qb.from( "posts" )
         .orderBy( "published_at" )
         .select( "post_id", "author_id", "title", "body" )
         .whereLike( "author", "Ja%" )
         .join( "authors", "authors.id", "=", "posts.author_id" )
         .get();

// Becomes
var results = queryExecute(
    "SELECT post_id, author_id, title, body FROM posts INNER JOIN authors ON authors.id = posts.author_id WHERE author LIKE ? ORDER BY published_at",
    [ { value = "Ja%", cfsqltype = "CF_SQL_VARCHAR", list = false, null = false } ]
);
```

qb enables you to explore new ways of organizing your code by letting you pass around a query builder object that will compile down to the right SQL without you having to keep track of the order, whitespace, or other SQL gotchas!

Here's a gist with an example of the powerful models you can create with this! <https://gist.github.com/elpete/80d641b98025f16059f6476561d88202>

## Usage

To start a new query, instantiate a new Builder: `wirebox.getInstance( "QueryBuilder@qb" )`.

By default, qb uses a generic Grammar. You can specify your specific grammar in ColdBox by setting the `defaultGrammar` in your `moduleSettings`.

```cfscript
moduleSettings = {
    qb = {
        defaultGrammar = "MySQLGrammar@qb"
    }
};
```

If you are not using WireBox, just make sure to wire up the `Builder` object with the correct grammar:

```cfscript
var grammar = new qb.models.Query.Grammars.MySQLGrammar();
var builder = new qb.models.Query.Builder( grammar );
```


# What's New?

## 12.0.0

### Breaking Changes

#### Add new [`convertEmptyStringsToNull`](/12.0.0/installation-and-usage#configuration-settings) setting and default to true.

qb now automatically converts an empty string value to `null` when inserting into a query.  If your application relies on inserting or updating values to an empty string, set this setting to `false`.

#### Remove `autoAddScale` setting.

qb now always automatically adds a `scale` to `decimal` and `float` query params. This has been the default since [v8.5.0](#id-8.5.0). This can still be overridden by providing a full struct query param when adding bindings.

#### Remove `strictDateDetection` setting

qb will now only use type introspection over the `isDate` function for all date detection. This has been the default since [v9.0.0](#id-9.0.0).

#### Remove `autoDeriveNumericType` setting

qb will only use `INTEGER` or `DECIMLAL` sql types instead of the more ambiguous `NUMERIC`. This has been the default since [v9.0.0](#id-9.0.0).

#### Allow for default values for [`max`](/12.0.0/query-builder/executing-queries/aggregates#max), [`min`](/12.0.0/query-builder/executing-queries/aggregates#min), [`count`](/12.0.0/query-builder/executing-queries/aggregates#count), and [`sum`](/12.0.0/query-builder/executing-queries/aggregates#sum) functions

The argument order change to account for the new `defaultValue` argument. If you are using positional parameters with these functions, please migrate to the new function signatures.

#### Removal of `CF_SQL` prefix

The `CF_SQL` prefix for `cfsqltype` has been optional since [ColdFusion 11](https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-tags/tags-p-q/cfqueryparam.html), so while this change should not impact any running application, we are labelling it as a breaking change out of an abundance of caution.

#### Initializer Argument change for `QueryUtils`

To support removal of the settings above and to add a new setting to convert empty strings to null, the `QueryUtils` class' initializer has been modified.  If you are creating this class manually, please check the API docs and upgrade to the new initializer arguments.

### New Features

* New `DerbyGrammar` support.
* Allow queries [without a table name or `FROM` clause](/12.0.0/query-builder/building-queries/from#from).
* Add a new [`returningAll()`](/12.0.0/query-builder/executing-queries/inserts-updates-deletes#returningall) shortcut method for `returning( "*" )`.
* Order your queries randomly with the [`orderByRandom`](/12.0.0/query-builder/building-queries/ordering-grouping-and-limit#order-by-random) method.
* New [`createAs`](/12.0.0/schema-builder/create#createas) method available on `SchemaBuilder`.
* `TRUNCATE` tables with [`SchemaBuilder.truncate( ... )`](/12.0.0/schema-builder/drop#truncate).
* **SQL Server**: Add support for [`FOR ...` clauses](/12.0.0/query-builder/building-queries/for).
* **SQL Server**: Allow restricting the [`DELETE UNMATCHED` clause in `upsert`](/12.0.0/query-builder/executing-queries/inserts-updates-deletes#upsert).
* **Postgres**: Add [`jsonb(`](/12.0.0/schema-builder/columns#jsonb)`)` support in `SchemaBuilder`.
* **MySQL**: Use `JSON` type for [`json()`](/12.0.0/schema-builder/columns#json) columns.

### Bug Fixes

* Compatibility fixes for BoxLang and Adobe ColdFusion.
* Compatibility for pure BoxLang (without the `bx-compat-cfml` module).
* Fix the `count` method for pagination when being used with a query with `DISTINCT` turned on.
* Fix for `UPDATE` queries with `RETURNING` clauses being invalid.
* Improve performance for [`exists`](/12.0.0/query-builder/executing-queries/aggregates#exists) queries.
* **Postgres**: Use the native `UUID` type for [`guid()`](/12.0.0/schema-builder/columns#guid) columns.
* **Oracle**: Support Unicode versions of table column types (e.g. [`unicodeText()`](/12.0.0/schema-builder/columns#unicodetext))

## 11.1.0

**QueryBuilder:** Support JOINS in DELETE statements for supported grammars, like MySQL and SQL Server.

## 11.0.3

**QueryBuilder:** Don't overly specify that grammars must extend `BaseGrammar`. It's just an implicit interface, after all.

## 11.0.2

**QueryBuilder:** Have aliases work with full server qualifications, like `ServerName.schemaName.tableName`.

## 11.0.1

### Allow for disabling of wrapping values

Either a Grammar setting (`setShouldWrapValues( true|false )`) or for a one-off Query Builder ([`withoutWrappingValues()`](/12.0.0/query-builder/options-and-utilities/query-options#withoutwrappingvalues) / [`withWrappingValues()`](/12.0.0/query-builder/options-and-utilities/query-options#withwrappingvalues)) can control whether identifiers like table names, columns, etc. are wrapped.

### BoxLang Compatibility

This release includes updates to be compatible with the latest releases of BoxLang.

## 11.0.0

### Auto Boolean Casting

Grammars will be able to influence the `cfsqltype` and value when passing in a literal boolean value as a binding. Postgres and SQLite have boolean support, so they will keep the literal boolean value and use a `cfsqltype` of `CF_SQL_OTHER`. SQL Server uses `CF_SQL_BIT`, Oracle users `CF_SQL_NUMERIC`, and MySQL uses `CF_SQL_TINYINT` — all of these will convert literal boolean values to either 1 or 0. This behavior is skipped when providing a custom `cfsqltype`.

{% hint style="info" %}
Custom grammars can implement the `getBooleanSqlType` and `convertBooleanValue` methods to customize this behavior.
{% endhint %}

{% hint style="danger" %}
Additionally, attempting to change the grammar with any bindings currently configured will throw an exception. This is because the bindings are converted via the grammar when added to the builder and cannot be changed retroactively when setting a new grammar. Set the grammar first before configuring the query to avoid this exception.
{% endhint %}

## 10.0.2

**QueryUtils:** Fix timestamp formatting losing timezone information

## 10.0.1

**QueryUtils:** Manually construct ISO 8601 timestamps due to lack of Adobe support

## 10.0.0

* Full compatibility for running on [BoxLang](https://boxlang.io/) with the [`bx-compat-cfml`](https://forgebox.io/view/bx-compat-cfml) module.
* Internal property name changes for BoxLang compatibility as well as cleaner code. (This *may* cause breaking changes, in rare cases.  See the [Migration Guide](https://qb.ortusbooks.com/12.0.0/pages/-LA-U_b2vfkZD-h5AIUm#v10.0.0) for more details.)

## 9.8.1

* Fix missing `parseNumber` function for ACF
* Add alias to `clone()`

## 9.8.0

Support alias renaming using [`withAlias`](/12.0.0/query-builder/building-queries/from#withalias)&#x20;

## 9.7.1

Add in missing join compilations.

## 9.7.0

Implement [crossApply](/12.0.0/query-builder/building-queries/joins#crossapply) and [outerApply](/12.0.0/query-builder/building-queries/joins#outerapply) for supported Grammars

## 9.6.1

Expand type annotation for `from`. This can be a string or an Expression.

## 9.6.0

Make [`addBindings`](/12.0.0/query-builder/building-queries/parameters-and-bindings#addbindings) and [`addBindingsFromBuilder`](/12.0.0/query-builder/building-queries/parameters-and-bindings#addbindingsfrombuilder) publicly accessible.

## 9.5.1

Add MariaDB support to `AutoDiscover@qb` grammar. (It will choose the `MySQLGrammar@qb`.)

## 9.5.0

Add [`findOrFail`](/12.0.0/query-builder/executing-queries/retrieving-results#findorfail) and [`existsOrFail`](/12.0.0/query-builder/executing-queries/aggregates#existsorfail) methods, inspired by [Quick](https://quick.ortusbooks.com).

## 9.4.1

Better Support for OracleGrammar in SchemaBuilder

* Fix trigger creation by escaping colons (`:`).
* Try to drop associated sequences and triggers when dropping a table.
* Better support for creating a table in a different schema by only checking for the last identifier as the table name in [`hasTable`](/12.0.0/schema-builder/schema-builder#hastable) and [`hasColumn`](/12.0.0/schema-builder/schema-builder#hascolumn).

## 9.4.0

Allow for setting a [`defaultSchema`](/12.0.0/schema-builder/schema-builder) property on a `SchemaBuilder` instance.

The `defaultSchema` will be used for methods like [`hasTable`](/12.0.0/schema-builder/schema-builder#hastable) and [`hasColumn`](/12.0.0/schema-builder/schema-builder#hascolumn). A passed in `schema` will still take precedence.

## 9.3.1

* Use `CHAR` for `GUID` and `UUID` types in MySQL.
* Don't call `getUtils` from inside `QueryUtils`.

## 9.3.0

Make [`replaceBindings`](/12.0.0/query-builder/options-and-utilities/query-options#replacing-or-inlining-bindings) publicly available in `QueryUtils`.

This is used by qb to inline query bindings in `toSQL` or `dump` calls and can be used to inline the bindings in other tools like[ CommandBox Migrations](https://forgebox.io/view/commandbox-migrations).

## 9.2.5

Use named parameters when passing to `BaseGrammar`. This avoids problems where custom Grammars have extra arguments and we add arguments to the official grammar.

## 9.2.4

{% hint style="info" %}
We apologize for the new features in a patch release.
{% endhint %}

#### New Features

* Add the ability to pretend to run queries, both in [QueryBuilder](/12.0.0/query-builder/debugging#pretend) and [SchemaBuilder](/12.0.0/schema-builder/debugging#pretend).
* Add query logging to [QueryBuilder](/12.0.0/query-builder/debugging#querylog) and [SchemaBuilder](/12.0.0/schema-builder/debugging#querylog) instances.

#### Bug Fixes

* Use varchar for clob when converting to a CFML query. This is used when removing a column like in Oracle pagination.

## 9.2.3

Handle more numeric SQL types like `AtomicInteger` and `Long`.

## 9.2.2

Add millisecond accuracy to inline bindings.

## 9.2.1

Separate `having` bindings from `where` bindings.

## 9.2.0

### New Features

We now support the `returning` function inside `update` and `delete` statements for supported Grammars.  Supported grammars are SQL Server, Postgres, and SQLite.

### Bug Fixes

* Fix raw table name parsing in update queries for `SqlServerGrammar`.
* Fix truncating text in nested wheres inside joins.
* Fix out of order bindings in joinSub

## 9.1.5

Switch from `table_catalog` to `table_schema` when referencing schema for `PostgresGrammar`.

## 9.1.4

CommandBox-friendly injections for SQL Commenter.

## 9.1.3

Add support for `from` bindings, used especially in `fromSub` queries.

## 9.1.2

This release reverts the use of native `returntype`s.  There are too many bugs between engine implementations to make it viable.  No end-user changes should be visible.

## 9.1.1

Make `withReturnFormat` a public method.

## 9.1.0

### New Features

Add ability to inline bindings when calling `toSQL` and `dump`. These strings can be executed in a DBMS application.

### Bug Fixes

* Move `coldbox` namespace injection to the function body so CommandBox doesn't blow up.
* Correctly apply native returntypes after `newQuery` and `withReturnFormat`.

## 9.0.2

* Fix losing `defaultOptions` when calling `newQuery`.
* Shortcut for no return format using `none`.
* Allow for native struct returntypes. Requires a return format of `none`.

## 9.0.1

Fix `RouteInfoCommenter` file name.

## 9.0.0

### Breaking Changes

#### Dropped support for Adobe ColdFusion 2016

Adobe has ended support for ACF 2016, and so must we.

#### SchemaBuilder's `uuid` split into [guid()](/12.0.0/schema-builder/columns#guid) and [uuid()](/12.0.0/schema-builder/columns#uuid)

CFML's `uuid` does not match other languages; it's one character shorter. Because of this, the value from `createUUID()` cannot be used in some database column types like SQL Server's `uniqueidentifier`. This made for some confusion in SchemaBuilder since it wasn't clear if `uuid` meant CFML's definition or the wider world's definition.

So, the types have been split, following Lucee's pattern, into [`uuid`](/12.0.0/schema-builder/columns#uuid) (matching CFML's [`createUUID()`](https://cfdocs.org/createuuid)) and [`guid`](/12.0.0/schema-builder/columns#guid) (matching Java's UUID or [`createGUID()`](https://cfdocs.org/createguid) on Lucee).

#### Returning all rows from [paginate](/12.0.0/query-builder/executing-queries/retrieving-results#paginate) when maxRows is  0 or lower

Popular grid frameworks like Quasar and Datatables use values of 0 or -1 to return all rows from a query. This is now supported in qb. Previously, it generated an invalid query (`SELECT * FROM users LIMIT 0 OFFSET 0`).

This behavior can be customized by providing a callback to the `shouldMaxRowsOverrideToAll` setting or `init` argument. For instance, to revert to the previous behavior you would set the function as follows:

```cfscript
moduleSettings = {
    "qb": {
        "shouldMaxRowsOverrideToAll": function( maxRows ) {
            return false;
        }
    }
};
```

#### [`autoDeriveNumericType`](/12.0.0/query-builder/building-queries/parameters-and-bindings#numeric-sql-type) is now the default

Introduced in [8.10.0](#8.10.0), this feature uses separate SQL types for integers and decimals to increase performance in certain database grammars.  This feature is now the default, but the previous behavior can be enabled by setting `autoDeriveNumericType` to `false`.

{% hint style="warning" %}
**Note:** the option to revert to the old behavior will be removed in the next major version.
{% endhint %}

#### [`strictDateDetection`](/12.0.0/query-builder/building-queries/parameters-and-bindings#strict-date-detection) is now the default

Introduced in [8.1.0](#8.1.0), this feature only returns a SQL type of `CF_SQL_TIMESTAMP` if the param is a date object, not just a string that looks like a date.  This helps avoid situations where some strings were incorrectly interpreted as dates.  For many, the migration path is straightforward — calls to [`now()`](https://cfdocs.org/now) are already date objects as well as any function that operates on a date.  If you need to parse a string as a date, the [`parseDateTime`](https://cfdocs.org/parsedatetime) built-in function can accomplish that.

{% hint style="warning" %}
**Note:** the option to revert to the old behavior **may** be removed in the next major version.
{% endhint %}

### New Features and Improvements

#### SQLite Grammar Support

Thanks to [Jason Steinhouer](https://github.com/jsteinshouer), qb now supports SQLite for both `QueryBuilder` and `SchemaBuilder`.  You can use it in your apps by specifying `SQLiteGrammar@qb` as the default grammar.

#### [sqlCommenter Support](/12.0.0/query-builder/debugging/sqlcommenter)

sqlCommenter is a [specification by Google](https://google.github.io/sqlcommenter/) for adding contextual information as a comment at the end of a SQL statement.  This can give insights into your application, especially when diagnosing slow queries. Examples of the information you can append to your queries are `route`, `handler`, `action`, `version`, and others, as well as the ability to add your own, such as `loggedInUser` and more.

#### [sumRaw](/12.0.0/query-builder/executing-queries/aggregates#sumraw) helper function

There's a new shortcut method to return `qb.sum( qb.raw( expression ) )`. You're welcome. 😉

#### Dedicated [`dropIndex`](/12.0.0/schema-builder/alter#dropindex) method

Some grammars, like SQL Server, do not treat simple indexes as constraints.  For this reason, we've added a [`dropIndex`](/12.0.0/schema-builder/alter#dropindex) method alongside the existing [`dropConstraint`](/12.0.0/schema-builder/alter#dropconstraint).

#### [`columnList`](/12.0.0/query-builder/executing-queries/aggregates#columnlist) helper method

[`columnList`](/12.0.0/query-builder/executing-queries/aggregates#columnlist) will return either an array of column names for the configured table or the query that is generated by `cfdbinfo` for the configured table.  Especially useful when working with dynamically generated grids.&#x20;

### Bug Fixes

* Correctly compile `insertUsing` statements that use Common Table Expressions (CTEs).
* Update `announceInterception` calls for ColdBox 7. (Thank you, Michael Born.)
* Fixed `insertUsing` not placing Common Table Expressions (CTEs) in the correct order.
* Added the missing keyword in the Postgres [`upsert`](/12.0.0/query-builder/executing-queries/inserts-updates-deletes#upsert) syntax.
* Don't add `DISTINCT` when doing a `COUNT(*)`.
* Support aggregates for unioned queries.

## 8.10.0

* Add a [`firstOrFail`](/12.0.0/query-builder/executing-queries/retrieving-results#firstorfail) fetch method inspired by [Quick](https://quick.ortusbooks.com).
* There are now [specific numeric SQL types for integers and decimals](/12.0.0/query-builder/building-queries/parameters-and-bindings#numeric-sql-type) used during the `inferSQLType` check in `QueryUtils`.  This is an opt-in feature, enabled by setting the `autoDeriveNumericType` setting. The previous approach was to use `CF_SQL_NUMERIC` for all numeric types which could cause performance issues in some grammars as they interpreted all `CF_SQL_NUMERIC` as floating point numbers.

## 8.9.1

* `HOLDLOCK` and `READPAST` are mutually exclusive table locks in SQL Server but were mistakenly being applied together.

## 8.9.0

* Specify `defaultOptions` [inside of your ColdBox config.](/12.0.0/query-builder/options-and-utilities/query-options)

## 8.8.1

* Better parsing of `raw` statements when deriving [`insertUsing`](/12.0.0/query-builder/executing-queries/inserts-updates-deletes#insertusing) columns.

## 8.8.0

### New Features and Improvements

* Insert data based off of a callback or builder using [`insertUsing`](/12.0.0/query-builder/executing-queries/inserts-updates-deletes#insertusing).
* Insert data ignoring duplicate key errors using [`insertIgnore`](/12.0.0/query-builder/executing-queries/inserts-updates-deletes#insertignore).
* Use a callback or builder as the source for an [`upsert`](/12.0.0/query-builder/executing-queries/inserts-updates-deletes#upsert) statement.
* Allow for deleting unmatched source records in [upserts](/12.0.0/query-builder/executing-queries/inserts-updates-deletes#upsert) (SQL Server only).
* Add a new `skipLocked` flag to [`lockForUpdate`](/12.0.0/query-builder/building-queries/locks#lockforupdate).

### Bug Fixes

* Don't uppercase quoted aliases in Oracle.
* Fix for aliases in update statements.
* Don't sort columns for `insertUsing`.
* Add subquery bindings in insert and upsert statements.
* Maintain column order when using source in upsert.

## 8.7.8

* Fix for Oracle returning custom column types when renaming a column.

## 8.7.7

* Explicit arguments scoping.

## 8.7.6

* `arrayEach` is slow compared to merging arrays.

## 8.7.5

* Fix wheres with joins in update statements.

## 8.7.2

* Add better null handling to `inferSqlType`.

## 8.7.1

* Correctly format columns being updated.

## 8.7.0

### New Features and Improvements

* Add an [upsert](/12.0.0/query-builder/executing-queries/inserts-updates-deletes#upsert) method.  `upsert` can update or insert multiple records at once depending on if a column is matched.
* Allow expressions in [`value`](/12.0.0/query-builder/executing-queries/retrieving-results#value) and [`values`](/12.0.0/query-builder/executing-queries/retrieving-results#values).  Also add a [`valueRaw`](/12.0.0/query-builder/executing-queries/retrieving-results#valueraw) and [`valuesRaw`](/12.0.0/query-builder/executing-queries/retrieving-results#valuesraw) helper method to make that pattern more ergonomic.
* Allow [`JOIN` statements in `UPDATE` statements](/12.0.0/query-builder/executing-queries/inserts-updates-deletes#updating-with-joins).  (This is **not** supported on Oracle.)
* Allow [updates with subselects](/12.0.0/query-builder/executing-queries/inserts-updates-deletes#updating-with-subselects) using closures or builder instances.

### Bug Fixes

* Better handling of [`group by`](/12.0.0/query-builder/building-queries/group-by-and-having#groupby) and [`having`](/12.0.0/query-builder/building-queries/group-by-and-having#having) clauses in [pagination](/12.0.0/query-builder/building-queries/limit-offset-and-pagination#simplepaginate-and-paginate) queries.
* Allow any value to be returned from [aggregates](/12.0.0/query-builder/executing-queries/aggregates) including strings, numbers, and dates.
* Provide default values for [sum](/12.0.0/query-builder/executing-queries/aggregates#sum) and [count](/12.0.0/query-builder/executing-queries/aggregates#count) if no records are returned.
* Test in CI with [full](https://coldfusion.adobe.com/2018/07/null-support-in-coldfusion-2018/) [null](https://docs.lucee.org/guides/cookbooks/NullSupport.html) support.

## 8.6.1

* Correctly wrap CTE expressions with parenthesis when required in certain grammars.

## 8.6.0

* `SchemaBuilder` can now be configured with [default query options](/12.0.0/schema-builder/schema-builder).  (Default options will still be overridden by options passed to each `SchemaBuilder` method.)

## 8.5.0

### QueryBuilder

* Add a [`reset`](/12.0.0/query-builder/options-and-utilities/clone-and-reset#reset) method to QueryBuilder.
* Add [locking](/12.0.0/query-builder/building-queries/locks) helpers such as [`lock`](/12.0.0/query-builder/building-queries/locks#lock), [`noLock`](/12.0.0/query-builder/building-queries/locks#nolock), [`lockForUpdate`](/12.0.0/query-builder/building-queries/locks#lockforupdate), and [`sharedLock`](/12.0.0/query-builder/building-queries/locks#sharedlock).
* Correct return aggregate values for date values from `max` and `min` executors.
* [Automatically add a `scale`](/12.0.0/query-builder/building-queries/parameters-and-bindings#automatic-scale-detection) to an incoming query param when needed.
* Add a [`whereNotLike`](/12.0.0/query-builder/building-queries/wheres#wherenotlike) shortcut method.
* Correctly format a `COUNT(DISTINCT column)` query.
* Only use bulk insert syntax when needed in OracleGrammar due to interactions between the `result` parameter to `cfquery`, Lucee, and the Oracle JDBC driver.

### SchemaBuilder

* Add support for [stored computed columns](/12.0.0/schema-builder/column-modifiers#storedas) and [virtual computed columns](/12.0.0/schema-builder/column-modifiers#virtualas).

## 8.4.9

* Swap `master` branch to `main` branch.

## 8.4.8

* Remove unnecessary injection for QueryUtils.

## 8.4.7

* Account for raw expressions when generating mementos for comparison

## 8.4.6

* Add support for [mediumtext](/12.0.0/schema-builder/columns#mediumtext) & [longtext](/12.0.0/schema-builder/columns#longtext) types for MySQLGrammar.

## 8.4.5

* Fix limit on [simplePaginate](/12.0.0/query-builder/executing-queries/retrieving-results#simplepaginate).

## 8.4.1 - 8.4.4

* Migrate release process to GitHub Actions.

## 8.4.0

* Add a `simplePaginate` pagination method for quicker performance when total records or total pages are not needed or too slow.

## 8.3.0

* Introduce a [`numericSQLType`](/12.0.0/query-builder/building-queries/parameters-and-bindings#numeric-sql-type) setting to specify the default numeric SQL type.

## 8.2.2

* Default to `html` for the `dump` format argument to `writeDump`.

## 8.2.1

* Correctly use the passed in `strictDateDetection` to the `QueryUtils.cfc`.

## 8.2.0

{% hint style="success" %}
📹 [Watch a walkthrough of this change on CFCasts.](https://cfcasts.com/series/whats-new-in-qb-8)
{% endhint %}

* Added a [`dump`](/12.0.0/query-builder/debugging#dump) command to aid in debugging a query while chaining.

## 8.1.0

{% hint style="success" %}
📹 [Watch a walkthrough of these changes on CFCasts.](https://cfcasts.com/series/whats-new-in-qb-8)
{% endhint %}

* [`orderByRaw`](/12.0.0/query-builder/building-queries/ordering-grouping-and-limit#order-by-raw) now can accept bindings.
* A new, optional [`strictDateDetection`](/12.0.0/query-builder/building-queries/parameters-and-bindings#strict-date-detection) setting is available to check the underlying Java class of a date object instead of using `isDate`.

## 8.0.3

* Ignore select bindings for aggregate queries.
* Allow spaces in table aliases.
* Split FLOAT and DECIMAL column types in SQL Server.

## 8.0.2

* Clear orderBy bindings when calling `clearOrders`.

## 8.0.1

* Trim table definitions before searching for aliases.  Makes qb more lenient with extra whitespace.

## 8.0.0

{% hint style="success" %}
📹 [Watch a walkthrough of these changes on CFCasts.](https://cfcasts.com/series/whats-new-in-qb-8)
{% endhint %}

#### BREAKING CHANGES

* \`\`[`when`](/12.0.0/query-builder/building-queries/when#when) callbacks now automatically scope and group where clauses when an `OR` combinator is used.

#### Other Changes

* Combine [`clearOrders`](/12.0.0/query-builder/building-queries/ordering-grouping-and-limit#clearorders) and `orderBy` with a new [`reorder`](/12.0.0/query-builder/building-queries/ordering-grouping-and-limit#reorder)method.
* Clear current selected columns with [`clearSelect`](/12.0.0/query-builder/building-queries/selects#clearselect).
* Combine [`clearSelect`](/12.0.0/query-builder/building-queries/selects#clearselect) and either [`select`](/12.0.0/query-builder/building-queries/selects#get) or [`selectRaw`](/12.0.0/query-builder/building-queries/selects#get-3) with [`reselect`](/12.0.0/query-builder/building-queries/selects#reselect) and [`reselectRaw`](/12.0.0/query-builder/building-queries/selects#reselectraw) respectively.

## 7.10.0

* Expose nested where functions to enable advanced query manipulation in downstream libraries like Quick.

## 7.9.9

* Fixes for OracleGrammar including table aliases and wrapped subqueries.

## 7.9.8

* Allow nullable [timestamps](/12.0.0/schema-builder/columns#timestamp) in MySQL.

## 7.9.7

* Return 0 on null [aggregates](/12.0.0/query-builder/executing-queries/aggregates).

## 7.9.6

* Match type hints to documentation for [join](/12.0.0/query-builder/building-queries/joins) functions

## 7.9.5

* Handle enhanced numeric checks with Secure Profile enabled.

## 7.9.4

* Allow raw statements in basic where clauses.

## 7.9.3

* Passed along the options struct to the [`count`](/12.0.0/query-builder/executing-queries/aggregates#count) method when calling [`paginate`](/12.0.0/query-builder/building-queries/limit-offset-and-pagination#paginate).

## 7.9.2

* Allow for space-delimited [sort](/12.0.0/query-builder/building-queries/ordering-grouping-and-limit) directions like `column DESC`.
* Add helpful message when trying to use a closure with [`from`](/12.0.0/query-builder/building-queries/from#get) instead of [`fromSub`](/12.0.0/query-builder/building-queries/from#get-3).
* \`\`[`value`](/12.0.0/query-builder/executing-queries/retrieving-results#value) and [`values`](/12.0.0/query-builder/executing-queries/retrieving-results#values) now work with [column formatters.](/12.0.0/query-builder/options-and-utilities/column-formatter)
* Correctly format RETURNING clauses with [column formatters](/12.0.0/query-builder/options-and-utilities/column-formatter) and ignoring table qualifiers.

## 7.9.1

* Handle multi-word columns in `queryRemoveColumns`.

## 7.9.0

* Remove elvis operator due to ACF compatibility issues

## 7.8.0

* Add support for [MONEY](/12.0.0/schema-builder/columns#money) and [SMALLMONEY](/12.0.0/schema-builder/columns#smallmoney) data types to [SchemaBuilder](/12.0.0/schema-builder/create).

## 7.7.3

* Fix wrapping of [enum](/12.0.0/schema-builder/columns#enum) types for Postgres.

## 7.7.2

* Compatibility fix for ACF 2018 and `listLast` parsing.
* Include current\_timestamp default for [`timestamp`](/12.0.0/schema-builder/columns#timestamp) columns in SchemaBuilder.
* Ignore table qualifiers for insert and update.

## 7.7.1

* Fix a bug with preventDuplicateJoins when using the closure syntax with a join.

## 7.7.0

* Add executionTime to the data output from BaseGrammar, including being available in interceptors.

## 7.6.2

* Fix a case where a column was not wrapped correctly when a `where` used a subquery for the value.

## 7.6.1

* Avoid `duplicate` function due to cbORM / Hibernate bugs when used in the same application.

## 7.6.0

* Split off a private `whereBasic` method.  This is used in Quick to provide extra sql type features.
* Add a [`clearOrders`](/12.0.0/query-builder/building-queries/ordering-grouping-and-limit#clearorders) method.  Any already configured orders are cleared.  Any orders added after this call will be added as normal.
* [`selectRaw`](/12.0.0/query-builder/building-queries/selects#get-3) now can take an array of expressions.

## 7.5.1

Fixed an issue using column formatters with `update` and `insert`.

## 7.5.0

Using a new `preventDuplicateJoins` setting in the module settings, qb can detect duplicate joins and ignore them. This is especially useful in a heavily filtered and dynamic query where you may or may not need the join at all or more than one column may need the same join. `preventDuplicateJoins` defaults to `false`, so it is opt-in. It may be turned on by default in a future breaking release of qb.

## 7.4.0

Enhance order by's with more direction options ([c767ac8](https://github.com/coldbox-modules/qb/commit/c767ac8764fab70d70dc77baa7bb9fb27c1d4eeb))

You can now use two shortcut methods: `orderByAsc` and `orderByDesc`. Additionally, `orderBySub` or using `orderBy` with a closure or builder instance will respect the direction argument.

## 7.3.15

* Fix using `whereBetween` with query param structs ([07c9b72](https://github.com/coldbox-modules/qb/commit/07c9b728bdbad6bf02ccd9d21dbdf6968062c02e))

## 7.3.14

* Ignore orders in aggregate queries ([39e1338](https://github.com/coldbox-modules/qb/commit/39e1338a147838165e05225bd91ef7e6cde2319a))

## 7.3.13

* Format with cfformat ([dc2a9b6](https://github.com/coldbox-modules/qb/commit/dc2a9b61503690d753a71c3b7bce002ebdf4ccda))

## 7.3.12

* Improve column wrapping with trimming ([d98a5cb](https://github.com/coldbox-modules/qb/commit/d98a5cb65851c154b6755e90254d1a2c1df82833))
* Prefer the parent query over magic methods when the parent query has the exact method. ([f9fd8d1](https://github.com/coldbox-modules/qb/commit/f9fd8d157cdc0d7480811c4659c130ee1d58888f))

## 7.3.9, 7.3.10, 7.3.11

* Switch to using [ForgeBox Storage](https://commandbox.ortusbooks.com/forgebox-enterprise/storage#storing-package-binaries-on-forgebox).

## 7.3.8

* Allow passing query options in to paginate ([cdecfb3](https://github.com/coldbox-modules/qb/commit/cdecfb36f5acab87edd3a478c570f77d285df554))

## 7.3.7

* Fix for inserting null values directly ([1de27a6](https://github.com/coldbox-modules/qb/commit/1de27a697f65bfdeed63442ad66be47cd0d30344))

## 7.3.5, 7.3.6

* Use cfformat for automatic formatting ([119e434](https://github.com/coldbox-modules/qb/commit/119e434b307a2cc2323b857a214c20842cafbbd4))
* Add a type to the onMissingMethod exception ([90d1093](https://github.com/coldbox-modules/qb/commit/90d109312b2ea86c00db34020b12b5ab22bb377b))

## 7.3.4

* Correctly wrap [comments](/12.0.0/schema-builder/column-modifiers#comment) in `MySQLGrammar`.

## 7.3.2, 7.3.3

* Publish qb apidocs to [Ortus API Docs](https://apidocs.ortussolutions.com/#/coldbox-modules/qb/).

## 7.3.1

* Fix for null values breaking the new `checkIsActuallyNumeric` method in `QueryUtils`.

## 7.3.0

* Add a `parameterLimit` public property to `SqlServerGrammar`.  This property is used in Quick to split up eager loading to work around the 2100 param limit of SQL Server.

## 7.2.0

* Allow a [parent query](broken://pages/-LxZv7a5KIrwcD1HJyVa) to be set.  A parent query will receive any method calls that are not found on the Query Builder instance.  This is especially useful for instances like [Quick](https://quick.ortusbooks.com/) to allow Quick features like scopes to be available inside any closures.

## 7.1.0

* Lambdas (arrow functions) are now allowed wherever closures are allowed.
* Add an [`orderByRaw`](/12.0.0/query-builder/building-queries/ordering-grouping-and-limit#order-by-raw) method.
* Allow for fully-qualified column names (`table_name.column.name`) in the [`value`](/12.0.0/query-builder/executing-queries/retrieving-results#value) and [`values`](/12.0.0/query-builder/executing-queries/retrieving-results#values) methods.

## 7.0.0

#### **BREAKING CHANGES**

*Please see the* [*Migration Guide*](/12.0.0/migration-guide#v-7-0-0) *for more information on these changes.*

* Drop support for Lucee 4.5 and Adobe ColdFusion 11.
* `MSSQLGrammar` renamed to `SqlServerGrammar`
* Remove variadic parameters support in builder functions like `select`.
* The `defaultGrammar` mapping needs to be the full WireBox mapping, including the `@qb`, if needed.
  * For instance, `MSSQLGrammar` would become `MSSQLGrammar@qb`.
  * This will allow for other grammars to be more easily contributed via third party modules.
* The argument names of `forPage` changed to match the new `paginate` method.
* Add `defaultValue` and optional exception throwing to `value`. (This changed the argument order.)
* All methods that could conceivably take a subquery as well as a value now accept a closure or another builder instance to use as a subquery. (This changed the argument names in some instances.)

#### **Other Changes**

* Completely revamped documentation! (You're looking at it right now.)
* Add new flag to [`toSQL( showBindings = true )`](/12.0.0/query-builder/debugging#tosql) to replace question marks (`?`) with `cfqueryparam`-compatible structs for debugging.
* Preserve column case and order when converting a query to an array using the default `"array"` return format.
* Add a new [paginate](/12.0.0/query-builder/executing-queries/retrieving-results#paginate) method to generate a pagination struct alongside the results.  This can be customized using a custom [PaginationCollector](/12.0.0/query-builder/executing-queries/retrieving-results#custom-pagination-collectors).
* Allow raw values in [`insert`](/12.0.0/query-builder/executing-queries/inserts-updates-deletes#insert) calls.
* Allow [default `queryExecute` `options`](/12.0.0/query-builder/options-and-utilities/query-options#default-options) to be configure at a Query Builder level.  This also enables custom `QueryBuilders` a la [Hyper](https://www.forgebox.io/view/hyper).
* Add a [`whereLike`](/12.0.0/query-builder/building-queries/wheres#wherelike) method.
* Allow closures to be used in left and right joins.
* Provide an [`addUpdate`](/12.0.0/query-builder/executing-queries/inserts-updates-deletes#addupdate) method to programmatically build the `SET` clause of an update query.
* [Add a new `chunk` method](/12.0.0/query-builder/executing-queries/retrieving-results#chunking-results) to grab records from the database in small sets.
* Add `raw` in `alterTable` segments.
* Add `dropAllObjects` support for `SqlServerGrammar` and `OracleGrammar` to support `migrate fresh` from cfmigrations.
* Add a `renameTable` alias for `rename`.
* Remove default constraints when dropping columns with a default on `SqlServerGrammar`.
* Add more column types and column helpers to `SchemaBuilder`, including:
  * `datetimeTz`
  * `lineString`
  * `nullableTimestamps`
  * `point`
  * `polygon`
  * `softDeletes`
  * `softDeletesTz`
  * `timeTz`
  * `timestamps`
  * `timestampTz`
  * `timestampsTz`
  * `withCurrent`

\*\*\*\*

## 6.4.0

* [Allow Expressions (`query.raw`) in update statements.](/12.0.0/whats-new)


# Installation & Usage

## Installation

Installation is easy through [CommandBox](https://www.ortussolutions.com/products/commandbox) and [ForgeBox](https://www.forgebox.io/). Simply type `box install qb` to get started.

## Usage

To start a new query, instantiate a new Builder: `wirebox.getInstance('QueryBuilder@qb')`.

By default, qb uses a generic Grammar. You can specify your specific grammar in ColdBox by setting the `defaultGrammar` in your `moduleSettings`.

```cfscript
moduleSettings = {
    qb = {
        defaultGrammar = "MySQLGrammar@qb"
    }
};
```

The grammars provided by qb are:

* MySQLGrammar
* OracleGrammar
* PostgresGrammar
* SqlServerGrammar
* SQLiteGrammar
* DerbyGrammar

If you are not using WireBox, make sure to wire up the `Builder` object with the correct grammar:

```cfscript
var grammar = new qb.models.Grammars.MySQLGrammar();
var builder = new qb.models.Query.QueryBuilder( grammar );
```

## Configuration Settings

Here are the full configuration settings you can use in the module settings:

```javascript
moduleSettings = {

    qb : {
        "defaultGrammar": "AutoDiscover@qb",
        "defaultReturnFormat": "array",
        "preventDuplicateJoins": false,
        "convertEmptyStringsToNull": true,
        "numericSQLType": "NUMERIC",
        "integerSQLType": "INTEGER",
        "decimalSQLType": "DECIMAL",
        "defaultOptions": {},
        "sqlCommenter": {
            "enabled": false,
            "commenters": [
                { "class": "FrameworkCommenter@qb", "properties": {} },
                { "class": "RouteInfoCommenter@qb", "properties": {} },
                { "class": "DBInfoCommenter@qb", "properties": {} }
            ]
        },
        "shouldMaxRowsOverrideToAll": function( maxRows ) {
            return maxRows <= 0;
        }
    }

}
```

## SQL Type Inference

QB binds all parameters by default and guesses the SQL type based on passed values. The default SQL type for numeric values is `CF_SQL_NUMERIC`, which is a floating point number, for the widest compatibility. This can cause performance problems with large recordsets in some database engines. You can provide a different default in `coldbox.cfc` if you wish to override this setting:

```cfscript
moduleSettings = {
    qb = {
        defaultGrammar = "MySQLGrammar@qb",
        numericSQLType = "CF_SQL_BIGINT"
    }
};
```

## Integrating With FW/1

> Note: These instructions assume a basic knowledge of FW/1, a working FW/1 application structure with qb installed in the `/subsystems` directory (manually or via CommandBox), and a database configured to run with your application.

### Wiring Up With DI/1

Once the application structure is setup, now we need to wire up qb to a bean factory using DI/1.

First we will add a mapping in `Application.cfc`.

```cfscript
this.mappings = {
    "/qb" = expandPath("./subsystems/qb")
};
```

Next we need to tell DI/1 where qb's components are and how to reference them for later use in the application. We can do so by defining the configuration settings in the `variables.framework.subsystems` struct in `Application.cfc`. The example below makes use of a load listener to declare each component instance and pass in any constructor arguments.

```cfscript
qb = {
  diLocations = "/qb/models",
  diConfig = {
    loadListener = function( di1 ) {
      di1.declare( "BaseGrammar" ).instanceOf( "qb.models.Query.Grammars.Grammar" ).done()
         .declare( "MySQLGrammar" ).instanceOf( "qb.models.Query.Grammars.MySQLGrammar" ).done()
         .declare( "QueryUtils" ).instanceOf( "qb.models.Query.QueryUtils" ).done()
         .declare( "QueryBuilder" ).instanceOf( "qb.models.Query.QueryBuilder" )
         .withOverrides({
            grammar = di1.getBean( "MySQLGrammar" ),
            utils = di1.getBean( "QueryUtils" ),
            returnFormat = "array"
         })
         .asTransient();
    }
  }
}
```

### Usage In Your FW/1 Application

Now that everything is configured, you can launch your application with CommandBox by entering `start` in the terminal or use whatever method you're accustomed to.

To access qb from your application's code, you can call on it by using `getBeanFactory()`.

```cfscript
// Create an instance of qb
builder = getBeanFactory( "qb" ).getBean( "QueryBuilder" );
// Query the database
posts = builder.from( "Posts" ).get();
posts = builder.from( "Posts" ).where( "IsDraft", "=", 0 ).get();
```

#### For further instructions on getting started with qb & FW/1, refer to [this blog post](http://tonyjunkes.com/blog/working-with-fw1-and-qb/).


# Migration Guide

## v12.0.0

### Add new [`convertEmptyStringsToNull`](/12.0.0/installation-and-usage#configuration-settings) setting and default to true.

qb now automatically converts an empty string value to `null` when inserting into a query.  If your application relies on inserting or updating values to an empty string, set this setting to `false`.

### Remove `autoAddScale` setting

It is no longer possible to disable auto scale being added.  You can still override any scale by providing it in your query param struct.

### Remove `strictDateDetection` setting

It is no longer possible to disable strict date detection being performed.  You can still override the `cfsqltype` by specifying it in your query param struct.

### Remove `autoDeriveNumericType` setting

It is no longer possible to disable the numeric type detection.  You can specify the numeric types you want used in your settings.  You can also override the `cfsqltype` by specifying it in your query param struct.

### Argument order changed for some aggregate functions

The [`max`](/12.0.0/query-builder/executing-queries/aggregates#max), [`min`](/12.0.0/query-builder/executing-queries/aggregates#min), [`count`](/12.0.0/query-builder/executing-queries/aggregates#count), and [`sum`](/12.0.0/query-builder/executing-queries/aggregates#sum) methods now accept a `defaultValue` argument.  This comes **before** the `defaultOptions` argument.  If you are using positional parameters with any of these functions, update your code to the new method signature.

### Argument order changed for QueryUtils initializer

This only affects people instantiating `QueryUtils` manually (such as non-ColdBox users) and instantiating with positional arguments.

Please review the QueryUtils `init` function and update your code to the new method signature, if needed.

### Generated `cfsqltype` attributes no longer include the `CF_SQL_` prefix

Although it shouldn't impact any running application, out of an abundance of caution, we are labeling the drop of the`CF_SQL_` prefix as a breaking change.  This prefix has been optional since Adobe ColdFusion 11.

## v11.0.0

### Auto Boolean Casting

Grammars will be able to influence the `cfsqltype` and value when passing in a literal boolean value as a binding. Postgres and SQLite have boolean support, so they will keep the literal boolean value and use a`cfsqltype` of `CF_SQL_OTHER`. SQL Server uses `CF_SQL_BIT`, Oracle users`CF_SQL_NUMERIC`, and MySQL uses `CF_SQL_TINYINT` — all of these will convert literal boolean values to either 1 or 0. This behavior is skipped when providing a custom `cfsqltype`. Custom grammars can implement the`getBooleanSqlType` and `convertBooleanValue` methods to customize this behavior.

Most people will not need to change anything in their code for this breaking change.

## v10.0.0

### Dropped Support for Adobe Coldfusion 2018

### Internal variables renamed for compatibility with BoxLang and cleaner code in general

In certifying qb for BoxLang, we discovered that some of the way qb had worked for years was due to a lucky interaction between properties and functions sharing a name.  Both of these values are put into the `variables` scope, and the way qb shared some of these names like the `from` method as well as the `from` property only worked because of the way Lucee and ACF ordered defining the function and properties.  BoxLang is more strict in this regard and probably for the best.  You can probably imagine how setting `variables.from` inside a function called `from` would maybe work once and then cause a very strange bug when trying to call the `from` function internally again.  Because of these reasons, the following properties have had their names changed:

#### QueryBuilder

* `from` -> `tableName`

#### Column

* `nullable` -> `isNullable`
* `unique` -> `isUnique`
* `unsigned` -> `isUnsigned`
* `default` -> `defaultValue`
* `comment` -> `commentValue`
* `onUpdate` -> `onUpdateAction`
* `onDelete` -> `onDeleteAction`

The following functions have had their signatures updated:

#### BaseGrammar

* `compileFrom` -> `compileTableName( required QueryBuilder query, required any tableName )`

For the majority of users, this will not take any updates to their code to work with qb 10.  For users who have created a custom grammar, column type, or a custom QueryBuilder class, you will need to make sure you code uses the updated property names and functions.

## v9.0.0

### Dropped support for Adobe ColdFusion 2016

Adobe has ended support for ACF 2016, and so must we.

### SchemaBuilder's `uuid` split into [guid()](/12.0.0/schema-builder/columns#guid) and [uuid()](/12.0.0/schema-builder/columns#uuid)

CFML's `uuid` does not match other languages; it's one character shorter. Because of this, the value from `createUUID()` cannot be used in some database column types like SQL Server's `uniqueidentifier`. This made for some confusion in SchemaBuilder since it wasn't clear if `uuid` meant CFML's definition or the wider world's definition.

So, the types have been split, following Lucee's pattern, into [`uuid`](/12.0.0/schema-builder/columns#uuid) (matching CFML's [`createUUID()`](https://cfdocs.org/createuuid)) and [`guid`](/12.0.0/schema-builder/columns#guid) (matching Java's UUID or [`createGUID()`](https://cfdocs.org/createguid) on Lucee).

{% hint style="warning" %}
If you are using `uuid` with 36 character UUIDs or SQL Server's `uniqueidentifier` columns, please migrate your `uuid` calls to `guid`.
{% endhint %}

### Returning all rows from [paginate](/12.0.0/query-builder/executing-queries/retrieving-results#paginate) when maxRows is  0 or lower

Popular grid frameworks like Quasar and Datatables use values of 0 or -1 to return all rows from a query. This is now supported in qb. Previously, it generated an invalid query (`SELECT * FROM users LIMIT 0 OFFSET 0`).

{% hint style="success" %}
If this behavior is fine for your application, you don't need to change anything.
{% endhint %}

This behavior can be customized by providing a callback to the `shouldMaxRowsOverrideToAll` setting or `init` argument.&#x20;

{% hint style="danger" %}
If you need to revert to the previous behavior, provide the following as the `shouldMaxRowsOverrideToAll` setting:

```cfscript
moduleSettings = {
    "qb": {
        "shouldMaxRowsOverrideToAll": function( maxRows ) {
            return false;
        }
    }
};
```

{% endhint %}

### [`autoDeriveNumericType`](/12.0.0/query-builder/building-queries/parameters-and-bindings#numeric-sql-type) is now the default

Introduced in [8.10.0](#8.10.0), this feature uses separate SQL types for integers and decimals to increase performance in certain database grammars.  This feature is now the default, but the previous behavior can be enabled by setting `autoDeriveNumericType` to `false`.

{% hint style="success" %}
This behavior *should* be an improvement in most every case without any changes needed.
{% endhint %}

{% hint style="danger" %}
If you need to revert to the previous behavior, provide the following as the `autoDeriveNumericType` setting:

```cfscript
moduleSettings = {
    "qb": {
        "autoDeriveNumericType": false
    }
};
```

{% endhint %}

{% hint style="warning" %}
**Note:** The option to revert to the old behavior will be removed in the next major version.
{% endhint %}

#### [`strictDateDetection`](/12.0.0/query-builder/building-queries/parameters-and-bindings#strict-date-detection) is now the default

Introduced in [8.1.0](#8.1.0), this feature only returns a SQL type of `CF_SQL_TIMESTAMP` if the param is a date object, not just a string that looks like a date.  This helps avoid situations where some strings were incorrectly interpreted as dates.  For many, the migration path is straightforward — calls to [`now()`](https://cfdocs.org/now) are already date objects as well as any function that operates on a date.  If you need to parse a string as a date, the [`parseDateTime`](https://cfdocs.org/parsedatetime) built-in function can accomplish that.

{% hint style="warning" %}
If you are relying on qb treating any strings as dates you will need to parse them as actual date objects first. (You can do so using functions like [`parseDateTime`](https://cfdocs.org/parsedatetime).
{% endhint %}

{% hint style="danger" %}
If you need to revert to the previous behavior, provide the following as the `strictDateDetection` setting:

```cfscript
moduleSettings = {
    "qb": {
        "strictDateDetection": false
    }
};
```

{% endhint %}

{% hint style="warning" %}
**Note:** The option to revert to the old behavior **may** be removed in the next major version.
{% endhint %}

## v8.0.0

### Where clauses with an OR combinator are now automatically wrapped inside [`when`](/12.0.0/query-builder/building-queries/when#when) callbacks

This isn't a breaking change that will affect most people.  In fact, it will most likely improve your code.

Previously, when using the [`when`](/12.0.0/query-builder/building-queries/when#when) control flow function, you were fully responsible for the wrapping of your where statements.  For example, the following query:

```javascript
qb.from( "users" )
    .where( "active", 1 )
    .when( len( url.q ), function( q ) {
        q.where( "username", "LIKE", q & "%" )
            .orWhere( "email", "LIKE", q & "%" );   
    } );
```

Would generate the following SQL:

```sql
SELECT *
FROM "users"
WHERE "active" = ?
    AND "username" = ?
    OR "email" = ?
```

The problem with this statement is that the `OR` can short circuit the `active` check.

The fix is to wrap the `LIKE` statements in parenthesis.  This is done in qb using a function callback to `where`.

```javascript
qb.from( "users" )
    .where( "active", 1 )
    .where( function( q ) {
        q.where( "username", "LIKE", q & "%" )
            .orWhere( "email", "LIKE", q & "%" );
    } );
```

```sql
SELECT *
FROM "users"
WHERE "active" = ?
    AND (
        "username" = ?
        OR "email" = ?
    )
```

When using the `when` control flow function, it was easy to miss this.  This is because you are already in a closure - it looks the same as when using `where` to group the clauses.

In qb 8.0.0, `when` will automatically group added where clauses when needed.  That means our original example now produces the SQL we probably expected.

```javascript
// qb 8.0.0
qb.from( "users" )
    .where( "active", 1 )
    .when( len( url.q ), function( q ) {
        q.where( "username", "LIKE", q & "%" )
            .orWhere( "email", "LIKE", q & "%" );   
    } );
```

```sql
SELECT *
FROM "users"
WHERE "active" = ?
    AND (
        "username" = ?
        OR "email" = ?
    )
```

Grouping is not needed if there is no `OR` combinator.  In these cases no grouping is added.

```javascript
// qb 8.0.0
qb.from( "users" )
    .where( "active", 1 )
    .when( url.keyExists( "admin" ), function( q ) {
        q.where( "admin", 1 )
            .whereNotNull( "hireDate" );
    } );
```

```sql
SELECT *
FROM "users"
WHERE "active" = ?
    AND "admin" = ?
    AND "hireDate IS NOT NULL
```

If you had already wrapped your expression in a group inside the `when` callback, nothing changes.  Your code works as before.  The `OR` combinator check only works on the top most level of added where clauses.

```javascript
qb.from( "users" )
    .where( "active", 1 )
    .when( len( url.q ), function( q ) {
        q.where( function( q2 ) {
            q2.where( "username", "LIKE", q & "%" )
                .orWhere( "email", "LIKE", q & "%" );
        } );
    } );
```

```sql
SELECT *
FROM "users"
WHERE "active" = ?
    AND (
        "username" = ?
        OR "email" = ?
    )
```

Additionally, if you do not add any where clauses inside a `when` callback, nothing changes from qb 7.

The breaking change part is if you were relying on these statements residing at the same level without grouping.  In those cases, you may pass the `withoutScoping` flag to the `when` callback.

```javascript
// qb 8.0.0
qb.from( "users" )
    .where( "active", 1 )
    .when(
        condition = len( url.q ),
        onTrue = function( q ) {
            q.where( "username", "LIKE", q & "%" )
                .orWhere( "email", "LIKE", q & "%" );   
        },
        withoutScoping = true
    );
```

```sql
SELECT *
FROM "users"
WHERE "active" = ?
    AND "username" = ?
    OR "email" = ?
```

## v7.0.0

### Lucee 4.5 and Adobe ColdFusion 11 EOL

Support for Lucee 4.5 and Adobe ColdFusion 11 has been dropped. If you need support for these engines, please remain on an earlier version of qb.

### MSSQLGrammar renamed to SqlServerGrammar

`MSSQLGrammar` was visually too close to `MySQLGrammar` and was hard to differentiate quickly. `SqlServerGrammar` is much more unique and easily identifiable. Additionally, more people that use this library refer to their database engine as "SQL Server" than "MSSQL".

To migrate, replace any instances of `MSSQLGrammar` with `SqlServerGrammar`. Make sure to also append the `@qb` namespace, if needed, [as explained below.](/12.0.0/migration-guide#defaultgrammar-updated-to-be-the-full-wirebox-mapping)

### Variadic Parameters Support Removed

Variadic parameter support was the ability to pass any number of arguments to certain methods like `select`.

```javascript
qb.select( "name", "email", "createdDate" );
```

This code came with a slight performance cost and readability cost. That, combined with the fact that the above syntax is very close to an array, we are dropping support for variadic parameters. To migrate, wrap instances of variadic parameters in an array:

```javascript
qb.select( [ "name", "email", "createdDate" ] );
```

### defaultGrammar updated to be the full WireBox mapping

In previous versions, the value passed to `defaultGrammar` was used to look up a mapping in the `@qb` namespace. This made it difficult to add or use grammars that weren't part of qb. (You could get around this be registering your custom grammar in the `@qb` namespace, but doing so seemed strange.)

To migrate this code, change your `defaultGrammar` to be the full WireBox mapping in your `moduleSettings`:

```javascript
moduleSettings = {
    "qb": {
        "defaultGrammar": "MSSQLGrammar@qb"
    }
};
```

### value method argument order changed

A `defaultValue` parameter and optional exception throwing was added to `value`. This pushed the `options` struct to the end of the method. If you are using positional parameters with `value`, you will need to update your method calls to either use named parameters or the new positions.

```javascript
public any function value(
    required string column,
    string defaultValue = "",
    boolean throwWhenNotFound = false,
    struct options = {}
);
```

### Some methods renamed `callback` to `query`

All methods that could conceivably take a subquery as well as a value now accept a closure or another builder instance to use as a subquery. This led to changing the `callback` argument to `query` in the following cases:

* `whereSub`
* `whereInSub`
* `whereExists`
* `orWhereExists`
* `whereNotExists`
* `andWhereNotExists`
* `orWhereNotExists`
* `whereNullSub`
* `orderBySub`
* `subSelect`

If you are using named parameters with any of the above methods you will need to migrate your method calls.

## v5.0.0

Version `v5.0.0` brings support for `SchemaBuilder` inside `qb`. To avoid naming confusion, `Builder` was renamed to `QueryBuilder`. Any references in your code to `Builder@qb` need to be updated to `QueryBuilder@qb`.


# Contributing & Filing Issues

We welcome all types of contributions!

The most common type of contribution is to fix an incorrect SQL generation for a database grammar.

To debug what SQL is being ran, you can always call `toSQL` on any `QueryBuilder` or `SchemaBuilder` object. Additionally, you can listen to the `preQBExecute` interception point for the generated SQL.

Each of the database grammars have two tests — `{Grammar}QueryBuilderSpec.cfc` and `{Grammar}SchemaBuilderSpec.cfc`. These tests run the same qb syntax across the different grammars. In each test are methods that return SQL strings like so:

```javascript
// MSSQLQueryBuilderSpec.cfc
function orWhere() {
    // If just a string is returned, we assume the bindings is an empty array ([])
    return {
        sql = "SELECT * FROM [users] WHERE [id] = ? OR [email] = ?",
        bindings = [ 1, "foo" ]
    };
}
```

```javascript
// OracleSchemaBuilderSpec.cfc
function boolean() {
    // returns an array since schema builder can execute multiple statements.
    return [ "CREATE TABLE ""USERS"" (""ACTIVE"" NUMBER(1, 0) NOT NULL)" ];
}
```

If you find an issue with the SQL generated from a grammar, please file a pull request with the correct SQL in these tests. It's okay if you don't submit a fix as well. (But we'd greatly appreciate it!) Doing so will help expedite the fix.

If you want to add support for a new database grammar, simply copy these two tests from an existing grammar, rename them, change the `getBuilder` method to return your new grammar, and fill out the SQL as it should be. That will guide your implementation to be 100% compatible with the other grammars in qb.


# Getting a New Query

A query builder is a stateful, transient object. That means that if you want to execute two different queries, you need two separate instances of `QueryBuilder`.

{% code title="QueryBuilder" %}

```javascript
// This will cause you pain and grief...

var user = query.from( "users" )
  .where( "username", rc.username )
  .first();

var posts = query.from( "posts" ).get();
// This will error because `username` is not a column in `posts`.
```

{% endcode %}

As such, be careful when injecting QueryBuilder in to a component. If the component is a singleton, you will need to create the QueryBuilder inline or use a provider. This applies to ColdBox handlers as well.

{% code title="handlers/posts.cfc" %}

```javascript
component {

    property name="query" inject="QueryBuilder@qb";

    function create( event, rc, prc ) {
        // This will cause you pain and grief...
        query.table( "posts" )
            .where( "id", rc.id )
            .update( event.getOnly( [ "body" ] ) );
    }

}
```

{% endcode %}

While the above may seem innoculous, it can run in to issues as multiple requests come in to your application. Each request is sharing the same query builder instance and subsequent requests will have unintended results as the `where` clause keeps growing request after request.

The solution is to either create the QueryBuilder inline, ensuring that each request has its own query to execute:

{% code title="handlers/posts.cfc" %}

```javascript
component {

    function create( event, rc, prc ) {
        getInstance( "QueryBuilder@qb" )
            .table( "posts" )
            .where( "id", rc.id )
            .update( event.getOnly( [ "body" ] ) );
    }

}
```

{% endcode %}

Or to use a WireBox provider to create a new query each time it is accessed:

{% code title="handlers/posts.cfc" %}

```javascript
component {

    property name="query" inject="provider:QueryBuilder@qb";

    function create( event, rc, prc ) {
        query.table( "posts" )
            .where( "id", rc.id )
            .update( event.getOnly( [ "body" ] ) );
    }

}
```

{% endcode %}

{% hint style="warning" %}
One caveat when using a WireBox Provider: WireBox Providers proxy methods on to a new instance of the provided mapping on all methods except `get`. `get` is a method on the Provider itself. If you call `get` as the first method on a Provider it will return a new instance of QueryBuilder, not execute the query. In those (rare) cases you will need to call `query.get().get()`.
{% endhint %}

## newQuery

Once you have access to a QueryBuilder instance, you can create a new query using the same datasource, utils, returnFormat, paginationCollector, columnFormatter, and defaultOptions as the current QueryBuilder instance.

```javascript
// This will cause you pain and grief...

var user = query.from( "users" )
  .where( "username", rc.username )
  .first();

var posts = query.newQuery().from( "posts" ).get();
// This will work as we expect it to.
```


# Building Queries


# Selects

## Specifying A Select Clause

You may not always want to select all columns from a database table. You can influence the select list of a query with the following methods.

Individual columns can contain fully-qualified names (`some_table.some_column`), table aliases (`alias.some_column`), and even set column aliases themselves (`some_column AS c`). The `columns` argument can be a single column, a list of columns (comma-separated), or an array of columns.

## select <a href="#get" id="get"></a>

| Name    | Type            | Required | Default | Description                                                        |
| ------- | --------------- | -------- | ------- | ------------------------------------------------------------------ |
| columns | string \| array | `false`  | ​`"*"`  | A single column, list of columns, or array of columns to retrieve. |

When calling `select` any previous columns are discarded. If you want to incrementally select columns, use the `addSelect` method.

If you pass no columns to this method, it will default to `"*"`.

{% code title="QueryBuilder" %}

```javascript
query.select( [ "fname AS firstName", "age" ] ).from( "users" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT `fname` AS `firstName`, `age` FROM `users`
```

{% endcode %}

## distinct <a href="#get" id="get"></a>

| Name  | Type    | Required | Default | Description                     |
| ----- | ------- | -------- | ------- | ------------------------------- |
| state | boolean | `false`  | ​`true` | Value to set the distinct flag. |

Calling distinct will cause the query to be executed with the `DISTINCT` keyword.

{% code title="QueryBuilder" %}

```javascript
query.select( "username" ).distinct().from( "users" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT DISTINCT `username` FROM `users`
```

{% endcode %}

{% hint style="info" %}
`distinct` applies to the entire query, not just certain fields.
{% endhint %}

## addSelect <a href="#get" id="get"></a>

| Name    | Type            | Required | Default | Description                                                                 |
| ------- | --------------- | -------- | ------- | --------------------------------------------------------------------------- |
| columns | string \| array | `true`   | ​       | A single column, list of columns, or array of columns to add to the select. |

This method adds the columns passed to it to the currently selected columns.

{% hint style="warning" %}
If the `QueryBuilder` is currently selecting all columns (`"*"`) when this method is called, the incoming columns will becoming the only columns selected.
{% endhint %}

{% code title="QueryBuilder" %}

```javascript
query.addSelect( [ "fname AS firstName", "age" ] ).from( "users" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT `fname` AS `firstName`, `age` FROM `users`
```

{% endcode %}

## selectRaw <a href="#get" id="get"></a>

| Name       | Type  | Required | Default | Description                                  |
| ---------- | ----- | -------- | ------- | -------------------------------------------- |
| expression | any   | `true`   | ​       | The raw expression for the select statement. |
| bindings   | array | `false`  | `[]`    | Any bindings needed for the raw expression.  |

A shortcut to use a raw expression in the select clause.

The expression is added to the other already selected columns.

*(To learn more about raw and expressions, check out the docs on* [*Raw Expressions*](/12.0.0/query-builder/building-queries/raw-expressions)*.)*

{% code title="QueryBuilder" %}

```javascript
query.selectRaw( "YEAR(birthdate) AS birth_year" ).from( "users" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT YEAR(birthdate) AS birth_year FROM `users`
```

{% endcode %}

## subSelect <a href="#get" id="get"></a>

| Name  | Type                     | Required | Default | Description                                    |
| ----- | ------------------------ | -------- | ------- | ---------------------------------------------- |
| alias | string                   | `true`   | ​       | The alias for the subselect expression.        |
| query | Function \| QueryBuilder | `true`   |         | The callback or query to use in the subselect. |

The method lets you pass either a callback or a `QueryBuilder` instance to be used as a subselect expression. If a callback is passed it will be passed a new query instance as the only parameter.

The subselect is added to the other already selected columns.

{% code title="QueryBuilder" %}

```javascript
query.subSelect( "last_login_date", function( q ) {
    q.selectRaw( "MAX(created_date)" )
        .from( "logins" )
        .whereColumn( "users.id", "logins.user_id" );
} ) ).from( "users" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT (
    SELECT MAX(created_date)
    FROM `logins`
    WHERE `users`.`id` = `logins`.`user_id`
) AS `last_login_date`
FROM `users
```

{% endcode %}

## clearSelect <a href="#clearselect" id="clearselect"></a>

| Name         | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      | \`\`     |         |             |

Clears out the selected columns for a query along with any configured select bindings.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .select( [ "fname AS firstName", "age" ] )
    .clearSelect();
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT * FROM `users`
```

{% endcode %}

## reselect <a href="#reselect" id="reselect"></a>

| Name    | Type            | Required | Default | Description                                                        |
| ------- | --------------- | -------- | ------- | ------------------------------------------------------------------ |
| columns | string \| array | `false`  | ​`"*"`  | A single column, list of columns, or array of columns to retrieve. |

Clears out the selected columns for a query along with any configured select bindings. Then sets a selection of columns to select from the query. Any valid argument to [`select`](/12.0.0/query-builder/building-queries/selects#get) can be passed here.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .select( [ "fname AS firstName", "age" ] )
    .reselect( "username" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT `username` FROM `users`
```

{% endcode %}

## reselectRaw <a href="#reselectraw" id="reselectraw"></a>

| Name       | Type  | Required | Default | Description                                  |
| ---------- | ----- | -------- | ------- | -------------------------------------------- |
| expression | any   | `true`   | ​       | The raw expression for the select statement. |
| bindings   | array | `false`  | `[]`    | Any bindings needed for the raw expression.  |

Clears out the selected columns for a query along with any configured select bindings. Then adds an Expression or array of expressions to the already selected columns.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .select( [ "fname AS firstName", "age" ] )
    .reselectRaw( "YEAR(birthdate) AS birth_year" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT YEAR(birthdate) AS birth_year FROM `users`
```

{% endcode %}


# From

## from <a href="#from" id="from"></a>

| Name | Type                 | Required | Default | Description                                                                 |
| ---- | -------------------- | -------- | ------- | --------------------------------------------------------------------------- |
| from | string \| Expression | `true`   | ​       | The name of the table or a Expression object from which the query is based. |

Used to set the base table for the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT * FROM `users`
```

{% endcode %}

You can optionally specify an alias for the table.

{% code title="QueryBuilder" %}

```javascript
query.from( "users as u" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT * FROM `users` AS `u`
```

{% endcode %}

{% hint style="info" %}
A query does not need to have a table name specified.  If a query does not, it will be executed without a table (in the manner specified by the grammar).
{% endhint %}

## table <a href="#table" id="table"></a>

| Name  | Type                 | Required | Default | Description                                                                 |
| ----- | -------------------- | -------- | ------- | --------------------------------------------------------------------------- |
| table | string \| Expression | `true`   | ​       | The name of the table or a Expression object from which the query is based. |

An alias for `from` where you like how calling `table` looks.

{% code title="QueryBuilder" %}

```javascript
query.table( "users" ).insert( { "name" = "jon" } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
INSERT INTO `users` (`name`) VALUES (?)
```

{% endcode %}

## fromRaw <a href="#fromraw" id="fromraw"></a>

| Name     | Type   | Required | Default | Description                             |
| -------- | ------ | -------- | ------- | --------------------------------------- |
| from     | string | `true`   | ​       | The sql snippet to use as the table.    |
| bindings | array  | `false`  | `[]`    | Any bindings needed for the expression. |

Sometimes you need more control over your `from` clause in order to add grammar specific instructions, such as adding SQL Server table hints to your queries.

{% code title="QueryBuilder" %}

```javascript
query.fromRaw( "[users] u (nolock)" ).get();
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT * FROM [users] u (nolock) 
```

{% endcode %}

Since the `fromRaw()` takes your string verbatim, it's important that you make sure your SQL declaration is escaped properly. Failure to properly escape your table names may result in SQL errors.

{% hint style="warning" %}
Using `fromRaw` will most likely tie your code to a specific database, so think carefully before using the `fromRaw` method if you want your project to be database agnostic.
{% endhint %}

Many database engines allow you to define User Defined Functions. For example, SQL Server allows you to define UDFs that will return a table. In these type of cases, it may be necessary to bind parameters to your `from` clause.

You can bind parameters to the `fromRaw()` method by passing a secondary argument that is an array of the parameters to bind.

{% code title="QueryBuilder" %}

```javascript
query.fromRaw(
    "dbo.generateDateTable(?, ?, ?) as dt",
    [ "2017-01-01", "2017-12-31", "m" ]
).get();
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT * FROM dbo.generateDateTable(?, ?, ?) as dt
```

{% endcode %}

## fromSub <a href="#fromsub" id="fromsub"></a>

| Name  | Type                     | Required | Default | Description                                                                |
| ----- | ------------------------ | -------- | ------- | -------------------------------------------------------------------------- |
| alias | string                   | `true`   | ​       | The alias for the derived table.                                           |
| input | Function \| QueryBuilder | `true`   |         | Either a `QueryBuilder` instance or a closure to define the derived query. |

Complex queries often contain derived tables. Derived tables are essentially a temporal table defined as a subquery in the `from` statement.

{% code title="QueryBuilder" %}

```javascript
query.select( [ "firstName", "lastName" ] )
    .fromSub( "legalUsers", function ( q ) {
        q.select( [ "lName as lastName", "fName as firstName" ] )
            .from( "users" )
            .where( "age", ">=", 21 )
        ;
    } )
    .orderBy( "lastName" )
    .get()
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT `firstName`, `lastName`
FROM (
    SELECT `lName` as `lastName`, `fName` as `firstName`
    FROM `users`
    WHERE `age` >= 21
) AS `legalUsers`
ORDER BY `lastName`
```

{% endcode %}

In additional a function callback, a separate `QueryBuilder` instance can be passed to the `fromSub` method.

{% code title="QueryBuilder" %}

```javascript
var legalUsersQuery = query
    .select( [ "lName as lastName", "fName as firstName" ] )
    .from( "users" )
    .where( "age", ">=", 21 );

query.select( [ "firstName", "lastName" ] )
    .fromSub( "legalUsers", legalUsersQuery )
    .orderBy( "lastName" )
    .get();
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT `firstName`, `lastName`
FROM (
    SELECT `lName` as `lastName`, `fName` as `firstName`
    FROM `users`
    WHERE `age` >= 21
) AS `legalUsers`
ORDER BY `lastName`
```

{% endcode %}

## withAlias

<table><thead><tr><th>Name</th><th>Type</th><th data-type="checkbox">Required</th><th>Default Value</th><th>Description</th></tr></thead><tbody><tr><td>alias</td><td><code>string</code></td><td>true</td><td></td><td>The new alias to use for the table.</td></tr></tbody></table>

Adds an alias to the specified `from` table or renames a current alias.  Any existing aliased values in `columns`, `wheres`, `joins`, `groupBys`, or `orders` that match the previous alias will be remapped to the new alias.  This includes the full table name when used as an alias.

```cfscript
qb.from( "users" ).select( [ "users.name", "birthdate" ] );
// SELECT "users"."name", "birthdate" FROM "users"
qb.withAlias( "u1" );
// SELECT "u1"."name", "birthdate" FROM "users" AS "u1"
```


# For

{% hint style="warning" %}
This section only applies to SQL Server Grammars.
{% endhint %}

In SQL Server, `FOR` clauses are how you can return JSON or XML directly from your query.

In qb, only raw expressions are accepted via the `forRaw` method.

## forRaw

<table><thead><tr><th width="147.90625">Name</th><th width="121.19921875">Type</th><th width="80.03125">Required</th><th width="89.56640625">Default</th><th>Description</th></tr></thead><tbody><tr><td>expression</td><td>string</td><td>true</td><td></td><td>The raw sql for the <code>FOR</code> clause.</td></tr></tbody></table>

{% code title="QueryBuilder" %}

```javascript
query
    .select( [ "id", "name" ] )
    .from( "users" )
    .forRaw( "JSON AUTO" );
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT [id], [name]
FROM [users]
FOR JSON AUTO
```

{% endcode %}


# Joins

Join clauses range from simple to complex including joining complete subqueries on multiple conditions. qb has your back with all of these use cases.

| Table of Contents                                                   |                                                                           |                                                                           |                                                                       |
| ------------------------------------------------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------- |
| [join](/12.0.0/query-builder/building-queries/joins#join)           | [joinRaw](/12.0.0/query-builder/building-queries/joins#joinraw)           | [joinSub](/12.0.0/query-builder/building-queries/joins#joinsub)           | [joinWhere](/12.0.0/query-builder/building-queries/joins#joinwhere)   |
| [leftJoin](/12.0.0/query-builder/building-queries/joins#leftjoin)   | [leftJoinRaw](/12.0.0/query-builder/building-queries/joins#leftjoinraw)   | [leftJoinSub](/12.0.0/query-builder/building-queries/joins#leftjoinsub)   | [newJoin](/12.0.0/query-builder/building-queries/joins#newjoin)       |
| [rightJoin](/12.0.0/query-builder/building-queries/joins#get)       | [rightJoinRaw](/12.0.0/query-builder/building-queries/joins#rightjoinraw) | [rightJoinSub](/12.0.0/query-builder/building-queries/joins#rightjoinsub) | [JoinClause](/12.0.0/query-builder/building-queries/joins#joinclause) |
| [crossJoin](/12.0.0/query-builder/building-queries/joins#crossjoin) | [crossJoinRaw](/12.0.0/query-builder/building-queries/joins#crossjoinraw) | [crossJoinSub](/12.0.0/query-builder/building-queries/joins#crossjoinsub) |                                                                       |

## join <a href="#join" id="join"></a>

| Name     | Type                                                                                                                                                    | Required | Default   | Description                                                                                                                                                                                                                                                               |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| table    | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) \| [JoinClause](/12.0.0/query-builder/building-queries/joins#joinclause) | `true`   | ​         | The name of the table or a [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) object from which the query is based.  Alternatively, a configured [`JoinClause`](/12.0.0/query-builder/building-queries/joins#joinclause) instance can be passed.      |
| first    | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) \| Function                                                              | `false`  |           | The first column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) to join the table on.  Alternatively, a function can be passed to configure complex join statements.                                                                           |
| operator | string                                                                                                                                                  | `false`  | `"="`     | The boolean operator for the join clause.                                                                                                                                                                                                                                 |
| second   | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions)                                                                          | `false`  |           | The second column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) to join the table on.                                                                                                                                                         |
| type     | string                                                                                                                                                  | `false`  | `"inner"` | The type of the join.  Passing this as an argument is discouraged for readability. Use the dedicated methods like [`leftJoin`](/12.0.0/query-builder/building-queries/joins#leftjoin) and [`rightJoin`](/12.0.0/query-builder/building-queries/joins#get) where possible. |
| where    | boolean                                                                                                                                                 | `false`  | `false`   | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use the dedicated [`joinWhere`](/12.0.0/query-builder/building-queries/joins#joinwhere) or a join closure where possible.                         |

Applies a join to the query. The simplest join is to a table based on two columns:

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .join( "posts", "users.id", "=", "posts.author_id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
```

{% endcode %}

When doing a simple join using `=` as the operator, you can omit it and pass just the column names:

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .join( "posts", "users.id", "posts.author_id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
```

{% endcode %}

\`\`[`Expressions`](/12.0.0/query-builder/building-queries/raw-expressions) are also supported as the `table` argument (though you may prefer the readability of the [`joinRaw`](/12.0.0/query-builder/building-queries/joins#joinraw) method):

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .join( query.raw( "posts (nolock)" ), "users.id", "=", "posts.author_id" );
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT *
FROM [users]
JOIN posts (nolock)
  ON [users].[id] = [posts].[author_id]
```

{% endcode %}

{% hint style="warning" %}
Using `raw` will most likely tie your code to a specific database, so think carefully before using the `raw` method if you want your project to be database agnostic.
{% endhint %}

When you need to specify more clauses to join, you can pass a function as the second argument:

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .join( "posts", function( j ) {
        j.on( "users.id", "=", "posts.author_id" );
        j.on( "users.prefix", "=", "posts.prefix" );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
  AND `users`.`prefix` = `posts`.`prefix`
```

{% endcode %}

You can specify [`where`](/12.0.0/query-builder/building-queries/wheres) clauses in your joins as well.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .join( "posts", function( j ) {
        j.on( "users.id", "=", "posts.author_id" );
        j.whereNotNull( "posts.published_date" );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
  AND `posts`.`published_date` IS NOT NULL
```

{% endcode %}

Conditions inside a join clause can be grouped using a function.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .join( "posts", function( j ) {
        j.on( function( j1 ) {
            j1.on( "users.id", "posts.author_id" )
                .orOn( "users.id", "posts.reviewer_id" );
        } );
        j.whereNotNull( "posts.published_date" );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON (
      `users`.`id` = `posts`.`author_id`
      OR `users`.`id` = `posts`.`reviewer_id`
  )
  AND `posts`.`published_date` IS NOT NULL
```

{% endcode %}

A preconfigured [`JoinClause`](/12.0.0/query-builder/building-queries/joins#joinclause) can also be passed to the join function. This allows you to extract shared pieces of code out to different functions.

{% code title="QueryBuilder" %}

```javascript
var j = query.newJoin( "contacts" )
    .on( "users.id", "posts.author_id" );

query.from( "users" ).join( j );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
```

{% endcode %}

## joinWhere <a href="#joinwhere" id="joinwhere"></a>

| Name     | Type                                                                                       | Required | Default   | Description                                                                                                                                                                                                                                                                                    |
| -------- | ------------------------------------------------------------------------------------------ | -------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| table    | string                                                                                     | `true`   | ​         | The raw SQL string to use as the table.                                                                                                                                                                                                                                                        |
| first    | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) \| Function | `false`  |           | The first column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) to join the table on.  Alternatively, a function can be passed to configure complex join statements.                                                                                                |
| operator | string                                                                                     | `false`  | `"="`     | The boolean operator for the join clause.                                                                                                                                                                                                                                                      |
| second   | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions)             | `false`  |           | The second column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) to join the table on.                                                                                                                                                                              |
| type     | string                                                                                     | `false`  | `"inner"` | The type of the join.  Passing this as an argument is discouraged for readability. Use the dedicated methods like [`leftJoin`](/12.0.0/query-builder/building-queries/joins#leftjoin) and [`rightJoin`](/12.0.0/query-builder/building-queries/joins#get) with a join function where possible. |

Adds a join to another table based on a `WHERE` clause instead of an `ON` clause. `WHERE` clauses introduce parameters and parameter bindings whereas `on` clauses join between columns and don't need parameter bindings.

For simple joins, this specifies a column on which to join the two tables:

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .joinWhere( "contacts", "contacts.balance", "<", 100 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `contacts`
  WHERE `contacts`.`balance` < ?
```

{% endcode %}

For complex joins, a function can be passed to `first`. This allows multiple `on` and `where` conditions to be applied to the join. See the documentation for [`join`](/12.0.0/query-builder/building-queries/joins#join) for more information.

## joinRaw <a href="#joinraw" id="joinraw"></a>

| Name     | Type                                                                                       | Required | Default   | Description                                                                                                                                                                                                                                                                                 |
| -------- | ------------------------------------------------------------------------------------------ | -------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| table    | string                                                                                     | `true`   | ​         | The raw SQL string to use as the table.                                                                                                                                                                                                                                                     |
| first    | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) \| Function | `false`  |           | The first column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) to join the table on.  Alternatively, a function can be passed to configure complex join statements.                                                                                             |
| operator | string                                                                                     | `false`  | `"="`     | The boolean operator for the join clause.                                                                                                                                                                                                                                                   |
| second   | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions)             | `false`  |           | The second column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) to join the table on.                                                                                                                                                                           |
| type     | string                                                                                     | `false`  | `"inner"` | The type of the join.  Passing this as an argument is discouraged for readability. Use the dedicated methods like [`leftJoinRaw`](/12.0.0/query-builder/building-queries/joins#leftjoinraw) and [`rightJoinRaw`](/12.0.0/query-builder/building-queries/joins#rightjoinraw) where possible. |
| where    | boolean                                                                                    | `false`  | `false`   | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use a closure to define the where clauses where possible.                                                                                                           |

Uses the raw SQL provided to as the table for the join clause. All the other functionality of `joinRaw` matches the [`join`](/12.0.0/query-builder/building-queries/joins#join) method. Additionally, there are [`leftJoinRaw`](/12.0.0/query-builder/building-queries/joins#leftjoinraw), [`rightJoinRaw`](/12.0.0/query-builder/building-queries/joins#rightjoinraw), and `crossJoinRaw` methods available.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .joinRaw( "posts (nolock)", "users.id", "posts.author_id" );
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT *
FROM [users]
JOIN posts (nolock)
  ON [users].[id] = [posts].[author_id]
```

{% endcode %}

{% hint style="warning" %}
Using `joinRaw` will most likely tie your code to a specific database, so think carefully before using the `joinRaw` method if you want your project to be database agnostic.
{% endhint %}

## joinSub <a href="#joinsub" id="joinsub"></a>

| Name     | Type                                                                                       | Required | Default   | Description                                                                                                                                                                                                                                                                                 |
| -------- | ------------------------------------------------------------------------------------------ | -------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| alias    | string                                                                                     | `true`   |           | The alias for the derived table.                                                                                                                                                                                                                                                            |
| input    | Function \| QueryBuilder                                                                   | `true`   | ​         | Either a `QueryBuilder` instance or a function to define the derived query.                                                                                                                                                                                                                 |
| first    | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) \| Function | `true`   |           | The first column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) to join the table on.  Alternatively, a function can be passed to configure complex join statements.                                                                                             |
| operator | string                                                                                     | `false`  | `"="`     | The boolean operator for the join clause.                                                                                                                                                                                                                                                   |
| second   | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions)             | `false`  |           | The second column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) to join the table on.                                                                                                                                                                           |
| type     | string                                                                                     | `false`  | `"inner"` | The type of the join.  Passing this as an argument is discouraged for readability. Use the dedicated methods like [`leftJoinSub`](/12.0.0/query-builder/building-queries/joins#leftjoinsub) and [`rightJoinSub`](/12.0.0/query-builder/building-queries/joins#rightjoinsub) where possible. |
| where    | boolean                                                                                    | `false`  | `false`   | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use a closure to define the where clauses where possible.                                                                                                           |

Adds a join to a derived table. All the functionality of the [`join`](/12.0.0/query-builder/building-queries/joins#join) method applies to constrain the query. The derived table can be defined using a `QueryBuilder` instance:

{% code title="QueryBuilder" %}

```javascript
var sub = query.newQuery()
    .select( "id" )
    .from( "contacts" )
    .whereNotIn( "id", [ 1, 2, 3 ] );

query.from( "users as u" )
    .joinSub( "c", sub, "u.id", "=", "c.id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users` AS `u`
JOIN (
  SELECT `id`
  FROM `contacts`
  WHERE `id` NOT IN (?, ?, ?)
) AS `c`
  ON `u`.`id` = `c`.`id`
```

{% endcode %}

Alternatively, a function may be used to define the derived table:

{% code title="QueryBuilder" %}

```javascript
query.from( "users as u" )
    .joinSub( "c", function ( q ) {
        q.select( "id" )
            .from( "contacts" )
            .whereNotIn( "id", [ 1, 2, 3 ] );
    }, "u.id", "=", "c.id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users` AS `u`
JOIN (
  SELECT `id`
  FROM `contacts`
  WHERE `id` NOT IN (?, ?, ?)
) AS `c`
  ON `u`.`id` = `c`.`id`
```

{% endcode %}

Complex join conditions are also possible by passing a function as the third parameter:

{% code title="QueryBuilder" %}

```javascript
query.from( "users as u" )
    .joinSub( "c", function ( q ) {
        q.select( "id" )
            .from( "contacts" )
            .whereNotIn( "id", [ 1, 2, 3 ] );
    }, function( j ) {
        j.on( "u.id", "c.id" );
        j.on( "u.type", "c.type" );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users` AS `u`
JOIN (
  SELECT `id`
  FROM `contacts`
  WHERE `id` NOT IN (?, ?, ?)
) AS `c`
  ON `u`.`id` = `c`.`id`
  AND `u`.`type` = `c`.`type`
```

{% endcode %}

## leftJoin <a href="#leftjoin" id="leftjoin"></a>

| Name | Type | Required | Default | Description |
| ---- | ---- | -------- | ------- | ----------- |

| table | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) \| [JoinClause](/12.0.0/query-builder/building-queries/joins#joinclause) | `true` | ​ | <p>The name of the table or a <a href="/pages/-LqPwKuMTnx51m1fvv9o"><code>Expression</code></a> object from which the query is based. Alternatively, a configured <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance can be passed.</p><p>(Note: a <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance may have a different join type than a <code>left</code> join. The <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance's join type will be used.)</p> |
| ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

| first | string \| Expression \| Function | `false` |   | The first column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) to join the table on. Alternatively, a function can be passed to configure complex join statements. |
| ----- | -------------------------------- | ------- | - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

| operator | string | `false` | `"="` | The boolean operator for the join clause. |
| -------- | ------ | ------- | ----- | ----------------------------------------- |

| second | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) | `false` |   | The second column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) to join the table on. |
| ------ | ------------------------------------------------------------------------------ | ------- | - | ----------------------------------------------------------------------------------------------------------------- |

| where | boolean | `false` | `false` | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use a closure to define the where clauses where possible. |
| ----- | ------- | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

{% code title="QueryBuilder" %}

```javascript
query.from( "posts" )
    .leftJoin( "users", "users.id", "posts.author_id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `posts`
LEFT JOIN `users`
  ON `users`.`id` = `posts`.`author_id`
```

{% endcode %}

## leftJoinRaw <a href="#leftjoinraw" id="leftjoinraw"></a>

| Name     | Type                                                                                       | Required | Default | Description                                                                                                                                                                                     |
| -------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| table    | string                                                                                     | `true`   | ​       | The raw SQL string to use as the table.                                                                                                                                                         |
| first    | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) \| Function | `false`  |         | The first column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) to join the table on.  Alternatively, a function can be passed to configure complex join statements. |
| operator | string                                                                                     | `false`  | `"="`   | The boolean operator for the join clause.                                                                                                                                                       |
| second   | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The second column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) to join the table on.                                                                               |
| where    | boolean                                                                                    | `false`  | `false` | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use a closure to define the where clauses where possible.               |

Uses the raw SQL provided to as the table for the left join clause. All the other functionality of `leftJoinRaw` matches the [`join`](/12.0.0/query-builder/building-queries/joins#join) method.

{% code title="QueryBuilder" %}

```javascript
query.from( "posts" )
    .leftJoinRaw( "users (nolock)", "users.id", "posts.author_id" );
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT *
FROM [posts]
LEFT JOIN users (nolock)
  ON [users].[id] = [posts].[author_id]
```

{% endcode %}

{% hint style="warning" %}
Using `leftJoinRaw` will most likely tie your code to a specific database, so think carefully before using the `leftJoinRaw` method if you want your project to be database agnostic.
{% endhint %}

## leftJoinSub <a href="#leftjoinsub" id="leftjoinsub"></a>

| Name     | Type                                                                                       | Required | Default | Description                                                                                                                                                                                     |
| -------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| alias    | string                                                                                     | `true`   |         | The alias for the derived table.                                                                                                                                                                |
| input    | Function \| QueryBuilder                                                                   | `true`   | ​       | Either a `QueryBuilder` instance or a function to define the derived query.                                                                                                                     |
| first    | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) \| Function | `true`   |         | The first column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) to join the table on.  Alternatively, a function can be passed to configure complex join statements. |
| operator | string                                                                                     | `false`  | `"="`   | The boolean operator for the join clause.                                                                                                                                                       |
| second   | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The second column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) to join the table on.                                                                               |
| where    | boolean                                                                                    | `false`  | `false` | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use a closure to define the where clauses where possible.               |

Adds a left join to a derived table. All the functionality of the [`joinSub`](/12.0.0/query-builder/building-queries/joins#joinsub) method applies to define and constrain the query.

{% code title="QueryBuilder" %}

```javascript
var sub = query.newQuery()
    .select( "id" )
    .from( "contacts" )
    .whereNotIn( "id", [ 1, 2, 3 ] );

query.from( "users as u" )
    .leftJoinSub( "c", sub, "u.id", "=", "c.id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users` AS `u`
LEFT JOIN (
  SELECT `id`
  FROM `contacts`
  WHERE `id` NOT IN (?, ?, ?)
) AS `c`
  ON `u`.`id` = `c`.`id`
```

{% endcode %}

## rightJoin <a href="#get" id="get"></a>

| Name | Type | Required | Default | Description |
| ---- | ---- | -------- | ------- | ----------- |

| table | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) \| [JoinClause](/12.0.0/query-builder/building-queries/joins#joinclause) | `true` | ​ | <p>The name of the table or a <a href="/pages/-LqPwKuMTnx51m1fvv9o"><code>Expression</code></a> object from which the query is based. Alternatively, a configured <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance can be passed.</p><p>(Note: a <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance may have a different join type than a <code>right</code> join. The <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance's join type will be used.)</p> |
| ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

| first | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) \| Function | `false` |   | The first column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) to join the table on. Alternatively, a function can be passed to configure complex join statements. |
| ----- | ------------------------------------------------------------------------------------------ | ------- | - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

| operator | string | `false` | `"="` | The boolean operator for the join clause. |
| -------- | ------ | ------- | ----- | ----------------------------------------- |

| second | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) | `false` |   | The second column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) to join the table on. |
| ------ | ------------------------------------------------------------------------------ | ------- | - | ----------------------------------------------------------------------------------------------------------------- |

| where | boolean | `false` | `false` | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use a closure to define the where clauses where possible. |
| ----- | ------- | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .rightJoin( "posts", "users.id", "posts.author_id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
RIGHT JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
```

{% endcode %}

## rightJoinRaw <a href="#rightjoinraw" id="rightjoinraw"></a>

| Name     | Type                                                                                       | Required | Default | Description                                                                                                                                                                                     |
| -------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| table    | string                                                                                     | `true`   | ​       | The raw SQL string to use as the table.                                                                                                                                                         |
| first    | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) \| Function | `false`  |         | The first column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) to join the table on.  Alternatively, a function can be passed to configure complex join statements. |
| operator | string                                                                                     | `false`  | `"="`   | The boolean operator for the join clause.                                                                                                                                                       |
| second   | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The second column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) to join the table on.                                                                               |
| where    | boolean                                                                                    | `false`  | `false` | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use a closure to define the where clauses where possible.               |

Uses the raw SQL provided to as the table for the right join clause. All the other functionality of `rightJoinRaw` matches the [`join`](/12.0.0/query-builder/building-queries/joins#join) method.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .rightJoinRaw( "posts (nolock)", "users.id", "posts.author_id" );
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT *
FROM [users]
LEFT JOIN posts (nolock)
  ON [users].[id] = [posts].[author_id]
```

{% endcode %}

{% hint style="warning" %}
Using `rightJoinRaw` will most likely tie your code to a specific database, so think carefully before using the `rightJoinRaw` method if you want your project to be database agnostic.
{% endhint %}

## rightJoinSub <a href="#rightjoinsub" id="rightjoinsub"></a>

| Name     | Type                                                                                       | Required | Default | Description                                                                                                                                                                                     |
| -------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| alias    | string                                                                                     | `true`   |         | The alias for the derived table.                                                                                                                                                                |
| input    | Function \| QueryBuilder                                                                   | `true`   | ​       | Either a `QueryBuilder` instance or a function to define the derived query.                                                                                                                     |
| first    | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) \| Function | `true`   |         | The first column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) to join the table on.  Alternatively, a function can be passed to configure complex join statements. |
| operator | string                                                                                     | `false`  | `"="`   | The boolean operator for the join clause.                                                                                                                                                       |
| second   | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The second column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) to join the table on.                                                                               |
| where    | boolean                                                                                    | `false`  | `false` | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use a closure to define the where clauses where possible.               |

Adds a right join to a derived table. All the functionality of the [`joinSub`](/12.0.0/query-builder/building-queries/joins#joinsub) method applies to define and constrain the query.

{% code title="QueryBuilder" %}

```javascript
var sub = query.newQuery()
    .select( "id" )
    .from( "contacts" )
    .whereNotIn( "id", [ 1, 2, 3 ] );

query.from( "users as u" )
    .rightJoinSub( "c", sub, "u.id", "=", "c.id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users` AS `u`
RIGHT JOIN (
  SELECT `id`
  FROM `contacts`
  WHERE `id` NOT IN (?, ?, ?)
) AS `c`
  ON `u`.`id` = `c`.`id`
```

{% endcode %}

## crossJoin <a href="#crossjoin" id="crossjoin"></a>

| Name | Type | Required | Default | Description |
| ---- | ---- | -------- | ------- | ----------- |

| table | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) \| [JoinClause](/12.0.0/query-builder/building-queries/joins#joinclause) | `true` | ​ | <p>The name of the table or a <a href="/pages/-LqPwKuMTnx51m1fvv9o"><code>Expression</code></a> object from which the query is based. Alternatively, a configured <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance can be passed.</p><p>(Note: a <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance may have a different join type than a <code>cross</code> join. The <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance's join type will be used.)</p> |
| ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).crossJoin( "posts" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
CROSS JOIN `posts`
```

{% endcode %}

## crossJoinRaw <a href="#crossjoinraw" id="crossjoinraw"></a>

| Name  | Type   | Required | Default | Description                             |
| ----- | ------ | -------- | ------- | --------------------------------------- |
| table | string | `true`   | ​       | The raw SQL string to use as the table. |

Uses the raw SQL provided to as the table for the cross join clause. Cross joins cannot be further constrained with `on` or `where` clauses.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).crossJoinRaw( "posts (nolock)" );
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT *
FROM [users]
CROSS JOIN posts (nolock)
```

{% endcode %}

{% hint style="warning" %}
Using `crossJoinRaw` will most likely tie your code to a specific database, so think carefully before using the `crossJoinRaw` method if you want your project to be database agnostic.
{% endhint %}

## crossJoinSub <a href="#crossjoinsub" id="crossjoinsub"></a>

| Name  | Type                     | Required | Default | Description                                                                 |
| ----- | ------------------------ | -------- | ------- | --------------------------------------------------------------------------- |
| alias | string                   | `true`   |         | The alias for the derived table.                                            |
| input | Function \| QueryBuilder | `true`   | ​       | Either a `QueryBuilder` instance or a function to define the derived query. |

Adds a cross join to a derived table. The derived table can be defined using a `QueryBuilder` instance or a function just as with [`joinSub`](/12.0.0/query-builder/building-queries/joins#joinsub). Cross joins cannot be constrained, however.

{% code title="QueryBuilder" %}

```javascript
var sub = query.newQuery()
    .select( "id" )
    .from( "contacts" )
    .whereNotIn( "id", [ 1, 2, 3 ] );

query.from( "users as u" ).crossJoinSub( "c", sub );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users` AS `u`
CROSS JOIN (
  SELECT `id`
  FROM `contacts`
  WHERE `id` NOT IN (?, ?, ?)
)
```

{% endcode %}

## crossApply <a href="#crossapply" id="crossapply"></a>

| Name     | Type                         | Required | Default | Description                                                                                   |
| -------- | ---------------------------- | -------- | ------- | --------------------------------------------------------------------------------------------- |
| name     | string                       | `true`   |         | The name for the cross apply table                                                            |
| tableDef | `function` \| `QueryBuilder` | `true`   |         | A QueryBuilder instance or a function that accepts a new query builder instance to configure. |

Adds a cross apply join using a derived table. The derived table can be defined using a `QueryBuilder` instance or a function just as with [`joinSub`](/12.0.0/query-builder/building-queries/joins#joinsub).

{% code title="QueryBuilder" %}

```javascript
qb.from( "users as u" )
    .select( [ "u.ID", "childCount.c" ] )
    .crossApply( "childCount", function( qb ) {
        qb.selectRaw( "count(*) c" )
            .from( "children" )
            .whereColumn( "children.parentID", "=", "users.ID" )
            .where( "children.someCol", "=", 0 );
    } )
    .where( "childCount.c", ">", 1 )
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT
    [u].[ID],
    [childCount].[c]
FROM [users] AS [u]
CROSS APPLY (
    SELECT count(*) c
    FROM [children]
    WHERE [children].[parentID] = [users].[ID]
    AND [children].[someCol] = ?
) AS [childCount]
WHERE [childCount].[c] > ?
```

{% endcode %}

## outerApply <a href="#outerapply" id="outerapply"></a>

| Name     | Type                         | Required | Default | Description                                                                                   |
| -------- | ---------------------------- | -------- | ------- | --------------------------------------------------------------------------------------------- |
| name     | string                       | `true`   |         | The name for the cross apply table                                                            |
| tableDef | `function` \| `QueryBuilder` | `true`   |         | A QueryBuilder instance or a function that accepts a new query builder instance to configure. |

Adds a outer apply join using a derived table. The derived table can be defined using a `QueryBuilder` instance or a function just as with [`joinSub`](/12.0.0/query-builder/building-queries/joins#joinsub).

{% code title="QueryBuilder" %}

```javascript
qb.from( "users as u" )
    .select( [ "u.ID", "childCount.c" ] )
    .outerApply( "childCount", function( qb ) {
        qb.selectRaw( "count(*) c" )
            .from( "children" )
            .whereColumn( "children.parentID", "=", "users.ID" )
            .where( "children.someCol", "=", 0 );
    } )
    .where( "childCount.c", ">", 1 )
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT
    [u].[ID],
    [childCount].[c]
FROM [users] AS [u]
OUTER APPLY (
    SELECT count(*) c
    FROM [children]
    WHERE [children].[parentID] = [users].[ID]
    AND [children].[someCol] = ?
) AS [childCount]
WHERE [childCount].[c] > ?
```

{% endcode %}

## newJoin <a href="#newjoin" id="newjoin"></a>

| Name  | Type                                                                           | Required | Default   | Description                                                                                                                             |
| ----- | ------------------------------------------------------------------------------ | -------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| table | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) | `true`   | ​         | The name of the table or a [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) object from which the query is based. |
| type  | string                                                                         | `false`  | `"inner"` | The type of the join.  Valid types are `inner`, `left`, `right`, or `cross`.                                                            |

Creates a new [`JoinClause`](/12.0.0/query-builder/building-queries/joins#joinclause). A [`JoinClause`](/12.0.0/query-builder/building-queries/joins#joinclause) is a specialized version of a `QueryBuilder`. You may call `on` or `orOn` to constrain the [`JoinClause`](/12.0.0/query-builder/building-queries/joins#joinclause). You may also call any [`where`](/12.0.0/query-builder/building-queries/wheres) methods.

Creating a [`JoinClause`](/12.0.0/query-builder/building-queries/joins#joinclause) directly is useful when you need to share a join between different queries. You can create and configure the [`JoinClause`](/12.0.0/query-builder/building-queries/joins#joinclause) in a function and pass it to queries as needed.

{% code title="QueryBuilder" %}

```javascript
var j = query.newJoin( "contacts" )
    .on( "users.id", "posts.author_id" );

query.from( "users" ).join( j );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
```

{% endcode %}

{% hint style="warning" %}
Although a [`JoinClause`](/12.0.0/query-builder/building-queries/joins#joinclause) can be passed to [`join`](/12.0.0/query-builder/building-queries/joins#join), [`leftJoin`](/12.0.0/query-builder/building-queries/joins#leftjoin), [`rightJoin`](/12.0.0/query-builder/building-queries/joins#get), and `crossJoin`, the type of the [`JoinClause`](/12.0.0/query-builder/building-queries/joins#joinclause) will override the type of the function.
{% endhint %}

{% code title="QueryBuilder" %}

```javascript
// This is still an inner join because
// the JoinClause is an inner join
var j = query.newJoin( "contacts", "inner" )
    .on( "users.id", "posts.author_id" );

query.from( "users" ).leftJoin( j );
```

{% endcode %}

{% code title="MySQL" %}

```sql
-- This is still an inner join because
-- the JoinClause is an inner join
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
```

{% endcode %}

## JoinClause

A `JoinClause` is a specialized version of a `QueryBuilder`. You may call `on` or `orOn` to constrain the `JoinClause`. You may also call any [`where`](/12.0.0/query-builder/building-queries/wheres) methods.

### on

| Name       | Type                                                                                       | Required | Default | Description                                                                                                                                                                               |
| ---------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| first      | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) \| Function | `false`  |         | The first column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions)of the condition.  Alternatively, a function can be passed to nest conditions with parenthesis. |
| operator   | string                                                                                     | `false`  | `"="`   | The boolean operator for the condition.                                                                                                                                                   |
| second     | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The second column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) of the condition.                                                                             |
| combinator | string                                                                                     | `false`  | `"and"` | The boolean combinator for the clause (e.g. "and" or "or").                                                                                                                               |

Applies a join condition to the `JoinClause`. An alias for `whereColumn`.

{% code title="QueryBuilder" %}

```javascript
var j = query.newJoin( "contacts" )
    .on( "users.id", "posts.author_id" );

query.from( "users" ).join( j );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
```

{% endcode %}

### orOn

| Name     | Type                                                                                       | Required | Default | Description                                                                                                                                                                               |
| -------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| first    | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) \| Function | `false`  |         | The first column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions)of the condition.  Alternatively, a function can be passed to nest conditions with parenthesis. |
| operator | string                                                                                     | `false`  | `"="`   | The boolean operator for the condition.                                                                                                                                                   |
| second   | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The second column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) of the condition.                                                                             |

Applies a join condition to the `JoinClause` using an `or` combinator. An alias for `orWhereColumn`.

{% code title="QueryBuilder" %}

```javascript
var j = query.newJoin( "contacts" )
    .on( "users.id", "posts.author_id" )
    .orOn( "users.id", "posts.reviewer_id" );

query.from( "users" ).join( j );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
  OR `users`.`id` = `posts`.`reviewer_id`
```

{% endcode %}

## Preventing Duplicate Joins

You can optionally configure qb to ignore duplicate joins.  With this setting turned on each `JoinClause` is inspected and checked if it matches any existing `JoinClause` instances on the query.  This is useful if you have a table shared between optional constraints and want to ensure it is only added once.

You can opt-in to this behavior by setting `preventDuplicateJoins = true` in your `moduleSettings` in `config/ColdBox.cfc`.

```javascript
moduleSettings = {
    "qb": {
         "preventDuplicateJoins": true  
    }
};
```


# Wheres

| Table of Contents                                                          |                                                                                  |                                                                          |
| -------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| [where](/12.0.0/query-builder/building-queries/wheres#where)               | [andWhere](/12.0.0/query-builder/building-queries/wheres#andwhere)               | [orWhere](/12.0.0/query-builder/building-queries/wheres#orwhere)         |
| [whereBetween](/12.0.0/query-builder/building-queries/wheres#wherebetween) | [whereNotBetween](/12.0.0/query-builder/building-queries/wheres#wherenotbetween) | [whereColumn](/12.0.0/query-builder/building-queries/wheres#wherecolumn) |
| [whereExists](/12.0.0/query-builder/building-queries/wheres#whereexists)   | [whereNotExists](/12.0.0/query-builder/building-queries/wheres#wherenotexists)   | [whereLike](/12.0.0/query-builder/building-queries/wheres#wherelike)     |
| [whereIn](/12.0.0/query-builder/building-queries/wheres#wherein)           | [whereNotIn](/12.0.0/query-builder/building-queries/wheres#wherenotin)           | [whereRaw](/12.0.0/query-builder/building-queries/wheres#whereraw)       |
| [whereNull](/12.0.0/query-builder/building-queries/wheres#wherenull)       | [whereNotNull](/12.0.0/query-builder/building-queries/wheres#wherenotnull)       |                                                                          |

## Where Methods

### where

| Name       | Type                                                                                       | Required | Default | Description                                                                                                                                                                                                                                                                                                 |
| ---------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) \| Function | `true`   |         | The name of the column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) with which to constrain the query. A function can be passed to begin a nested where statement.                                                                                                             |
| operator   | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The operator to use for the constraint (i.e. "=", "<", ">=", etc.). A value can be passed as the `operator` and the `value` left null as a shortcut for equals (e.g. where( "column", 1 ) == where( "column", "=", 1 ) ).                                                                                   |
| value      | any                                                                                        | `false`  |         | The value with which to constrain the column.  An [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) can be passed as well.  If a QueryBuilder or Function is passed, it will be used as a subselect expression.                                                                        |
| combinator | string                                                                                     | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the [`andWhere`](/12.0.0/query-builder/building-queries/wheres#andwhere) and [`orWhere`](/12.0.0/query-builder/building-queries/wheres#orwhere) methods instead. |

Adds a where clause to a query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "active", "=", 1 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `active` = ?
```

{% endcode %}

{% hint style="info" %}
Using the `where` method will parameterize the `value` passed.  If you want to constrain a column to another column, use the [`whereColumn`](/12.0.0/query-builder/building-queries/wheres#wherecolumn) method.
{% endhint %}

You can also pass an [Expression](/12.0.0/query-builder/building-queries/raw-expressions) as the value.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "last_logged_in", ">", query.raw( "NOW()" ) );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `last_logged_in` > NOW()
```

{% endcode %}

Any of the following operators can be used in a where clause.

| Valid Operators |                |             |
| --------------- | -------------- | ----------- |
| =               | <              | >           |
| <=              | >=             | <>          |
| !=              | like           | like binary |
| not like        | between        | ilike       |
| &               | \|             | ^           |
| <<              | >>             | rlike       |
| regexp          | not regexp     | \~          |
| \~\*            | !\~            | !\~\*       |
| similar to      | not similar to |             |

When using the `"="` constraint, you can use a shortcut and define the value as the second argument.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "active", 1 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `active` = ?
```

{% endcode %}

{% hint style="info" %}
You may also use [dynamic where{Column}](/12.0.0/query-builder/building-queries/wheres#dynamic-where-methods) statements to simplify this further.
{% endhint %}

To group where statements together, pass a function to the where clause as the only parameter.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( function( q ) {
        q.where( "active", 1 )
            .where( "last_logged_in", ">", dateAdd( "ww", -1, now() ) )
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE (
    `active` = ?
    AND
    `last_logged_in` > ?
)
```

{% endcode %}

{% hint style="info" %}
This grouping can be nested as many levels as you require.
{% endhint %}

A Function or QueryBuilder can be used as a subselect expression when passed to `value`.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "email", "foo" )
    .orWhere( "id", "=", function( q ) {
        q.select( q.raw( "MAX(id)" ) )
            .from( "users" )
            .where( "email", "bar" );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `email` = ?
  OR `id` = (
    SELECT MAX(id)
    FROM `users`
    WHERE `email` = ?
  )
```

{% endcode %}

### andWhere

| Name     | Type                                                                                       | Required | Default | Description                                                                                                                                                                                                                          |
| -------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| column   | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) \| Function | `true`   |         | The name of the column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) with which to constrain the query. A function can be passed to begin a nested where statement.                                      |
| operator | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The operator to use for the constraint (i.e. "=", "<", ">=", etc.). A value can be passed as the `operator` and the `value` left null as a shortcut for equals (e.g. where( "column", 1 ) == where( "column", "=", 1 ) ).            |
| value    | any                                                                                        | `false`  |         | The value with which to constrain the column.  An [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) can be passed as well.  If a QueryBuilder or Function is passed, it will be used as a subselect expression. |

This method is simply an alias for [`where`](/12.0.0/query-builder/building-queries/wheres#where) with the combinator set to `"and"`.

### orWhere

| Name     | Type                                                                                       | Required | Default | Description                                                                                                                                                                                                                          |
| -------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| column   | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) \| Function | `true`   |         | The name of the column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) with which to constrain the query. A function can be passed to begin a nested where statement.                                      |
| operator | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The operator to use for the constraint (i.e. "=", "<", ">=", etc.). A value can be passed as the `operator` and the `value` left null as a shortcut for equals (e.g. where( "column", 1 ) == where( "column", "=", 1 ) ).            |
| value    | any                                                                                        | `false`  |         | The value with which to constrain the column.  An [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) can be passed as well.  If a QueryBuilder or Function is passed, it will be used as a subselect expression. |

This method is simply an alias for [`where`](/12.0.0/query-builder/building-queries/wheres#where) with the combinator set to `"or"`.

### whereBetween

| Name       | Type                            | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | ------------------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| Expression            | `true`   |         | The name of the column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                                                                    |
| start      | any \| Function \| QueryBuilder | `true`   |         | The beginning value of the BETWEEN statement.  If a function or QueryBuilder is passed it is used as a subselect expression.                                                                                                                                           |
| end        | any \| Function \| QueryBuilder | `true`   |         | The end value of the BETWEEN statement. If a function or QueryBuilder is passed it is used as a subselect expression.                                                                                                                                                  |
| combinator | string                          | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods](/12.0.0/query-builder/building-queries/wheres#andwhere-and-orwhere) instead. |
| negate     | boolean                         | `false`  | `false` | False for BETWEEN, True for NOT BETWEEN.                                                                                                                                                                                                                               |

Adds a where between clause to the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereBetween( "id", 1, 2 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `id` BETWEEN ? AND ?
```

{% endcode %}

If a function or QueryBuilder is passed it is used as a subselect expression.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereBetween(
        "id",
        function( q ) {
            q.select( q.raw( "MIN(id)" ) )
                .from( "users" )
                .where( "email", "bar" );
        },
        builder.newQuery()
            .select( builder.raw( "MAX(id)" ) )
            .from( "users" )
            .where( "email", "bar" )
    );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `id` BETWEEN (
    SELECT MIN(id)
    FROM `users`
    WHERE `email` = ?
)
AND (
    SELECT MAX(id)
    FROM `users`
    WHERE `email` = ?
)
```

{% endcode %}

### whereNotBetween

| Name       | Type                            | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | ------------------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| Expression            | `true`   |         | The name of the column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                                                                    |
| start      | any \| Function \| QueryBuilder | `true`   |         | The beginning value of the BETWEEN statement.  If a function or QueryBuilder is passed it is used as a subselect expression.                                                                                                                                           |
| end        | any \| Function \| QueryBuilder | `true`   |         | The end value of the BETWEEN statement. If a function or QueryBuilder is passed it is used as a subselect expression.                                                                                                                                                  |
| combinator | string                          | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods](/12.0.0/query-builder/building-queries/wheres#andwhere-and-orwhere) instead. |

Adds a where not in clause to the query.  This behaves identically to the [`whereBetween`](/12.0.0/query-builder/building-queries/wheres#wherebetween) method with the `negate`flag set to `true`.  See the documentation for [`whereBetween`](/12.0.0/query-builder/building-queries/wheres#wherebetween) for usage and examples.

### whereColumn

| Name       | Type                                                                           | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | ------------------------------------------------------------------------------ | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| first      | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) | `true`   |         | The name of the first column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                                                              |
| operator   | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) | `true`   |         | The operator to use for the constraint (i.e. "=", "<", ">=", etc.). A value can be passed as the `operator` and the `value` left null as a shortcut for equals (e.g. where( "column", 1 ) == where( "column", "=", 1 ) ).                                              |
| second     | string \| Expression                                                           | `false`  |         | The name of the second column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                                                             |
| combinator | string                                                                         | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods](/12.0.0/query-builder/building-queries/wheres#andwhere-and-orwhere) instead. |

Adds a where clause to a query that compares two columns.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereColumn( "first_name", "=", "last_name" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `first_name` = `last_name`
```

{% endcode %}

Just as with `where`, when using `"="` as the operator you can use a shorthand passing the second column in as the operator and leaving the second column `null`.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereColumn( "first_name", "last_name" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `first_name` = `last_name`
```

{% endcode %}

`Expressions` can be passed in place of either column.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereColumn( "first_name", query.raw( "LOWER(first_name)" ) );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `first_name` = LOWER(first_name)
```

{% endcode %}

### whereExists

| Name       | Type                     | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | ------------------------ | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| query      | Function \| QueryBuilder | `true`   |         | A function or QueryBuilder instance to be used as the exists subquery.                                                                                                                                                                                                 |
| combinator | string                   | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/12.0.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead. |
| negate     | boolean                  | `false`  | `false` | False for EXISTS, True for NOT EXISTS.                                                                                                                                                                                                                                 |

Adds a where exists clause to the query.

It can be configured with a function.

{% code title="QueryBuilder" %}

```javascript
query.from( "orders" )
    .whereExists( function( q ) {
        q.select( q.raw( 1 ) )
            .from( "products" )
            .whereColumn( "products.id", "orders.id" );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `orders`
WHERE EXISTS (
    SELECT 1
    FROM `products`
    WHERE `products`.`id` = `orders`.`id`
)
```

{% endcode %}

It can also be configured with a QueryBuilder instance.

{% code title="QueryBuilder" %}

```javascript
var existsQuery = query.newQuery()
    .select( q.raw( 1 ) )
    .from( "products" )
    .whereColumn( "products.id", "orders.id" );

query.from( "orders" )
    .whereExists( existsQuery );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `orders`
WHERE EXISTS (
    SELECT 1
    FROM `products`
    WHERE `products`.`id` = `orders`.`id`
)
```

{% endcode %}

### whereNotExists

| Name       | Type                     | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | ------------------------ | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| query      | Function \| QueryBuilder | `true`   |         | A function or QueryBuilder instance to be used as the not exists subquery.                                                                                                                                                                                             |
| combinator | string                   | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/12.0.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead. |

Adds a where not in clause to the query.  This behaves identically to the [`whereExists`](/12.0.0/query-builder/building-queries/wheres#whereexists) method with the `negate`flag set to `true`.  See the documentation for [`whereExists`](/12.0.0/query-builder/building-queries/wheres#whereexists) for usage and examples.

### whereLike

| Name       | Type                                                                           | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | ------------------------------------------------------------------------------ | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) | `true`   |         | The name of the column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                                                                    |
| value      | any                                                                            | `false`  |         | The value with which to constrain the column.  An [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) can be passed as well.  If a QueryBuilder or Function is passed, it will be used as a subselect expression.                                   |
| combinator | string                                                                         | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/12.0.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead. |

A shortcut for calling [`where`](/12.0.0/query-builder/building-queries/wheres#where) with `"like"` set as the operator.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereLike( "username", "J%" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `username` LIKE ?
```

{% endcode %}

### whereNotLike

| Name       | Type                                                                           | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | ------------------------------------------------------------------------------ | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) | `true`   |         | The name of the column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                                                                    |
| value      | any                                                                            | `false`  |         | The value with which to constrain the column.  An [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) can be passed as well.  If a QueryBuilder or Function is passed, it will be used as a subselect expression.                                   |
| combinator | string                                                                         | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/12.0.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead. |

A shortcut for calling [`where`](/12.0.0/query-builder/building-queries/wheres#where) with `"not like"` set as the operator.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereNotLike( "username", "J%" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `username` NOT LIKE ?
```

{% endcode %}

### whereIn

| Name       | Type                                                                                                                | Required | Default | Description                                                                                                                                                                                                                                                                                                 |
| ---------- | ------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| Expression                                                                                                | `true`   |         | The name of the column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                                                                                                         |
| values     | string \| array \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) \| Function \| QueryBuilder | `true`   |         | A single value, list of values, or array of values to constrain a column with.  [`Expressions`](/12.0.0/query-builder/building-queries/raw-expressions) may be used in any place a value is used.  Alternatively, a function or QueryBuilder instance can be passed in to be used as a subquery expression. |
| combinator | string                                                                                                              | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/12.0.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead.                                      |
| negate     | boolean                                                                                                             | `false`  | `false` | False for IN, True for NOT IN.                                                                                                                                                                                                                                                                              |

Adds a where in clause to the query.

The values passed to `whereIn` can be a single value, a list of values, or an array of values.

{% code title="QueryBuilder" %}

```javascript
query.from( "orders" )
    .whereIn( "id", [ 1, 4, 66 ] );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `orders`
WHERE `id` IN (?, ?, ?)
```

{% endcode %}

{% hint style="warning" %}
Some database grammars have a hard limit on the number of parameters passed to a SQL statement.  Keep this in mind while writing your queries.
{% endhint %}

If a list of values is passed in, it is converted to an array of values using a single comma (`","`) delimiter.

{% code title="QueryBuilder" %}

```javascript
query.from( "orders" )
    .whereIn( "id", "1,4,66" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `orders`
WHERE `id` IN (?, ?, ?)
```

{% endcode %}

Any value in the list or array can also be passed using a [custom parameter type](/12.0.0/query-builder/building-queries/parameters-and-bindings#custom-parameter-types) to have more control over the parameter settings.

{% code title="QueryBuilder" %}

```javascript
query.from( "orders" )
    .whereIn( "id", [ 1, 4, { value = "66", cfsqltype = "CF_SQL_VARCHAR" } ] );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `orders`
WHERE `id` IN (?, ?, ?)
```

{% endcode %}

`Expressions` can be freely mixed in with other values.

{% code title="QueryBuilder" %}

```javascript
query.from( "orders" )
    .whereIn( "id", [ query.raw( "MAX(id)" ), 4, 66 ] );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `orders`
WHERE `id` IN (MAX(id), ?, ?)
```

{% endcode %}

A function or QueryBuilder instance can be passed to be used as a subquery expression instead of a list of values.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereIn( "id", function( q ) {
        q.select( "id" )
            .from( "users" )
            .where( "age", ">", 25 );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE IN (
    SELECT `id`
    FROM `users`
    WHERE `age` > ?
)
```

{% endcode %}

{% hint style="warning" %}
You may find a `whereExists` method performs better for you than a `whereIn` with a subquery.
{% endhint %}

### whereNotIn

| Name       | Type                                                                                                                | Required | Default | Description                                                                                                                                                                                                                                                                                                 |
| ---------- | ------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| Expression                                                                                                | `true`   |         | The name of the column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                                                                                                         |
| values     | string \| array \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) \| Function \| QueryBuilder | `true`   |         | A single value, list of values, or array of values to constrain a column with.  [`Expressions`](/12.0.0/query-builder/building-queries/raw-expressions) may be used in any place a value is used.  Alternatively, a function or QueryBuilder instance can be passed in to be used as a subquery expression. |
| combinator | string                                                                                                              | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/12.0.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead.                                      |

Adds a where not in clause to the query.  This behaves identically to the `whereIn` method with the `negate`flag set to `true`.  See the documentation for [`whereIn`](/12.0.0/query-builder/building-queries/wheres#wherein) for usage and examples.

### whereRaw

| Name          | Type   | Required | Default | Description                                                                                                                                                                                                                                                            |
| ------------- | ------ | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| sql           | string | `true`   |         | The raw SQL to add to the query.                                                                                                                                                                                                                                       |
| whereBindings | array  | `false`  | `[]`    | Any bindings needed for the raw SQL.  Bindings can be simple values or [custom parameters](/12.0.0/query-builder/building-queries/parameters-and-bindings#custom-parameter-types).                                                                                     |
| combinator    | string | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/12.0.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead. |

Shorthand to add a raw SQL statement to the where clauses.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereRaw(
        "id = ? OR email = ? OR is_admin = 1",
        [ 1, "foo" ]
    );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE id = ? OR email = ? OR is_admin = 1
```

{% endcode %}

### whereNull

| Name       | Type                 | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | -------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| Expression | `true`   |         | The name of the column to check if it is NULL.  Can also pass an [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions).                                                                                                                               |
| combinator | string               | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/12.0.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead. |
| negate     | boolean              | `false`  | `false` | False for NULL, True for NOT NULL.                                                                                                                                                                                                                                     |

Adds a where null clause to the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereNull( "id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `id` IS NULL
```

{% endcode %}

### whereNotNull

| Name       | Type                 | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | -------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| Expression | `true`   |         | The name of the column to check if it is NULL.  Can also pass an [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions).                                                                                                                               |
| combinator | string               | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/12.0.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead. |
| negate     | boolean              | `false`  | `false` | False for NULL, True for NOT NULL.                                                                                                                                                                                                                                     |

Adds a where not in clause to the query.  This behaves identically to the [`whereNull`](/12.0.0/query-builder/building-queries/wheres#wherenull) method with the `negate`flag set to `true`.  See the documentation for [`whereNull`](/12.0.0/query-builder/building-queries/wheres#wherenull) for usage and examples.

## Dynamic Where Methods

qb uses `onMissingMethod` to provide a few different helpers when working with `where...` methods.

### andWhere... and orWhere...

Every `where...` method in qb can be called prefixed with either `and` or `or`.  Doing so will call the original method using the corresponding combinator.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "username", "like", "j%" )
    .andWhere( function( q ) {
        q.where( "isSubscribed", 1 )
            .orWhere( "isOnFreeTrial", 1 );
     } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `username` LIKE ?
  AND (
    `isSubscribed` = ?
    OR
    `isOnFreeTrial` = ?
  )
```

{% endcode %}

### where{Column}

If you call a method starting with `where` that does not match an existing qb method, qb will instead call the `where` method using the rest of the method name as the first column name.  (The rest of the arguments will be shifted to account for this.)  This also applies to `andWhere{Column}` and `orWhere{Column}` method signatures.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereUsername( "like", "j%" )
    .whereActive( 1 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `username` LIKE ?
  AND `active` = ?
```

{% endcode %}


# Order By

The `orderBy` method seems simple but has a lot of depth depending on the type of arguments you pass in.

{% hint style="info" %}
Calling `orderBy` multiple times appends to the order list.
{% endhint %}

## Order By (String)

| Name      | Type   | Required | Default | Description                                                                                                                          |
| --------- | ------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| column    | any    | `true`   |         | The name of the column to order by. An [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) can be passed as well. |
| direction | string | `false`  | `"asc"` | The direction by which to order the query. Accepts `"asc"`or `"desc"`.                                                               |

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( "email" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY `email` ASC
```

{% endcode %}

Calling `orderBy` multiple times will append to the order list.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( "email" )
    .orderBy( "username", "desc" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY
  `email` ASC,
  `username` DESC
```

{% endcode %}

You can also provide an [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions).

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( query.raw( "DATE(created_at)" ) );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY DATE(created_at)
```

{% endcode %}

## Order By (List)

| Name      | Type   | Required | Default | Description                                                                                                                                                                                                     |           |
| --------- | ------ | -------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
| column    | any    | `true`   |         | The list of the columns to order by.  Each column can optionally declare it's sort direction after a pipe delimiter. (e.g. \`"height                                                                            | desc"\`). |
| direction | string | `false`  | `"asc"` | The direction by which to order the query. Accepts `"asc"`or `"desc"`.  This value will be used as the default value for all entries in the column list that fail to specify a direction for a specific column. |           |

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( "email|asc,username", "desc" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY
  `email` ASC,
  `username` DESC
```

{% endcode %}

## Order By (Array of Strings)

| Name      | Type   | Required | Default | Description                                                                                                                                                                                                      |           |
| --------- | ------ | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
| column    | any    | `true`   |         | The array of the columns to order by.  Each column can optionally declare it's sort direction after a pipe delimiter. (e.g. \`"height                                                                            | desc"\`). |
| direction | string | `false`  | `"asc"` | The direction by which to order the query. Accepts `"asc"`or `"desc"`.  This value will be used as the default value for all entries in the column array that fail to specify a direction for a specific column. |           |

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( [ "email|asc", "username" ], "desc" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY
  `email` ASC,
  `username` DESC
```

{% endcode %}

## Order By (Array of Structs)

| Name      | Type   | Required | Default | Description                                                                                                                                                                                                                                   |
| --------- | ------ | -------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column    | any    | `true`   |         | The array of the columns to order by.  Each column can optionally declare it's sort direction using a struct.  The struct should have a column key and an optional direction key. (e.g. `{ column = "favorite_color", direction = "desc" }`). |
| direction | string | `false`  | `"asc"` | The direction by which to order the query. Accepts `"asc"`or `"desc"`.  This value will be used as the default value for all entries in the column array that fail to specify a direction for a specific column.                              |

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( [
        { "column": "email", "direction": "asc" },
        "username"
    ], "desc" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY
  `email` ASC,
  `username` DESC
```

{% endcode %}

## Order By (Subquery)

| Name      | Type   | Required | Default | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| --------- | ------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column    | any    | `true`   |         | The name of the column to order by. An [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) can be passed as well. An array can be passed with any combination of simple values, array, struct, or list for each entry in the array (an example with all possible value styles: column = \[ "last\_name", \[ "age", "desc" ], { column = "favorite\_color", direction = "desc" }, "height\|desc" ];. The column argument can also just accept a comman delimited list with a pipe ( \| ) as the secondary delimiter denoting the direction of the order by. The pipe delimiter is also used when parsing the column argument when it is passed as an array and the entry in the array is a pipe delimited string. |
| direction | string | `false`  | `"asc"` | Ignored when using a Function or QueryBuilder instance.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |

You can order with a subquery using either a function or a QueryBuilder instance.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( function( q ) {
        q.selectRaw( "MAX(created_date)" )
            .from( "logins" )
            .whereColumn( "users.id", "logins.user_id" );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY (
    SELECT MAX(created_date)
    FROM `logins`
    WHERE `users`.`id` = `logins`.`user_id`
)
```

{% endcode %}

## Order By Raw

| Name       | Type   | Required | Default | Description                                |
| ---------- | ------ | -------- | ------- | ------------------------------------------ |
| expression | string | `true`   |         | The raw SQL expression to use.             |
| bindings   | array  | `false`  | `[]`    | Any bindings (`?`) used in the expression. |

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderByRaw( "CASE WHEN status = ? THEN 1 ELSE 0 END DESC", [ 1 ] );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY CASE WHEN status = ? THEN 1 ELSE 0 END DESC
```

{% endcode %}

## Order By Random

| Name         | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderByRandom();
```

{% endcode %}

{% tabs %}
{% tab title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY RAND()
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
SELECT *
FROM [users]
ORDER BY NEWID()
```

{% endtab %}

{% tab title="Postgres" %}

```sql
SELECT *
FROM "users"
ORDER BY RANDOM()
```

{% endtab %}

{% tab title="Oracle" %}

```sql
SELECT *
FROM "USERS"
ORDER BY DBMS_RANDOM.VALUE
```

{% endtab %}

{% tab title="SQLite" %}

```sql
SELECT *
FROM "users"
ORDER BY RANDOM()
```

{% endtab %}

{% tab title="Derby" %}

```sql
SELECT *
FROM "users"
ORDER BY RANDOM()
```

{% endtab %}
{% endtabs %}

## clearOrders

| Name         | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

Clears the currently configured orders for the query.  Usually used by downstream libraries like [Quick](https://quick.ortusbooks.com/).

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( "email" )
    .clearOrders();
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
```

{% endcode %}

## reorder

| Name      | Type   | Required | Default | Description                                                                                                                          |
| --------- | ------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| column    | any    | `true`   |         | The name of the column to order by. An [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) can be passed as well. |
| direction | string | `false`  | `"asc"` | The direction by which to order the query. Accepts `"asc"`or `"desc"`.                                                               |

Clears the currently configured orders for the query and sets the new orders passed in.  Any valid argument to [`orderBy`](/12.0.0/query-builder/building-queries/ordering-grouping-and-limit) can be passed here.  Usually used by downstream libraries like [Quick](https://quick.ortusbooks.com/).

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( "email" )
    .reorder( "username" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY `username` ASC
```

{% endcode %}


# Group By and Having

## groupBy

| Name   | Type            | Required | Default | Description                                                                                                                                                                              |
| ------ | --------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| groups | string \| array | `true`   |         | A single column name, a list of column names, or an array of column names to group by.  An [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) can be passed as well. |

Passing a single string will group by that one column.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .groupBy( "country" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
GROUP BY `country`
```

{% endcode %}

You can also pass a list of column names.  A single comma (`","`) will be used as the delimiter.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .groupBy( "country,city" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
GROUP BY `country`, `city`
```

{% endcode %}

An array of column names can be provided.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .groupBy( [ "country", "city" ] );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
GROUP BY `country`, `city`
```

{% endcode %}

Calling `groupBy` multiple times will to the current groups.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .groupBy( "country" )
    .groupBy( "city" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
GROUP BY `country`, `city`
```

{% endcode %}

An [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) can be passed in place of a column.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .groupBy( query.raw( "DATE(created_at)" ) );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
GROUP BY DATE(created_at)
```

{% endcode %}

## having

| Name       | Type                                                                           | Required | Default | Description                                                                                                                                                                                                               |
| ---------- | ------------------------------------------------------------------------------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| [Expression](/12.0.0/query-builder/building-queries/raw-expressions) | `true`   |         | The name of the column or [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                       |
| operator   | any                                                                            | `false`  |         | The operator to use for the constraint (i.e. "=", "<", ">=", etc.). A value can be passed as the `operator` and the `value` left null as a shortcut for equals (e.g. where( "column", 1 ) == where( "column", "=", 1 ) ). |
| value      | any                                                                            | `false`  |         | The value with which to constrain the column.  An [`Expression`](/12.0.0/query-builder/building-queries/raw-expressions) can be passed as well.                                                                           |
| combinator | string                                                                         | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andHaving` and `orHaving` methods instead.                                |

Adds a having clause to a query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .groupBy( "email" )
    .having( "email", ">", 1 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
GROUP BY `email`
HAVING `email` > ?
```

{% endcode %}

`Expressions` can be used in place of the column or the value.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .groupBy( "email" )
    .having( query.raw( "COUNT(email)" ), ">", 1 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
GROUP BY `email`
HAVING COUNT(email) > ?
```

{% endcode %}


# Limit, Offset, and Pagination

## limit

| Name  | Type    | Required | Default | Description                    |
| ----- | ------- | -------- | ------- | ------------------------------ |
| value | numeric | `true`   |         | The limit value for the query. |

Sets the limit value for the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .limit( 5 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
LIMIT 5
```

{% endcode %}

## take

| Name  | Type    | Required | Default | Description                    |
| ----- | ------- | -------- | ------- | ------------------------------ |
| value | numeric | `true`   |         | The limit value for the query. |

Sets the limit value for the query.  Alias for [`limit`](/12.0.0/query-builder/building-queries/limit-offset-and-pagination#limit).

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .take( 5 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
LIMIT 5
```

{% endcode %}

## offset

| Name  | Type    | Required | Default | Description                     |
| ----- | ------- | -------- | ------- | ------------------------------- |
| value | numeric | `true`   |         | The offset value for the query. |

Sets the offset value for the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .offset( 25 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
OFFSET 25
```

{% endcode %}

## forPage

| Name    | Type    | Required | Default | Description                                                                            |
| ------- | ------- | -------- | ------- | -------------------------------------------------------------------------------------- |
| page    | numeric | `true`   |         | The page number to retrieve.                                                           |
| maxRows | numeric | `true`   |         | The number of records per page.  If a number less than 0 is passed, 0 is used instead. |

Helper method to calculate the limit and offset given a page number and count per page.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .forPage( 3, 15 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
LIMIT 15
OFFSET 30
```

{% endcode %}

## simplePaginate & paginate

This method combines `forPage`, `count`, and `get` to create a pagination struct alongside the results. Information on the `simplePaginate` or `paginate` methods, including custom pagination collectors, can be found in the [Retreiving Results](/12.0.0/query-builder/executing-queries/retrieving-results#paginate) section of the documentation.


# Locks

qb includes a few methods to help you lock certain rows when executing `select` statements.

{% hint style="warning" %}
**Note:** For locks to work properly, they must be nested inside a `transaction`.  qb does not handle any of the transaction lifecycle for you.
{% endhint %}

## sharedLock

| Name         | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

A shared lock prevents the selected rows from being modified until your transaction is committed.

{% tabs %}
{% tab title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "id", 1 )
    .sharedLock();
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `id` = ?
LOCK IN SHARE MODE
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
SELECT *
FROM [users] WITH (ROWLOCK,HOLDLOCK)
WHERE [id] = ?
```

{% endtab %}

{% tab title="Postgres" %}

```sql
SELECT *
FROM "users"
WHERE "id" = ?
FOR SHARE
```

{% endtab %}

{% tab title="Oracle" %}

```sql
LOCK TABLE "USERS"
IN SHARE MODE NOWAIT;

SELECT *
FROM "USERS"
WHERE "ID" = ?
```

{% endtab %}
{% endtabs %}

## lockForUpdate

| Name       | Type    | Required | Default | Description |
| ---------- | ------- | -------- | ------- | ----------- |
| skipLocked | Boolean | `false`  | `false` |             |

A lock for update lock prevents the selected rows from being modified or selected with another shared lock until your transaction is committed.

The main difference between a `sharedLock` and `lockForUpdate` is that a `lockForUpdate` prevents other reads or selects as well as updates.

{% tabs %}
{% tab title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "id", 1 )
    .lockForUpdate();
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `id` = ?
FOR UPDATE
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
SELECT *
FROM [users] WITH (ROWLOCK,UPDLOCK,HOLDLOCK)
WHERE [id] = ?
```

{% endtab %}

{% tab title="Postgres" %}

```sql
SELECT *
FROM "users"
WHERE "id" = ?
FOR UPDATE
```

{% endtab %}

{% tab title="Oracle" %}

```sql
SELECT *
FROM "USERS"
WHERE "ID" = ?
FOR UPDATE
```

{% endtab %}
{% endtabs %}

When using the `skipLocked` flag, the query will skip over locked records and only return and lock available records.

{% tabs %}
{% tab title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "id", 1 )
    .lockForUpdate( skipLocked = true )
    .orderBy( "id" )
    .limit( 5 );
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `id` = ?
ORDER BY `id`
LIMIT 5
FOR UPDATE SKIP LOCKED
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
SELECT TOP 5 *
FROM [users] WITH (ROWLOCK,UPDLOCK,HOLDLOCK,READPAST)
WHERE [id] = ?
ORDER BY [id]
```

{% endtab %}

{% tab title="Postgres" %}

```sql
SELECT *
FROM "users"
WHERE "id" = ?
ORDER BY "id"
LIMIT 1
FOR UPDATE SKIP LOCKED
```

{% endtab %}
{% endtabs %}

## noLock

| Name         | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

`noLock` will instruct your grammar to ignore any shared locks when executing the query.

Currently this only makes a difference in SQL Server grammars.

{% tabs %}
{% tab title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "id", 1 )
    .noLock();
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="SQL Server" %}

```sql
SELECT *
FROM [users] WITH (NOLOCK)
WHERE [id] = ?
```

{% endtab %}
{% endtabs %}

## lock

| Name  | Type   | Required | Default | Description                                    |
| ----- | ------ | -------- | ------- | ---------------------------------------------- |
| value | string | `true`   |         | The custom lock directive to add to the query. |

The `lock` method will allow you to add a custom lock directive to your query.  Think of it as the `raw` method for lock directives.

These lock directives vary from grammar to grammar.

## clearLock

| Name         | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

Clears any lock directive on the query.


# Unions

The query builder also lets you create union statements on your queries using either `UNION` or `UNION ALL` strategies.

The `union` methods take either a Query Builder instance or a closure which you use to define a new QueryBuilder instance.

Union statements are added in the order in which the `union` methods are invoked, but the `union` statements can be in any order in your API call stack. This means you can safely declare your `union` method calls before the `select`, `from` and `orderBy` calls on the source Query Builder instance.

* `union()` — This method builds a SQL statement using the `UNION` clause which combines two SQL queries into a single result set containing all the matching rows. The two queries *must* have the same defined columns and compatible data types or the SQL engine will generate an error. The `union` clause only returns unique rows.
* `unionAll()` — This builds a SQL statement using the `UNION ALL` clause. This is the same as `union` but includes duplicate rows.&#x20;

{% hint style="danger" %}
**IMPORTANT:** The QueryBuilder instances passed to a `union` statement *cannot* contain a defined order. Any use of the `orderBy()` method on the unioned QueryBuilder instances will result in an `OrderByNotAllowed`exception. To order the results, add an `orderBy()` call to the parent source Query Builder instance.
{% endhint %}

## union

| Name  | Type                     | Required | Default | Description                                                                                                                               |
| ----- | ------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| input | Function \| QueryBuilder | `true`   |         | The function or QueryBuilder instance to use as the unioned query.                                                                        |
| all   | boolean                  | `false`  | `false` | Determines if statement should be a "UNION ALL". Passing this as an argument is discouraged. Use the dedicated `unionAll` where possible. |

Adds a UNION statement to the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .select( "name" )
    .where( "id", 1 )
    .union( function ( q ) {
        q.from( "users" )
            .select( "name" )
            .where( "id", 2 );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION
SELECT `name`
FROM `users`
WHERE `id` = ?
```

{% endcode %}

Adding multiple union statements will append it to the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .select( "name" )
    .where( "id", 1 )
    .union( function ( q ) {
        q.from( "users" )
            .select( "name" )
            .where( "id", 2 );
    } )
    .union( function ( q ) {
        q.from( "users" )
            .select("name")
            .where( "id", 3 );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION
SELECT `name`
FROM `users`
WHERE `id` = ?
```

{% endcode %}

It can also add union queries as QueryBuilder instances.

{% code title="QueryBuilder" %}

```javascript
var q1 = query.newQuery()
    .from( "users" )
    .select( "name" )
    .where( "id", 2 );
    
var q2 = query.newQuery()
    .from( "users" )
    .select( "name" )
    .where( "id", 3 );

query.from( "users" )
    .select( "name" )
    .where( "id", 1 )
    .union( q1 )
    .union( q2 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION
SELECT `name`
FROM `users`
WHERE `id` = ?
```

{% endcode %}

## unionAll

| Name  | Type                     | Required | Default | Description                                                        |
| ----- | ------------------------ | -------- | ------- | ------------------------------------------------------------------ |
| input | Function \| QueryBuilder | `true`   |         | The function or QueryBuilder instance to use as the unioned query. |

Adds a UNION ALL statement to the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .select( "name" )
    .where( "id", 1 )
    .unionAll( function( q ) {
        q.from( "users" )
            .select( "name" )
            .where( "id", 2 );
     } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION ALL
SELECT `name`
FROM `users`
WHERE `id` = ?
```

{% endcode %}

Adding multiple `unionAll` statements will append it to the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .select( "name" )
    .where( "id", 1 )
    .unionAll( function( q ) {
        q.from( "users" )
            .select( "name" )
            .where( "id", 2 );
     } )
    .unionAll( function( q ) {
        q.from( "users" )
            .select( "name" )
            .where( "id", 3 );
     } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION ALL
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION ALL
SELECT `name`
FROM `users`
WHERE `id` = ?
```

{% endcode %}

It can also add union queries as QueryBuilder instances.

{% code title="QueryBuilder" %}

```javascript
var q1 = query.newQuery()
    .from( "users" )
    .select( "name" )
    .where( "id", 2 );
    
var q2 = query.newQuery()
    .from( "users" )
    .select( "name" )
    .where( "id", 3 );

query.from( "users" )
    .select( "name" )
    .where( "id", 1 )
    .unionAll( q1 )
    .unionAll( q2 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION ALL
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION ALL
SELECT `name`
FROM `users`
WHERE `id` = ?
```

{% endcode %}


# Common Table Expressions (i.e. CTEs)

Common Table Expressions (CTEs) are powerful SQL concept that allow you to create re-usable temporal result sets, which can be referenced as a table within your SQL. CTEs are available in many common database engines and are available in latest versions of all of the support grammars.

CTEs come in two basic types:

* **Non-recursive** — These are statements that do not reference themselves, in simplified terms they are like a derived table that can be referenced by a user-defined name.
* **Recursive** — Recursive CTEs reference themselves and are generally used for creating hierarchical data—such as creating a parent/child relationship within a table.&#x20;

While all of the grammars currently support CTEs, there is enough difference between the various databases implementations of CTEs that unless your CTEs are fairly basic, using CTEs within your project will most likely tie your project to a specific database, unless you account for the differences in your code.

However, CTEs are can be extremely useful to solve certain use cases.

To add CTEs to your queries, you have two methods available:

* `with()` — Allows you to define a non-recursive CTE.
* `withRecursive()` — Allows you to define a recursive CTE.

{% hint style="info" %}
Some database engines require the `recursive` keyword anytime at least one of your CTEs is recursive, but some database engines (e.g. SQL Server and Oracle) do not require the keyword. qb will manage adding the keyword, if necessary. If your query does use recursion you should use the `withRecursive()`method to avoid issues when migrating grammars.
{% endhint %}

## with

| Name      | Type                     | Required | Default | Description                                                                                                                                              |
| --------- | ------------------------ | -------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| name      | string                   | `true`   |         | The name of the CTE.                                                                                                                                     |
| input     | QueryBuilder \| Function | `true`   |         | Either a QueryBuilder instance or a function to define the derived query.                                                                                |
| columns   | Array\<String>           | `false`  | `[]`    | An optional array containing the columns to include in the CTE.                                                                                          |
| recursive | boolean                  | `false`  | `false` | Determines if the CTE statement should be a recursive CTE. Passing this as an argument is discouraged. Use the dedicated `withRecursive` where possible. |

You can build a CTE using a function:

{% code title="QueryBuilder" %}

```javascript
// qb
query.with( "UserCTE", function ( q ) {
        q
            .select( [ "fName as firstName", "lName as lastName" ] )
            .from( "users" )
            .where( "disabled", 0 );
    } )
    .from( "UserCTE" )
    .get();
```

{% endcode %}

{% code title="MySQL" %}

```sql
WITH `UserCTE` AS (
    SELECT
        `fName` as `firstName`,
        `lName` as `lastName`
    FROM `users`
    WHERE `disabled` = 0
) SELECT * FROM `UserCTE`
```

{% endcode %}

Alternatively, you can use a QueryBuilder instance instead of a function:

{% code title="QueryBuilder" %}

```javascript
// qb
var cte = query
    .select( [ "fName as firstName", "lName as lastName" ] )
    .from( "users" )
    .where( "disabled", 0 );

query.with( "UserCTE", cte )
    .from( "UserCTE" )
    .get();
```

{% endcode %}

{% code title="MySQL" %}

```sql
WITH `UserCTE` AS (
    SELECT
        `fName` as `firstName`,
        `lName` as `lastName`
    FROM `users`
    WHERE `disabled` = 0
)
SELECT * FROM `UserCTE`
```

{% endcode %}

A single query can reference multiple CTEs:

{% code title="QueryBuilder" %}

```javascript
query.with( "UserCTE", function ( q ) {
        q.select( [ "id", "fName as firstName", "lName as lastName" ] )
            .from( "users" )
            .where( "disabled", 0 );
    } )
    .with( "BlogCTE", function ( q ) {
        q.from( "blogs" )
            .where( "disabled", 0 );
    } )
    .from( "BlogCTE as b" )
    .join( "UserCTE as u", "b.Creator", "u.id" )
    .get();
```

{% endcode %}

{% code title="MySQL" %}

```sql
WITH `UserCTE` AS (
    SELECT
        `id`,
        `fName` as `firstName`,
        `lName` as `lastName`
    FROM `users`
    WHERE `disabled` = 0
),
`BlogCTE` AS (
    SELECT *
    FROM `blogs`
    WHERE `disabled` = 0
)
SELECT *
FROM `BlogCTE` AS `b`
INNER JOIN `UserCTE` AS `u`
ON `b`.`Creator` = `u`.`id`
```

{% endcode %}

## withRecursive

| Name    | Type                     | Required | Default | Description                                                               |
| ------- | ------------------------ | -------- | ------- | ------------------------------------------------------------------------- |
| name    | string                   | `true`   |         | The name of the CTE.                                                      |
| input   | QueryBuilder \| Function | `true`   |         | Either a QueryBuilder instance or a function to define the derived query. |
| columns | Array\<String>           | `false`  | `[]`    | An optional array containing the columns to include in the CTE.           |

{% hint style="warning" %}
**IMPORTANT** — The way the SQL in a recursive CTEs are written, using them in your code is likely to lock in you in to a specific database engine, unless you structure your code to build the correct SQL based on the current grammar being used.
{% endhint %}

Here is an example of building a recursive CTE using SQL Server which would return all parent/child rows and show their generation/level depth:

{% code title="QueryBuilder" %}

```javascript
query
.withRecursive( "Hierarchy", function ( q ) {
    q.select( [ "Id", "ParentId", "Name", q.raw( "0 AS [Generation]" ) ] )
        .from( "Sample" )
        .whereNull( "ParentId" )
        // use recursion to join the child rows to their parents
        .unionAll( function ( q ) {
            q.select( [
                    "child.Id",
                    "child.ParentId",
                    "child.Name",
                    q.raw( "[parent].[Generation] + 1" )
                ] )
                .from( "Sample as child" )
                .join( "Hierarchy as parent", "child.ParentId", "parent.Id" );
        } );
    }, [ "Id", "ParentId", "Name", "Generation" ] )
    .from( "Hierarchy" )
    .get();
```

{% endcode %}

{% code title="SqlServer" %}

```sql
WITH [Hierarchy] ([Id], [ParentId], [Name], [Generation]) AS (
    SELECT
        [Id],
        [ParentId],
        [Name],
        0 AS [Generation]
    FROM [Sample]
    WHERE [ParentId] IS NULL
    UNION ALL
    SELECT
        [child].[Id],
        [child].[ParentId],
        [child].[Name],

[parent].[Generation] + 1
    FROM [Sample] AS [child]
    INNER JOIN [Hierarchy] AS [parent]
        ON [child].[ParentId] = [parent].[Id]
) SELECT * FROM [Hierarchy]
```

{% endcode %}


# Raw Expressions

Raw expressions are the qb escape hatch.  While qb strives to provide ways to execute the majority of queries, you will occasionally need to provide raw sql values that are not processed by qb.  These SQL snippets are called `raw` or `Expressions` in qb.

{% hint style="warning" %}
`raw` expressions are useful, but shoud be used only if there is not another way to accomplish the same action using other qb methods.  This is because a `raw` expression has the potential to use syntax specific to one database grammar or another, preventing you from easily switching from one grammar to another, one of the major benefits of using qb.
{% endhint %}

The first way to retrieve an `Expression` is to call the `raw` method on the `QueryBuilder` object.

## raw

| Name | Type   | Required | Default | Description                              |
| ---- | ------ | -------- | ------- | ---------------------------------------- |
| sql  | string | true     |         | The raw sql to wrap up in an Expression. |

The sql snippet passed to `raw` is not processed by qb at all.  With that in mind, it is important to follow all best practices and security recommendations with the sql you use with `raw`.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).select( query.raw( "MAX(created_date)" ) );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT MAX(created_date) FROM `users`
```

{% endcode %}

Expressions can be passed to most qb methods, like `select`, `from`, `where`, or `orderBy`, among others.  Additionally, qb provides some convenience methods to add raw values in different parts of the query:

* [selectRaw](/12.0.0/query-builder/building-queries/selects#get-3)
* [fromRaw](/12.0.0/query-builder/building-queries/from#get-2)
* [joinRaw](/12.0.0/query-builder/building-queries/joins#joinraw)
* [leftJoinRaw](/12.0.0/query-builder/building-queries/joins#leftjoinraw)
* [rightJoinRaw](/12.0.0/query-builder/building-queries/joins#rightjoinraw)
* [crossJoinRaw](/12.0.0/query-builder/building-queries/joins#crossjoinraw)
* [whereRaw](/12.0.0/query-builder/building-queries/wheres#whereraw)
* forRaw


# When / Conditionals

If you store the builder object in a variable, you can use `if` and `else` statements like you would expect.

{% code title="QueryBuilder" %}

```javascript
var q = query.from( "posts" );
if ( someFlag ) {
    q.orderBy( "published_date", "desc" );
}
```

{% endcode %}

This works, but breaks chainability. To keep chainability you can use the `when` helper method.

## `when`

| Name           | Type     | Required | Default                     | Description                                                                                                   |
| -------------- | -------- | -------- | --------------------------- | ------------------------------------------------------------------------------------------------------------- |
| condition      | boolean  | true     |                             | The condition to switch on.                                                                                   |
| onTrue         | Function | true     |                             | The callback to execute if the condition is true.  It is passed the `builder` object as the only parameter.   |
| onFalse        | Function | false    | function( q ) { return q; } | The callback to execute if the conditions is false.  It is passed the `builder` object as the only parameter. |
| withoutScoping | boolean  | false    | `false`                     | Flag to turn off the automatic scoping of where clauses during the callback.                                  |

The `when` helper is used to allow conditional statements when defining queries without using if statements and having to store temporary variables.

{% code title="QueryBuilder" %}

```javascript
query.from( "posts" )
    .when( someFlag, function( q ) {
        q.orderBy( "published_date", "desc" );
    } )
    .get();
```

{% endcode %}

You can pass a third argument to be called in the `else` case.

{% code title="QueryBuilder" %}

```javascript
query.from( "posts" )
    .when(
        someFlag,
        function( q ) {
            q.orderBy( "published_date", "desc" );
        },
        function( q ) {
            q.orderBy( "modified_date", "desc" );
        }
    );
```

{% endcode %}

`when` callbacks are automatically scoped and grouped.  That means that if a where clause is added inside the callback with an `OR` combinator the clauses will automatically be grouped (have parenthesis put around them.)  You can disable this feature by passing `withoutScoping = true` to the `when` callback.

```javascript
qb.from( "users" )
    .where( "active", 1 )
    .when( len( url.q ), function( q ) {
        q.where( "username", "LIKE", q & "%" )
            .orWhere( "email", "LIKE", q & "%" );   
    } );
```

```sql
SELECT *
FROM "users"
WHERE "active" = ?
    AND (
        "username" = ?
        OR "email" = ?
    )
```


# Query Parameters and Bindings

## Custom Parameter Types

When passing a parameter to qb, it will infer the sql type to be used.  If you pass a number, `NUMERIC` will be used. If it is a date, `TIMESTAMP`, and so forth. If you need more control, you can pass a struct with the parameters you would pass to [`cfqueryparam`](https://cfdocs.org/cfqueryparam).

{% hint style="success" %}
You can pass include any parameters you would use with [`cfqueryparam`](https://cfdocs.org/cfqueryparam) including `null`, `list`, etc.  This applies anywhere parameters are used including `where`, `update`, and `insert` methods.
{% endhint %}

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "id", "=", { value = 18, cfsqltype = "VARCHAR" } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `id` = ?
```

{% endcode %}

This can be used when inserting or updating records as well.

{% code title="QueryBuilder" %}

```javascript
query.table( "users" )
    .insert( {
        "id" = { value 1, cfsqltype = "VARCHAR" },
        "age" = 18,
        "updatedDate" = { value = now(), cfsqltype = "DATE" }
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
INSERT INTO `users`
    (`id`, `age`, `updatedDate`)
VALUES
    (?, ?, ?)
```

{% endcode %}

### Numeric SQL Types

qb will use a different SQL type for integers and decimals.  You can customize the SQL types by setting the `integerSqlType` and `decimalSqlType` settings.

```cfscript
moduleSettings = {
    "qb": {
        "integerSqlType": "INTEGER",
        "decimalSqlType": "DECIMAL"
    }
};
```

Additionally, qb automatically calculates a scale based on the value provided if the value is a floating point number.

## Bindings

Bindings are the values that will be sent as parameters to a prepared SQL statement.  This protects you from [SQL injection.](https://en.wikipedia.org/wiki/SQL_injection)  In CFML, this uses [`cfqueryparam`](https://cfdocs.org/cfqueryparam) to parameterize the values.

If you need to inspect the bindings for the current query you can retrieve them in order using the `getBindings` method.

{% hint style="info" %}
You can view the current SQL for the query with bindings inline for debugging purposes using the [`toSQL`](/12.0.0/query-builder/debugging#tosql) method.
{% endhint %}

{% hint style="danger" %}
&#x20;Use these methods only for debugging. Modifying the bindings directly will likely cause issues when executing your query.  Adding or removing bindings should be done using the public API.
{% endhint %}

### getBindings

| Name         | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

This method returns the current bindings in order to be used for the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .join( "logins", function( j ) {
        j.on( "users.id", "logins.user_id" );
        j.where( "logins.created_date", ">", dateAdd( "m", -1, "01 Jun 2019" ) );
    } )
    .where( "active", 1 );
```

{% endcode %}

{% code title="Result" %}

```sql
[
    { value = "01 May 2019", cfsqltype = "TIMESTAMP"  },
    { value = 1, cfsqltype = "INTEGER" }
]
```

{% endcode %}

You can also retrieve the bindings associated to their corresponding types.

### getRawBindings

| Name         | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

This method returns the current bindings  to be used for the query associated to their corresponding types.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .join( "logins", function( j ) {
        j.on( "users.id", "logins.user_id" );
        j.where( "logins.created_date", ">", dateAdd( "m", -1, "01 Jun 2019" ) );
    } )
    .where( "active", 1 );
```

{% endcode %}

{% code title="Result" %}

```sql
{
    "commonTables" = [],
    "select" = [],
    "join" = [
        { value = "01 May 2019", cfsqltype = "CF_SQL_TIMESTAMP"  },
    ],
    "where" = [
        { value = 1, cfsqltype = "CF_SQL_NUMERIC" }
    ],
    "union" = [],
    "insert" = [],
    "insertRaw" = [],
    "update" = []
};
```

{% endcode %}

### addBindings

Adds a single binding or an array of bindings to a query for a given type.

| Name        | Type                        | Required | Default   | Description                                                       |
| ----------- | --------------------------- | -------- | --------- | ----------------------------------------------------------------- |
| newBindings | `Struct` \| `Array<Struct>` | true     |           | A single binding or an array of bindings to add for a given type. |
| type        | `String`                    | false    | `"where"` | The type of binding to add.                                       |

### addBindingsFromBuilder

Adds all of the bindings from another builder instance.

| Name | Type           | Required | Default | Description                                                |
| ---- | -------------- | -------- | ------- | ---------------------------------------------------------- |
| qb   | `QueryBuilder` | true     |         | Another builder instance to copy all of the bindings from. |


# Executing Queries


# Retrieving Results

## get

| Name    | Type            | Required | Default | Description                                                                                                    |
| ------- | --------------- | -------- | ------- | -------------------------------------------------------------------------------------------------------------- |
| columns | string \| array | false    |         | A shortcut parameter to retrieve only these columns overriding any columns previously set on the QueryBuilder. |
| options | struct          | false    | `{}`    | Any additional `queryExecute` options.                                                                         |

The `get` method is the most common method used for retrieving results. It executes using the configured `QueryBuilder` and returns the results.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).get();
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT * FROM `users`
```

{% endcode %}

`get` can also take a list or array of columns to use as a shortcut. If any are passed, those columns will be used instead of any columns previously set on the `QueryBuilder`.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).get( [ "id", "name" ] );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT `id`, `name` FROM `users`
```

{% endcode %}

## first

| Name    | Type   | Required | Default | Description                            |
| ------- | ------ | -------- | ------- | -------------------------------------- |
| options | struct | `false`  | `{}`    | Any additional `queryExecute` options. |

If you just need to retrieve a single row from the database table, you may use the `first` method. This method will return a single record (a `Struct` by default). If no row is found an empty `Struct` will be returned by default.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).first();
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT * FROM `users`
 LIMIT(1)
```

{% endcode %}

## firstOrFail

| Name         | Type   | Required | Default | Description                                                                                                                                                         |
| ------------ | ------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| errorMessage | string | `false`  |         | An optional string error message or callback to produce a string error message. If a callback is used, it is passed the QueryBuilder instance as the only argument. |
| options      | struct | `false`  | `{}`    | Any additional `queryExecute` options.                                                                                                                              |

{% hint style="danger" %}
**throws:** `RecordNotFound`
{% endhint %}

Returns the first matching row for the configured query, just like [`first`](#first). If no records are found, it throws an `RecordNotFound` exception.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).firstOrFail();
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT * FROM `users`
 LIMIT(1)
```

{% endcode %}

## find

| Name     | Type     | Required | Default | Description                             |
| -------- | -------- | -------- | ------- | --------------------------------------- |
| id       | `any`    | true     |         | The id value to look up.                |
| idColumn | `string` | false    | `"id"`  | The name of the id column to constrain. |
| options  | `struct` | false    | `{}`    | Any additional `queryExecute` options.  |

Adds an id constraint to the query and returns the first record from the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).find( 1 );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT * FROM `users`
WHERE `id` = ?
LIMIT(1)
```

{% endcode %}

## findOrFail

| Name     | Type     | Required | Default | Description                             |
| -------- | -------- | -------- | ------- | --------------------------------------- |
| id       | `any`    | true     |         | The id value to look up.                |
| idColumn | `string` | false    | `"id"`  | The name of the id column to constrain. |
| options  | `struct` | false    | `{}`    | Any additional `queryExecute` options.  |

{% hint style="danger" %}
**Throws:** `RecordNotFound`
{% endhint %}

Adds an id constraint to the query and returns the first record from the query. If no record is found, it throws an `RecordNotFound` exception.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).find( 415015 );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT * FROM `users`
WHERE `id` = ?
LIMIT(1)
```

{% endcode %}

## values

| Name    | Type   | Required | Default | Description                                                                                                                |
| ------- | ------ | -------- | ------- | -------------------------------------------------------------------------------------------------------------------------- |
| column  | any    | `true`   |         | The name of the column to retrieve or an [Expression](/12.0.0/query-builder/building-queries/raw-expressions) to retrieve. |
| options | struct | `false`  | `{}`    | Any additional `queryExecute` options.                                                                                     |

If you don't even need an entire row, you may extract a single value from each record using the `values` method. The `values` method will return the column of your choosing as a simple array.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).values( "firstName" );
```

{% endcode %}

{% code title="Result" %}

```
[ "jon", "jane", "jill", ... ]
```

{% endcode %}

An expression can also be passed to `values`:

```javascript
qb.from( "users" ).values( qb.raw( "CONCAT(fname, ' ', lname) AS fullName" ) );
```

{% hint style="info" %}
The [`valuesRaw`](/12.0.0/query-builder/executing-queries/retrieving-results#valuesraw) function can make this pattern more ergonomic.
{% endhint %}

## valuesRaw

| Name    | Type   | Required | Default | Description                                                                                |
| ------- | ------ | -------- | ------- | ------------------------------------------------------------------------------------------ |
| column  | string | `true`   |         | The sql to use as an [Expression](/12.0.0/query-builder/building-queries/raw-expressions). |
| options | struct | `false`  | `{}`    | Any additional `queryExecute` options.                                                     |

The `values` method will return the expression given for each row as a simple array.

```javascript
query.from( "users" ).valuesRaw( "CONCAT(fname, ' ', lname) AS fullName" );
```

## value

| Name              | Type    | Required | Default        | Description                                                                                                                |
| ----------------- | ------- | -------- | -------------- | -------------------------------------------------------------------------------------------------------------------------- |
| column            | any     | `true`   |                | The name of the column to retrieve or an [Expression](/12.0.0/query-builder/building-queries/raw-expressions) to retrieve. |
| defaultValue      | string  | `false`  | (empty string) | The default value returned if there are no records returned for the query.                                                 |
| throwWhenNotFound | boolean | `false`  | `false`        | If `true`, it throws a `RecordCountException` if no records are returned from the query.                                   |
| options           | struct  | `false`  | `{}`           | Any additional `queryExecute` options.                                                                                     |

This method is similar to `values` except it only returns a single, simple value. Where `values` calls `get` under the hood, this method calls `first`.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).value( "firstName" );
```

{% endcode %}

{% code title="Result" %}

```
"jon"
```

{% endcode %}

If no records are returned from the query, one of two things will happen. If the `throwWhenNotFound` boolean is set to `true`, a `RecordCountException` will be thrown. Otherwise the `defaultValue` provided to the method will be returned.

An expression can also be passed to `value`:

```javascript
qb.from( "users" ).value( qb.raw( "CONCAT(fname, ' ', lname) AS fullName" ) );
```

{% hint style="info" %}
The [`valueRaw`](/12.0.0/query-builder/executing-queries/retrieving-results#valueraw) function can make this pattern more ergonomic.
{% endhint %}

## valueRaw

| Name              | Type    | Required | Default        | Description                                                                                |
| ----------------- | ------- | -------- | -------------- | ------------------------------------------------------------------------------------------ |
| column            | string  | `true`   |                | The sql to use as an [Expression](/12.0.0/query-builder/building-queries/raw-expressions). |
| defaultValue      | string  | `false`  | (empty string) | The default value returned if there are no records returned for the query.                 |
| throwWhenNotFound | boolean | `false`  | `false`        | If `true`, it throws a `RecordCountException` if no records are returned from the query.   |
| options           | struct  | `false`  | `{}`           | Any additional `queryExecute` options.                                                     |

The `value` method will return the expression given for the first row found.

```javascript
query.from( "users" ).valueRaw( "CONCAT(fname, ' ', lname) AS fullName" );
```

## chunk

| Name     | Type     | Default | Description                                       |
| -------- | -------- | ------- | ------------------------------------------------- |
| max      | numeric  |         | The number of results to return in each chunk.    |
| callback | Function |         | The function that will be called with each chunk. |
| options  | struct   | `{}`    | Any additional `queryExecute` options.            |

Large datasets can be broken up and retrieved in chunks. This allows you to work with a subset of results at once to keep your memory footprint under control.

`chunk` can be called on any query like you would call `get`. You can stop the retrieving and processing early by returning `false` from the callback.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).chunk( 100, function( users ) {
    // Process the users here
    // Returning false from the callback stops processing
} );
```

{% endcode %}

## paginate

| Name    | Type    | Required | Default | Description                                                                            |
| ------- | ------- | -------- | ------- | -------------------------------------------------------------------------------------- |
| page    | numeric | `false`  | `1`     | The page number to retrieve.                                                           |
| maxRows | numeric | `false`  | `25`    | The number of records per page.  If a number less than 0 is passed, 0 is used instead. |
| options | struct  | `false`  | `{}`    | Any additional `queryExecute` options.                                                 |

Generates a pagination struct along with the results of the executed query. It does this by calling both `count` and `forPage`.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .paginate();
```

{% endcode %}

{% code title="Results" %}

```javascript
{
    "pagination": {
        "maxRows": 25,
        "offset": 0,
        "page": 1,
        "totalPages": 2,
        "totalRecords": 45
    },
    "results": [ { /* ... */ }, ]
}
```

{% endcode %}

The behavior when a `maxRows` of 0 or lower is passed is determined by the `shouldMaxRowsOverrideToAll` callback function. The default callback returns all rows for values `<= 0`. You can customize this behavior by passing a new callback to the `shouldMaxRowsOverrideToAll` setting or `init` argument.

## simplePaginate

| Name    | Type    | Required | Default | Description                                                                            |
| ------- | ------- | -------- | ------- | -------------------------------------------------------------------------------------- |
| page    | numeric | `false`  | `1`     | The page number to retrieve.                                                           |
| maxRows | numeric | `false`  | `25`    | The number of records per page.  If a number less than 0 is passed, 0 is used instead. |
| options | struct  | `false`  | `{}`    | Any additional `queryExecute` options.                                                 |

Generates a simple pagination struct along with the results of the executed query. It does so without getting a `count` of the number of records the query would return.  This can be desirable for performance reasons if your query count is rather large.  It instead determines if there are more records by asking for one more row that your specified `maxRows`.  If the number of rows returned exceeds your specified `maxRows` then the pagination returns `hasMore: true`.  The `results` will always contain your specified `maxRows` (or less, if there aren't enough records).

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .simplePaginate();
```

{% endcode %}

{% code title="Results" %}

```javascript
{
    "pagination": {
        "maxRows": 25,
        "offset": 0,
        "page": 1,
        "hasMore": true
    },
    "results": [ { /* ... */ }, ]
}
```

{% endcode %}

The behavior when a `maxRows` of 0 or lower is passed is determined by the `shouldMaxRowsOverrideToAll` callback function. The default callback returns all rows for values `<= 0`. You can customize this behavior by passing a new callback to the `shouldMaxRowsOverrideToAll` setting or `init` argument.

### Custom Pagination Collectors

A pagination collector is the name given to the struct returned from calling the [`paginate`](/12.0.0/query-builder/executing-queries/retrieving-results#paginate) method. It can be a struct or a component. It needs one function defined and will be passed the following parameters.

#### generateWithResults

| Name         | Type    | Description                                                                                            |
| ------------ | ------- | ------------------------------------------------------------------------------------------------------ |
| totalRecords | numeric | The total records count.                                                                               |
| results      | any     | The results of the query execution.  It will be passed as whatever return format the user has defined. |
| page         | numeric | The current page number.                                                                               |
| maxRows      | numeric | The maximum number of rows retrieved per page.                                                         |

You can set your custom pagination collector either in the constructor using the `paginationCollector` argument or by calling `setPaginationCollector` on a query builder instance.

By default, qb ships with [`cbpaginator`](https://forgebox.io/view/cbpaginator) as its pagination collector. The return format of `cbpaginator` is the example shown above.

In qb 8.4.0 the `simplePaginate` method was added.  This uses a new method on the `paginationCollector`.

#### generateSimpleWithResults

| Name    | Type    | Description                                                                                            |
| ------- | ------- | ------------------------------------------------------------------------------------------------------ |
| results | any     | The results of the query execution.  It will be passed as whatever return format the user has defined. |
| page    | numeric | The current page number.                                                                               |
| maxRows | numeric | The maximum number of rows retrieved per page.                                                         |

{% hint style="info" %}
If you use a custom `paginationCollector`, ensure it has been updated with this new `generateSimpleWithResults` method before calling `simplePaginate`.
{% endhint %}


# Aggregates

The query builder also provides a variety of aggregate methods such as `count`, `max`, `min`, and `sum`. These methods take the headache out of setting up these common aggregate functions.

When executing any of the aggregate functions, any `where` restrictions on your query will still be applied.

Instead of returning a query, these methods return a simple value.

## exists

| Name    | Type    | Required | Default | Description                                                 |
| ------- | ------- | -------- | ------- | ----------------------------------------------------------- |
| options | struct  | `false`  | `{}`    | Any additional `queryExecute` options.                      |
| toSQL   | boolean | `false`  | `false` | Returns the query as SQL, if true, instead of executing it. |

Returns `true` if the query returns any rows.  Returns `false` otherwise.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).where( "username", "like", "jon%" ).exists();
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT COUNT(*) AS aggregate FROM `users` WHERE `username` LIKE 'jon%'
```

{% endcode %}

## existsOrFail

| Name         | Type     | Required | Default | Description                            |
| ------------ | -------- | -------- | ------- | -------------------------------------- |
| options      | `struct` | false    | `{}`    | Any additional `queryExecute` options. |
| errorMessage | `string` | false    |         | An optional string error message.      |

Returns `true` if the query returns any rows.  Throws a `RecordNotFound` exception otherwise.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).where( "username", "like", "jon%" ).existsOrFail();
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT COUNT(*) AS aggregate FROM `users` WHERE `username` LIKE 'jon%'
```

{% endcode %}

## count

| Name         | Type    | Required | Default | Description                                                          |
| ------------ | ------- | -------- | ------- | -------------------------------------------------------------------- |
| column       | string  | `false`  | `"*"`   | The column on which to count records.                                |
| defaultValue | any     | `false`  | `0`     | The default value for the `COUNT` query, if no records are returned. |
| options      | struct  | `false`  | `{}`    | Any additional `queryExecute` options.                               |
| toSQL        | boolean | `false`  | `false` | Returns the query as SQL, if true, instead of executing it.          |

Returns an integer number of rows returned by the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).count();
```

{% endcode %}

{% tabs %}
{% tab title="SQL (MySQL)" %}

```sql
SELECT COUNT(*) AS aggregate FROM `users`
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
SELECT COUNT(*) FROM [users]
```

{% endtab %}
{% endtabs %}

## max

| Name         | Type   | Required | Default | Description                                                        |
| ------------ | ------ | -------- | ------- | ------------------------------------------------------------------ |
| column       | string | `true`   |         | The column on which to find the max.                               |
| defaultValue | any    | `false`  |         | The default value for the `MAX` query, if no records are returned. |
| options      | struct | `false`  | `{}`    | Any additional `queryExecute` options.                             |

Returns the maximum value for the given column.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).max( "age" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT MAX(age) AS aggregate FROM `users`
```

{% endcode %}

## min

| Name         | Type   | Required | Default | Description                                                        |
| ------------ | ------ | -------- | ------- | ------------------------------------------------------------------ |
| column       | string | `true`   |         | The column on which to find the min.                               |
| defaultValue | any    | `false`  |         | The default value for the `MIN` query, if no records are returned. |
| options      | struct | `false`  | `{}`    | Any additional `queryExecute` options.                             |

Returns the minimum value for the given column.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).min( "age" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT MIN(age) AS aggregate FROM `users`
```

{% endcode %}

## sum

| Name         | Type   | Required | Default | Description                                                        |
| ------------ | ------ | -------- | ------- | ------------------------------------------------------------------ |
| column       | string | `true`   |         | The column to sum.                                                 |
| defaultValue | any    | `false`  | `0`     | The default value for the `SUM` query, if no records are returned. |
| options      | struct | `false`  | `{}`    | Any additional `queryExecute` options.                             |

Returns the sum of all returned rows for the given column.

{% code title="QueryBuilder" %}

```javascript
query.from( "employees" ).sum( "salary" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT SUM(salary) AS aggregate FROM `employees`
```

{% endcode %}

## sumRaw

| Name    | Type   | Required | Default | Description                            |
| ------- | ------ | -------- | ------- | -------------------------------------- |
| column  | string | `true`   |         | The column to sum.                     |
| options | struct | `false`  | `{}`    | Any additional `queryExecute` options. |

Returns the sum of all returned rows for the expression.

{% code title="QueryBuilder" %}

```javascript
query.from( "accounts" ).sumRaw( "netAdditions + netTransfers" )
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT SUM(netAdditions + netTransfers) AS aggregate FROM `accounts`
```

{% endcode %}

## columnList

| Name       | Type    | Required | Default | Description                                                     |
| ---------- | ------- | -------- | ------- | --------------------------------------------------------------- |
| asQuery    | boolean | `false`  | `false` | Flag to retrieve the columnList as a query instead of an array. |
| datasource | string  | `false`  |         | Optional datasource to from which to retrieve the columnList.   |

Retrieves the columns for the configured table.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).columnList();
```

{% endcode %}

{% code title="Result" %}

```json
[ "id", "firstName", "lastName", "username", "email", "password" ]
```

{% endcode %}


# Inserts, Updates, and Deletes

The following methods all have the same return value:

```javascript
{
    "result": "Value of the `result` parameter to `queryExecute`",
    "query": "Return value of running `queryExecute` - a CFML query object"
}
```

{% hint style="info" %}
`insert`, `update`, and `delete` actions always return a query object for `query`, regardless of your configured `returnFormat`.
{% endhint %}

## insert

| Name    | Type                     | Required | Default | Description                                                                               |
| ------- | ------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------- |
| values  | struct \| array\<struct> | `true`   |         | A struct or array of structs to insert in to the table.                                   |
| options | struct                   | `false`  | `{}`    | Any additional `queryExecute` options.                                                    |
| toSQL   | boolean                  | `false`  | `false` | If `true`, returns the raw SQL string instead of running the query. Useful for debugging. |

{% hint style="warning" %}
This call must come after setting the query's table using [`from`](/12.0.0/query-builder/building-queries/from#get) or [`table`](/12.0.0/query-builder/building-queries/from#get-1).
{% endhint %}

You can insert a single record by passing a struct:

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .insert( {
        "name" = "Robert",
        "email" = "robert@test.com",
        "age" = 55
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
INSERT INTO `users` (`age`, `email`, `name`)
VALUES (?, ?, ?)
```

{% endcode %}

You can specify any [query param](/12.0.0/query-builder/building-queries/parameters-and-bindings#custom-parameter-types) options such as the SQL type by passing a struct with the parameters you would pass to [`cfqueryparam`](https://cfdocs.org/cfqueryparam).

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .insert( {
        "name" = "Robert",
        "email" = "robert@test.com",
        "age" = { value = 55, cfsqltype = "CF_SQL_INTEGER" }
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
INSERT INTO `users` (`age`, `email`, `name`)
VALUES (?, ?, ?)
```

{% endcode %}

Raw values can be supplied to an insert statement.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .insert( {
        "name" = "Robert",
        "email" = "robert@test.com",
        "updatedDate" = query.raw( "NOW()" )
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
INSERT INTO `users` (`age`, `email`, `updatedDate`)
VALUES (?, ?, NOW())
```

{% endcode %}

Multiple rows can be inserted in a batch by passing an array of structs to `insert`.

{% hint style="info" %}
This is not the same as looping over and array and calling `insert` in the loop. Using an array with `insert` will batch the inserts in one SQL call. Looping over an array and calling `insert` each time will create a SQL request for each item in the array. Bottom line, pass your array to `insert`!
{% endhint %}

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).insert( [
    { "email" = "john@example.com", "name" = "John Doe" },
    { "email" = "jane@example.com", "name" = "Jane Doe" }
] );
```

{% endcode %}

{% tabs %}
{% tab title="MySQL" %}

```sql
INSERT INTO `users` (`email`, `name`)
VALUES (?, ?), (?, ?)
```

{% endtab %}

{% tab title="Oracle" %}

```sql
INSERT ALL
INTO "USERS" ("EMAIL", "NAME") VALUES (?, ?)
INTO "USERS" ("EMAIL", "NAME") VALUES (?, ?)
SELECT 1 FROM dual
```

{% endtab %}
{% endtabs %}

## insertIgnore

| Name    | Type                     | Required | Default | Description                                                                               |
| ------- | ------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------- |
| values  | struct \| array\<struct> | true     |         | A struct or array of structs to insert in to the table.                                   |
| target  | array\<string>           | false    | `[]`    | An array of key column names to match on. (SQL Server and Oracle grammars only.)          |
| options | struct                   | false    | `{}`    | Any additional `queryExecute` options.                                                    |
| toSQL   | boolean                  | false    | `false` | If `true`, returns the raw SQL string instead of running the query. Useful for debugging. |

{% hint style="warning" %}
This call must come after setting the query's table using [`from`](/12.0.0/query-builder/building-queries/from#get) or [`table`](/12.0.0/query-builder/building-queries/from#get-1).
{% endhint %}

Inserts data into a table while ignoring duplicate key conflicts.

{% hint style="info" %}
`target` is only required for `SQLServerGrammar` and `OracleGrammar`
{% endhint %}

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .insertIgnore(
        values = [
            { "email" = "foo", "name" = "bar" },
            { "email" = "baz", "name" = "bam" }
        ],
        target = [ "email" ]
    );
```

{% endcode %}

{% tabs %}
{% tab title="MySQL" %}

```sql
INSERT IGNORE INTO `users` (`email`, `name`)
VALUES (?, ?), (?, ?)
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
MERGE [users] AS [qb_target]
USING (VALUES (?, ?), (?, ?)) AS [qb_src] ([email], [name])
ON [qb_target].[email] = [qb_src].[email]
WHEN NOT MATCHED BY TARGET THEN
INSERT ([email], [name]) VALUES ([email], [name]);
```

{% endtab %}

{% tab title="Postgres" %}

```sql
INSERT INTO "users" ("email", "name")
VALUES (?, ?), (?, ?)
ON CONFLICT DO NOTHING
```

{% endtab %}

{% tab title="Oracle" %}

```sql
MERGE INTO "USERS" "QB_TARGET"
USING (SELECT ?, ? FROM dual UNION ALL SELECT ?, ? FROM dual) "QB_SRC"
ON "QB_TARGET"."EMAIL" = "QB_SRC"."EMAIL"
WHEN NOT MATCHED THEN
INSERT ("EMAIL", "NAME")
VALUES ("QB_SRC"."EMAIL", "QB_SRC"."NAME")
```

{% endtab %}
{% endtabs %}

## insertUsing

| Name    | Type                     | Required | Default | Description                                                                                                                                |
| ------- | ------------------------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| source  | function \| QueryBuilder | true     |         | A callback or builder instance to serve as the source of the insert.                                                                       |
| columns | array\<string>           | false    |         | An array of column names that will be inserted. If no columns are passed, the columns will be derived from the source columns and aliases. |
| options | struct                   | false    | `{}`    | Any additional `queryExecute` options.                                                                                                     |
| toSQL   | boolean                  | false    | `false` | If `true`, returns the raw SQL string instead of running the query. Useful for debugging.                                                  |

{% hint style="warning" %}
This call must come after setting the query's table using [`from`](/12.0.0/query-builder/building-queries/from#get) or [`table`](/12.0.0/query-builder/building-queries/from#get-1).
{% endhint %}

Inserts data into a table using a subquery as the source.

```javascript
qb.from( "users" )
    .insertUsing( function( q ) {
        q.from( "activeDirectoryUsers" )
            .select( [ "email", "modifiedDate AS createdDate" ] )
            .where( "active", 1 );
    } );
```

```sql
INSERT INTO `users` (`email`, `createdDate`)
SELECT `email`, `modifiedDate` AS `createdDate`
FROM `activeDirectoryUsers`
WHERE `active` = ?
```

You can also pass in an array of column names to avoid aliasing in your source query.

```javascript
qb.from( "users" )
    .insertUsing(
        columns = [ "email", "createdDate" ],
        source = function( q ) {
            q.from( "activeDirectoryUsers" )
                 .select( [ "email", "modifiedDate" ] )
                 .where( "active", 1 );
        }
    );
```

```sql
INSERT INTO `users` (`email`, `createdDate`)
SELECT `email`, `modifiedDate`
FROM `activeDirectoryUsers`
WHERE `active` = ?
```

Alternatively, the source can be defined as a QueryBuilder object:

```cfscript
qb.from( "users" )
    .insertUsing(
        qb.newQuery()
            .from( "activeDirectoryUsers" )
            .select( [ "email", "modifiedDate AS createdDate" ] )
            .where( "active", 1 )
    );
```

```sql
INSERT INTO `users` (`email`, `createdDate`)
SELECT `email`, `modifiedDate` AS `createdDate`
FROM `activeDirectoryUsers`
WHERE `active` = ?
```

## update

| Name    | Type    | Required | Default | Description                                                                                                                                           |
| ------- | ------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| values  | struct  | `false`  | `{}`    | A struct of column and value pairs to update. These column and value pairs are appended to any already set with the [`addUpdate`](#addupdate) method. |
| options | struct  | `false`  | `{}`    | Any additional `queryExecute` options.                                                                                                                |
| toSQL   | boolean | `false`  | `false` | If `true`, returns the raw SQL string instead of running the query. Useful for debugging.                                                             |

{% hint style="warning" %}
This call must come after setting the query's table using [`from`](/12.0.0/query-builder/building-queries/from#get) or [`table`](/12.0.0/query-builder/building-queries/from#get-1).
{% endhint %}

Updates a table with a struct of column and value pairs.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .update( {
        "email" = "foo",
        "name" = "bar"
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
UPDATE `users`
SET `email` = ?,
    `name` = ?
```

{% endcode %}

You can specify any [query param](/12.0.0/query-builder/building-queries/parameters-and-bindings#custom-parameter-types) options such as the SQL type by passing a struct with the parameters you would pass to [`cfqueryparam`](https://cfdocs.org/cfqueryparam).

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .update( {
        "email" = "foo",
        "name" = "bar",
        "updatedDate" = { value = now(), cfsqltype = "CF_SQL_TIMESTAMP" }
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
UPDATE `users`
SET `email` = ?,
    `name` = ?,
    `updatedDate` = ?
```

{% endcode %}

Any constraining of the update query should be done using the appropriate [WHERE](/12.0.0/query-builder/building-queries/wheres) statement before calling `update`.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereId( 1 )
    .update( {
        "email" = "foo",
        "name" = "bar"
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
UPDATE `users`
SET `email` = ?,
    `name` = ?
WHERE `Id` = ?
```

{% endcode %}

You can update a column based on another column using a raw expression.

{% code title="QueryBuilder" %}

```javascript
query.from( "hits" )
    .where( "page", "someUrl" )
    .update( {
        "count" = query.raw( "count + 1" )
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
UPDATE `hits`
SET `count` = count + 1
WHERE `page` = ?
```

{% endcode %}

### Updating Null values

Null values can be inserted by using queryparam syntax:

```sql
query.from("user")
		.whereId( 10 )
		.update( {
			manager_FK = { value = "", null=true },
		} )
```

if you are using full null support the following (easier) syntax is also allowed:

```sql
query.from("user")
		.whereId( 10 )
		.update( {
			manager_FK = { value = null },
		} )
```

### Updating with Subselects

Subselects can be used to update values by passing a closure as the value

```sql
qb.table( "employees" )
    .update( {
		    "departmentName" = function( q ) {
		        q.from( "departments" )
		            .select( "name" )
		            .whereColumn( "employees.departmentId", "departments.id" );
		    } )
		} );
```

{% tabs %}
{% tab title="MySQL" %}

```sql
UPDATE `employees`
SET `departmentName` = (
    SELECT `name`
    FROM `departments`
    WHERE `employees`.`departmentId` = `departments`.`id`
)
```

{% endtab %}
{% endtabs %}

You can also pass a builder instance in place of the closure.

```sql
qb.table( "employees" )
    .update( {
		    "departmentName" = qb.newQuery()
		        .from( "departments" )
		        .select( "name" )
		        .whereColumn( "employees.departmentId", "departments.id" )
		    } )
		} );
```

### Updating with Joins

qb will correctly format `JOIN` clauses in your `UPDATE` statements for your database grammar.

{% hint style="danger" %}
`OracleGrammar` **does not support** `JOIN` clauses in`UPDATE` statements. Consider using [subselects](#updating-with-subselects) in your `UPDATE` statement instead.
{% endhint %}

```sql
qb.table( "employees" )
    .join( "departments", "departments.id", "employees.departmentId" )
    .update( {
        "employees.departmentName": qb.raw( "departments.name" )
    } );
```

{% tabs %}
{% tab title="MySQL" %}

```sql
UPDATE `employees`
INNER JOIN `departments`
    ON `departments`.`id` = `employees`.`departmentId`
SET `employees`.`departmentName` = departments.name
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
UPDATE [employees]
SET [employees].[departmentName] = departments.name
FROM [employees]
INNER JOIN [departments]
    ON [departments].[id] = [employees].[departmentId]
```

{% endtab %}

{% tab title="Postgres" %}

```sql
UPDATE "employees"
SET "employees"."departmentName" = departments.name
FROM "departments"
WHERE "departments"."id" = "employees"."departmentId"
```

{% endtab %}
{% endtabs %}

## addUpdate

| Name   | Type   | Required | Default | Description                                                     |
| ------ | ------ | -------- | ------- | --------------------------------------------------------------- |
| values | struct | `true`   |         | A struct of column and value pairs to add to the update clause. |

Adds values to a later [`update`](#update), similar to [`addSelect`](/12.0.0/query-builder/building-queries/selects#get-2).

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereId( 1 )
    .addUpdate( {
        "email" = "foo",
        "name" = "bar"
    } )
    .when( true, function( q ) {
        q.addUpdate( {
            "foo": "yes"
        } );
    } )
    .when( false, function( q ) {
        q.addUpdate( {
            "bar": "no"
        } );
    } )
    .update();
```

{% endcode %}

{% code title="MySQL" %}

```sql
UPDATE `users`
SET `email` = ?,
    `foo` = ?,
    `name` = ?
WHERE `Id` = ?
```

{% endcode %}

## updateOrInsert

| Name    | Type    | Required | Default | Description                                                                               |
| ------- | ------- | -------- | ------- | ----------------------------------------------------------------------------------------- |
| values  | struct  | `true`   |         | A struct of column and value pairs to either update or insert.                            |
| options | boolean | `false`  | `{}`    | Any additional `queryExecute` options.                                                    |
| toSql   | boolean | `false`  | `false` | If `true`, returns the raw SQL string instead of running the query. Useful for debugging. |

Performs an update statement if the configured query returns `true` for `exists`. Otherwise, performs an insert statement.

If an update statement is performed qb applies a `limit( 1 )` to the update statement.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "email", "foo" )
    .updateOrInsert( {
        "email" = "foo",
        "name" = "baz"
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
UPDATE `users`
SET `email` = ?,
    `name` = ?
WHERE `email` = ?
LIMIT 1
```

{% endcode %}

If the configured query returns 0 records, then an insert statement is performed.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "email", "foo" )
    .updateOrInsert( {
        "email" = "foo",
        "name" = "baz"
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
INSERT INTO `users` (`email`, `name`)
VALUES (?, ?)
```

{% endcode %}

## upsert

| Name            | Type                                       | Required | Default | Description                                                                                                                                                                                                                                                                    |
| --------------- | ------------------------------------------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| values          | struct \| array\<struct> \| array\<string> | `true`   |         | A struct or array of structs to insert into or update on the table. If a `source` is provided, this should be an array of column names to update instead.                                                                                                                      |
| target          | string \| array\<string>                   | `true`   |         | A column name or array of column names to match the values to the table. If a match is found, the record will be updated. Otherwise, a new record will be inserted. Most database grammars required these columns to have either a primary key or a unique index.              |
| update          | array \| struct                            | `false`  | `null`  | Either an array of columns to update using the current `value` matched or a struct containing the column names as keys and the corresponding to update. If blank, it will update all the columns in the passed in `value`.                                                     |
| source          | function \| QueryBuilder                   | `false`  | `null`  | A callback function or QueryBuilder object to use as the source for the upsert. When using this parameter, `values` must be an array of column names to update.                                                                                                                |
| deleteUnmatched | any                                        | `false`  | `false` | <p>Boolean flag or callback to delete any unmatched source records as part the upsert. (SQL Server only.)<br><br>If a callback is passed, it will be called with a <code>QueryBuilder</code> instance that can be restricted for the <code>DELETE UNMATCHED</code> clause.</p> |
| options         | boolean                                    | `false`  | `{}`    | Any additional `queryExecute` options.                                                                                                                                                                                                                                         |
| toSql           | boolean                                    | `false`  | `false` | If `true`, returns the raw SQL string instead of running the query. Useful for debugging.                                                                                                                                                                                      |

An upsert is a batch operation that either inserts or updates a row depending on if a target match is found. If a row is matched with the target column(s), then the matched row is updated. Otherwise a new row is inserted.

{% hint style="warning" %}
In most database grammars, the target columns are required to be primary key or unique indexes.
{% endhint %}

```sql
qb.table( "users" )
    .upsert(
        values = [
            {
                "username": "johndoe",
                "active": 1,
                "createdDate": "2021-09-08 12:00:00",
                "modifiedDate": "2021-09-08 12:00:00"
            },
            {
                "username": "janedoe",
                "active": 1,
                "createdDate": "2021-09-10 10:42:13",
                "modifiedDate": "2021-09-10 10:42:13"
            },
        ],
        target = [ "username" ],
        update = [ "active", "modifiedDate" ],
    );
```

{% tabs %}
{% tab title="MySQL" %}

```sql
INSERT INTO `users`
    (`active`, `createdDate`, `modifiedDate`, `username`)
VALUES
    (?, ?, ?, ?),
    (?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
    `active` = VALUES(`active`),
    `modifiedDate` = VALUES(`modifiedDate`)
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
MERGE [users] AS [qb_target]
USING (VALUES (?, ?, ?, ?), (?, ?, ?, ?)) AS [qb_src]
    ([active], [createdDate], [modifiedDate], [username])
ON [qb_target].[username] = [qb_src].[username]
WHEN MATCHED THEN UPDATE
    SET [active] = [qb_src].[active],
        [modifiedDate] = [qb_src].[modifiedDate]
WHEN NOT MATCHED BY TARGET THEN INSERT
    ([active], [createdDate], [modifiedDate], [username])
    VALUES
    ([active], [createdDate], [modifiedDate], [username])
```

{% endtab %}

{% tab title="Postgres" %}

```sql
INSERT INTO "users"
    ("active", "createdDate", "modifiedDate", "username")
VALUES
    (?, ?, ?, ?),
    (? ,? ,? ,?)
ON CONFLICT ("username") DO UPDATE
    "active" = EXCLUDED."active",
    "modifiedDate" = EXCLUDED."modifiedDate"
```

{% endtab %}

{% tab title="Oracle" %}

```sql
MERGE INTO "USERS" "QB_TARGET"
USING (
    SELECT ?, ?, ?, ? FROM dual
    UNION ALL
    SELECT ?, ?, ?, ? FROM dual
) "QB_SRC"
ON "QB_TARGET"."USERNAME" = "QB_SRC"."USERNAME"
WHEN MATCHED THEN UPDATE
    SET "ACTIVE" = "QB_SRC"."ACTIVE",
        "MODIFIEDDATE" = "QB_SRC"."MODIFIEDDATE"
WHEN NOT MATCHED THEN INSERT
    ("ACTIVE", "CREATEDDATE", "MODIFIEDDATE", "USERNAME")
    VALUES
    ("QB_SRC"."ACTIVE", "QB_SRC"."CREATEDDATE", "QB_SRC"."MODIFIEDDATE", "QB_SRC"."USERNAME")
```

{% endtab %}
{% endtabs %}

The update clause in a upsert can also accept raw values, making it very useful for tracking data like statistics.

```sql
qb.table( "stats" )
    .upsert(
        values = [
            { "postId": 1, "viewedDate": "2021-09-08", "views": 1 },
            { "postId": 2, "viewedDate": "2021-09-08", "views": 1 }
        ],
        target = [ "postId", "viewedDate" ],
        update = { "views": qb.raw( "stats.views + 1" ) }
    );
```

{% tabs %}
{% tab title="MySQL" %}

```sql
INSERT INTO `stats`
    (`postId`, `viewedDate`, `views`)
VALUES
    (?, ?, ?),
    (?, ?, ?)
ON DUPLICATE KEY UPDATE
    `views` = stats.views + 1
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
MERGE [stats] AS [qb_target]
USING (VALUES (?, ?, ?), (?, ?, ?)) AS [qb_src]
    ([postId], [viewedDate], [views])
ON [qb_target].[postId] = [qb_src].[postId]
    AND [qb_target].[viewedDate] = [qb_src].[viewedDate]
WHEN MATCHED THEN UPDATE
    SET [views] = stats.views + 1
WHEN NOT MATCHED BY TARGET THEN INSERT
    ([postId], [viewedDate], [views])
    VALUES
    ([postId], [viewedDate], [views])
```

{% endtab %}

{% tab title="Postgres" %}

```sql
INSERT INTO "stats"
    ("postId", "viewedDate", "views")
VALUES
    (?, ?, ?),
    (?, ?, ?)
ON CONFLICT ("postId", "viewedDate") DO UPDATE
    "views" = stats.views + 1
```

{% endtab %}

{% tab title="Oracle" %}

```sql
MERGE INTO "STATS" "QB_TARGET"
USING (
    SELECT ?, ?, ? FROM dual
    UNION ALL
    SELECT ?, ?, ? FROM dual
) "QB_SRC"
ON "QB_TARGET"."POSTID" = "QB_SRC"."POSTID"
    AND "QB_TARGET"."VIEWEDDATE" = "QB_SRC"."VIEWEDDATE"
WHEN MATCHED THEN UPDATE
    SET "VIEWS" = stats.views + 1
WHEN NOT MATCHED THEN INSERT
    ("POSTID", "VIEWEDDATE", "VIEWS")
    VALUES
    ("QB_SRC"."POSTID", "QB_SRC"."VIEWEDDATE", "QB_SRC"."VIEWS")
```

{% endtab %}
{% endtabs %}

A source callback or QueryBuilder instance can be used instead of explicit values. This allows you to do upserts across tables or subqueries.

To do this, provide a `source` that is either a function to configure a new QueryBuilder instance or an already configured QueryBuilder instance. Then specify the columns that will be affected as an array of strings to `values`.

```sql
qb.table( "stats" )
    .upsert(
        source = function( q ) {
            q.from( "activeDirectoryUsers" )
                .select( [
                    "username",
                    "active",
                    "createdDate",
                    "modifiedDate"
                ] );
        },
        values = [ "username", "active", "createdDate", "modifiedDate" ],
        target = [ "username" ],
        update = [ "active", "modifiedDate" ]
    );
```

{% tabs %}
{% tab title="MySQL" %}

```sql
INSERT INTO `users`
    (`username`, `active`, `createdDate`, `modifiedDate`)
SELECT `username`, `active`, `createdDate`, `modifiedDate`
FROM `activeDirectoryUsers`
ON DUPLICATE KEY UPDATE
    `active` = VALUES(`active`),
    `modifiedDate` = VALUES(`modifiedDate`)
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
MERGE [users] AS [qb_target]
USING (
    SELECT [username], [active], [createdDate], [modifiedDate]
    FROM [activeDirectoryUsers]
) AS [qb_src]
ON [qb_target].[username] = [qb_src].[username]
WHEN MATCHED THEN UPDATE
    SET [active] = [qb_src].[active],
        [modifiedDate] = [qb_src].[modifiedDate]
WHEN NOT MATCHED BY TARGET THEN INSERT
    ([username], [active], [createdDate], [modifiedDate])
VALUES ([username], [active], [createdDate], [modifiedDate]);
```

{% endtab %}

{% tab title="Postgres" %}

```sql
INSERT INTO "users"
("username", "active", "createdDate", "modifiedDate")
SELECT "username", "active", "createdDate", "modifiedDate"
FROM "activeDirectoryUsers"
ON CONFLICT ("username") DO UPDATE
    "active" = EXCLUDED."active",
    "modifiedDate" = EXCLUDED."modifiedDate"
```

{% endtab %}

{% tab title="Oracle" %}

```sql
MERGE INTO "USERS" "QB_TARGET"
USING (
    SELECT "USERNAME", "ACTIVE", "CREATEDADATE", "MODIFIEDDATE"
    FROM "ACTIVEDIRECTORYUSERS"
) "QB_SRC"
ON "QB_TARGET"."USERNAME" = "QB_SRC"."USERNAME"
WHEN MATCHED THEN UPDATE
    SET "ACTIVE" = "QB_SRC"."ACTIVE",
        "MODIFIEDDATE" = "QB_SRC"."MODIFIEDDATE"
WHEN NOT MATCHED THEN INSERT
    ("USERNAME", "ACTIVE", "CREATEDDATE", "MODIFIEDDATE")
    VALUES
    (
        "QB_SRC"."USERNAME",
        "QB_SRC"."ACTIVE",
        "QB_SRC"."CREATEDDATE",
        "QB_SRC"."MODIFIEDDATE"
    )
```

{% endtab %}
{% endtabs %}

## delete

| Name     | Type    | Required | Default | Description                                                                                                                                                                   |
| -------- | ------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| id       | any     | `false`  |         | A convenience argument for \`where( "id", "=", arguments.id ). The query can be constrained by normal [WHERE](/12.0.0/query-builder/building-queries/wheres) methods as well. |
| idColumn | string  | `false`  | `"id"`  | The name of the id column for the delete shorthand.                                                                                                                           |
| options  | boolean | `false`  | `{}`    | Any additional `queryExecute` options.                                                                                                                                        |
| toSql    | boolean | `false`  | `false` | If `true`, returns the raw SQL string instead of running the query. Useful for debugging.                                                                                     |

Deletes all records that the query returns.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "email", "foo" )
    .delete();
```

{% endcode %}

{% code title="MySQL" %}

```sql
DELETE FROM `users`
WHERE `email` = ?
```

{% endcode %}

The `id` argument is a convenience to delete a single record by id.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .delete( 1 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
DELETE FROM `users`
WHERE `id` = ?
```

{% endcode %}

## returning

| Name    | Type            | Required | Default | Description                                                                                   |
| ------- | --------------- | -------- | ------- | --------------------------------------------------------------------------------------------- |
| columns | string \| array | `true`   |         | A single column, a list or columns, or an array of columns to return from the inserted query. |

{% hint style="danger" %}
`returning` is only supported in `PostgresGrammar`, `SqlServerGrammar`, and `SQLiteGrammar`. Using this method on unsupported grammars will result in an `UnsupportedOperation` exception. Be aware that using this method constrains your grammar choices.
{% endhint %}

Specifies columns to be returned from the insert query.

<pre class="language-javascript" data-title="QueryBuilder"><code class="lang-javascript">query.from( "users" )
    .returning( "id" )
    .insert( {
        "email" = "foo",
        "name" = "bar"
<strong>    } );
</strong></code></pre>

{% tabs %}
{% tab title="SQL Server" %}

```sql
INSERT INTO [users] ([email], [name])
OUTPUT INSERTED.[id]
VALUES (?, ?)
```

{% endtab %}

{% tab title="Postgres" %}

```sql
INSERT INTO "users" ("email", "name")
VALUES (?, ?)
RETURNING "id"
```

{% endtab %}

{% tab title="SQLite" %}

```sql
INSERT INTO "users" ("email", "name")
VALUES (?, ?)
RETURNING "id"
```

{% endtab %}
{% endtabs %}

The `returning` function also applies to `update` and `delete` calls.

{% code title="QueryBuilder" %}

```javascript
query.table( "users" )
    .returning( [ "id", "modifiedDate" ] )
    .where( "id", 1 )
    .update( { "email": "john@example.com" } );
```

{% endcode %}

{% tabs %}
{% tab title="SQL Server" %}

```sql
UPDATE [users]
SET [email] = ?
OUTPUT INSERTED.[id], INSERTED.[modifiedDate]
WHERE [id] = ?
```

{% endtab %}

{% tab title="Postgres" %}

```sql
UPDATE "users"
SET "email" = ?
WHERE "id" = ?
RETURNING "id", "modifiedDate"
```

{% endtab %}

{% tab title="SQLite" %}

```sql
UPDATE "users"
SET "email" = ?
WHERE "id" = ?
RETURNING "id", "modifiedDate"
```

{% endtab %}
{% endtabs %}

<pre class="language-javascript" data-title="QueryBuilder"><code class="lang-javascript"><strong>query.table( "users" )
</strong>    .returning( "id" )
    .where( "active", 0 )
    .delete();
</code></pre>

{% tabs %}
{% tab title="SQL Server" %}

```sql
DELETE FROM [users]
OUTPUT DELETED.[id]
WHERE [active] = ?
```

{% endtab %}

{% tab title="Postgres" %}

```sql
DELETE FROM "users" WHERE "active" = ?
RETURNING "id"
```

{% endtab %}

{% tab title="SQLite" %}

```sql
DELETE FROM "users" WHERE "active" = ?
RETURNING "id"
```

{% endtab %}
{% endtabs %}

You can also use `raw` Expressions in a `returning` call. This is especially useful for SQL Server returning both the old and new values from an `update` call.

{% code title="QueryBuilder" %}

```javascript
qb.from( "users" )
    .where( "id", 1 )
    .returningRaw( [
        "DELETED.modifiedDate AS oldModifiedDate",
        "INSERTED.modifiedDate AS newModifiedDate"
    ] )
    .update( { "email": "john@example.com" } );
```

{% endcode %}

{% tabs %}
{% tab title="SQL Server" %}

```sql
UPDATE [users]
SET [email] = ?
OUTPUT
    DELETED.modifiedDate AS oldModifiedDate,
    INSERTED.modifiedDate AS newModifiedDate
WHERE [id] = ?
```

{% endtab %}
{% endtabs %}

## returningAll

| Name         | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

Shortcut method for `returning( "*" )`.

<pre class="language-javascript" data-title="QueryBuilder"><code class="lang-javascript">query.from( "users" )
    .returningAll()
    .insert( {
        "email" = "foo",
        "name" = "bar"
<strong>    } );
</strong></code></pre>

{% tabs %}
{% tab title="SQL Server" %}

```sql
INSERT INTO [users] ([email], [name])
OUTPUT INSERTED.*
VALUES (?, ?)
```

{% endtab %}

{% tab title="Postgres" %}

```sql
INSERT INTO "users" ("email", "name")
VALUES (?, ?)
RETURNING *
```

{% endtab %}

{% tab title="SQLite" %}

```sql
INSERT INTO "users" ("email", "name")
VALUES (?, ?)
RETURNING *
```

{% endtab %}
{% endtabs %}


# Options and Utilities


# Query Options and Utilities

Each query execution method allows for the passing of an options struct. This is the same struct you would pass to [`queryExecute`](https://cfdocs.org/queryexecute).

## Default Options

qb allows you to specify default options when creating the QueryBuilder instance using the `defaultOptions` argument.

You can set `defaultOptions` for the default QueryBuilder (`QueryBuilder@qb`) in your `config/ColdBox.cfc` file under `moduleSettings`.

```javascript
moduleSettings = {
    "qb": {
        "defaultOptions": {
            "timeout": 60
        }
    }
};
```

You can also combine this with WireBox to create custom QueryBuilder instances pointing to different datasources and even different grammars.

{% hint style="info" %}
When mapping to components provided by modules, such as qb, use the [`afterAspectsLoad`](https://coldbox.ortusbooks.com/digging-deeper/interceptors/core-interception-points/application-life-cycle-events) interception point inside your `config/WireBox.cfc` to ensure all modules are fully loaded and available.
{% endhint %}

{% code title="config/WireBox.cfc" %}

```javascript
component {

    function afterAspectsLoad() {
        binder.map( "MyCustomQueryBuilder" )
            .to( "qb.models.Query.QueryBuilder" )
            .initArg( name = "grammar", ref = "AutoDiscover@qb" )
            .initArg( name = "defaultOptions", value = {
                "datasource": "my_custom_datasource" 
            } );
    }

}
```

{% endcode %}

## Retrieving results from alternative datasources

In `Application.cfc` you can specify your default datasource which will be used by qb. If you want to retrieve data from other datasources you can specify this in all retrieval functions by using the extra options parameter such as:

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .get( options = { datasource: "MyOtherDatasourceName" } );
```

{% endcode %}

If you also want to use a non-default SQL Grammar you have to specify this when creating your `QueryBuilder`.

{% code title="QueryBuilder" %}

```javascript
var query = wirebox.getInstance( "QueryBuilder@qb" )
    .setGrammar( wirebox.getInstance( "SqlServerGrammar@qb" ) );
```

{% endcode %}

## Replacing or Inlining Bindings

qb can inline the query bindings into the SQL string that it has built up.  This is used by other tools like [`toSQL`](/12.0.0/query-builder/debugging#tosql) or [`dump`](/12.0.0/query-builder/debugging#dump) to provide a richer debugging experience.  It is also publicly available for other libraries to use, such as [CommandBox Migrations](https://forgebox.io/view/commandbox-mgirations).

### replaceBindings

Replace the question marks (?) in a sql string with the bindings provided.

| Name     | Type            | Required | Default Value | Description                                                                                                                                      |
| -------- | --------------- | -------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| sql      | `String`        | true     |               | The SQL with question marks (`?`) to replace with bindings.                                                                                      |
| bindings | `Array<Struct>` | true     |               | The bindings to use when replacing the question marks (`?`) in the provided SQL string.                                                          |
| inline   | `boolean`       | false    | `false`       | Flag to inline the bindings value or not.  If `true`, a SQL-executable value will be replaced.  If `false`, the binding struct will be replaced. |

## withoutWrappingValues

Helper method to disable wrapping identifiers only for the given query.

```cfscript
qb.from( "users" ).select( [ "id", "email" ] ).withoutWrappingValues().get();
```

```sql
SELECT id, email FROM users
```

## withWrappingValues

Helper method to enable wrapping identifiers only for the given query.

```cfscript
qb.from( "users" ).select( [ "id", "email" ] ).withWrappingValues().get();
```

```sql
-- MySQL
SELECT `id`, `email` FROM `users`

-- SQL Server
SELECT [id], [email] FROM [users]

-- Postgres, SQLite, Oracle
SELECT "id", "email" FROM "users"
```


# Clone and Reset

## Clone

At times you may need to duplicate a query.  Using `clone` you have a performant way to duplicate a query without using the `duplicate` method.

{% code title="QueryBuilder" %}

```javascript
var q1 = query.from( "users" ).where( "firstName", "like", "Jo%" );
var q2 = q1.clone();
q2.getFrom(); // "users"
```

{% endcode %}

## Reset

When you need to remove all configuration for a query, you can call the `reset` method.

{% code title="QueryBuilder" %}

```javascript
var q1 = query.from( "users" ).where( "firstName", "like", "Jo%" );
var q2 = q1.reset();
q2.getColumns(); // "*"
```

{% endcode %}


# Return Format

`returnFormat` refers to the transformation your executed query makes (if any) before being returned to you. You can choose one of three return formats:

* `"array"`
* `"query"`
* `"none"`
* A custom function

By default, qb returns an array of structs as the result of your query. This is the same as specifying `array` as your `returnFormat`:

{% code title="config/ColdBox.cfc" %}

```javascript
moduleSettings = {
    "qb": {
        "returnFormat": "array"
    }
};
```

{% endcode %}

You can get the original query object that CFML generates by setting the `returnFormat` to `query`:

{% code title="config/ColdBox.cfc" %}

```javascript
moduleSettings = {
    "qb": {
        "returnFormat": "query"
    }
};
```

{% endcode %}

This setting can be overridden on a per-instance basis by calling `setReturnFormat()`:

{% code title="setReturnFormat" %}

```javascript
var qb = wirebox.getInstance( "QueryBuilder@qb" );

qb
   .setReturnFormat( 'query' )
   .from( 'users' )
   .get()
```

{% endcode %}

If you want complete control over your return result, you can provide a function as a `returnFormat`. The results of the function will be returned as the results of the builder.

{% code title="config/ColdBox.cfc" %}

```javascript
moduleSettings = {
    "qb": {
        "returnFormat": function( q ) {
            return application.wirebox.getInstance(
                "name" = "Collection",
                "initArguments" = { "collection": q }
            );
        }
    }
};
```

{% endcode %}


# Column Formatter

Available as an advanced option for framework authors, qb will call out to a column formatter prior to processing a column as part of the SQL query.  This allows frameworks like Quick to define queries using aliases and transform them to columns during execution.

You can provide your own column formatter function to qb through the `init` method or by calling `setColumnFormatter`.  It is a function that takes a column string and returns a string

```javascript
query.setColumnFormatter( function( column ) {
    return lcase( arguments.column );
} );
```


# Interception Points

Two interception points are available from QB: `preQBExecute` and `postQBExecute`. These fire before and after the `queryExecute` call, respectively.

## preQBExecute

The following information is available in the `interceptData` struct:

| Name         | Type   | Description                                             |
| ------------ | ------ | ------------------------------------------------------- |
| sql          | String | The SQL string to execute.                              |
| bindings     | Struct | The struct of bindings (keys and values) for the query. |
| options      | Struct | Any options to pass along to `queryExecute`.            |
| returnObject | String | The type to return: `query` or `result`.                |

## postQBExecute

The following information is available in the `interceptData` struct:

| Name         | Type          | Description                                             |
| ------------ | ------------- | ------------------------------------------------------- |
| sql          | String        | The SQL string to execute.                              |
| bindings     | Struct        | The struct of bindings (keys and values) for the query. |
| options      | Struct        | Any options to pass along to `queryExecute`.            |
| returnObject | String        | The type to return: `query` or `result`.                |
| query        | Query \| null | The query object or `null` if there isn't one.          |
| result       | Struct        | The query result struct.                                |


# Debugging

## Debugging a Single Query

### toSQL

| Name         | Type              | Required | Default  | Description                                                                                                                                                                                                                                                      |
| ------------ | ----------------- | -------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| showBindings | boolean \| string | `false`  | ​`false` | If `true`, the bindings for the query will be substituted back in where the question marks (`?`) appear as `cfqueryparam` structs.  If `inline`, the binding value will be substituted back creating a query that can be copy and pasted to run in a SQL client. |

Returns the SQL that would be executed for the current query.

{% code title="QueryBuilder" %}

```javascript
var q = query.from( "users" )
    .where( "active", "=", 1 );

writeOutput( q.toSQL() );
```

{% endcode %}

{% code title="Result" %}

```sql
SELECT * FROM "users" WHERE "active" = ?
```

{% endcode %}

The bindings for the query are represented by question marks (`?`) just as when using `queryExecute`.  qb can replace each question mark with the corresponding `cfqueryparam`-compatible struct by passing `showBindings = true` to the method.

{% code title="QueryBuilder" %}

```javascript
var q = query.from( "users" )
    .where( "active", "=", 1 );

writeOutput( q.toSQL( showBindings = true ) );
```

{% endcode %}

{% code title="Result" %}

```sql
SELECT * FROM "users" WHERE "active" = {"value":1,"cfsqltype":"CF_SQL_NUMERIC","null":false}
```

{% endcode %}

If you want to show the SQL that would be executed for the `update`, `insert`, `updateOrInsert`, or `delete` methods, you can pass a `toSQL = true` flag to those methods.  Please see those individual methods for more information.

To get back a SQL string that can be copied and pasted into a SQL client to run can be retrieved by passing `showBindings = "inline"`.

{% code title="QueryBuilder" %}

```cfscript
var q = query.from( "users" )
    .where( "active", "=", 1 );

writeOutput( q.toSQL( showBindings = "inline" ) );
```

{% endcode %}

{% code title="Result" %}

```sql
SELECT * FROM "users" WHERE "active" = 1
```

{% endcode %}

### tap

| Name     | Type     | Required | Default | Description                                              |
| -------- | -------- | -------- | ------- | -------------------------------------------------------- |
| callback | Function | `true`   | ​       | A function to execute with a clone of the current query. |

Executes a callback with a clone of the current query passed to it.  Any changes to the passed query is ignored and the original query returned.

While not strictly a debugging method, `tap` makes it easy to see the changes to a query after each call without introducing temporary variables.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .tap( function( q ) {
        writeOutput( q.toSQL() & "<br>" );
    } )
    .where( "active", "=", 1 )
    .tap( function( q ) {
        writeOutput( q.toSQL() & "<br>" );
    } );
```

{% endcode %}

{% code title="Result" %}

```sql
SELECT * FROM "users"
SELECT * FROM "users" WHERE "active" = ?
```

{% endcode %}

### dump

| Name         | Type              | Required | Default | Description                                                                                                                                                                                                                                                      |
| ------------ | ----------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| showBindings | boolean \| string | `false`  | `false` | If `true`, the bindings for the query will be substituted back in where the question marks (`?`) appear as `cfqueryparam` structs.  If `inline`, the binding value will be substituted back creating a query that can be copy and pasted to run in a SQL client. |

A shortcut for the most common use case of `tap`.  This forwards on the SQL for the current query to `writeDump`.  You can pass along any `writeDump` argument to `dump` and it will be forward on.  Additionally, the `showBindings` argument will be forwarded on to the `toSQL` call.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .dump()
    .where( "active", "=", 1 )
    .dump( label = "after where", showBindings = true, abort = true )
    .get();
```

{% endcode %}

{% code title="Result" %}

```sql
SELECT * FROM "users"
SELECT * FROM "users" WHERE "active" = ?
```

{% endcode %}

### pretend

A `QueryBuilder` instance can be put into pretend mode by calling the `pretend` method.  In this mode, the `QueryBuilder` will turn all query operations into no-ops. A log of the SQL that would have been executed can be retrieved from the query log.

Once a `QueryBuilder` instance has been set to pretend mode, it cannot be unset.  Instead, you will need to obtain a [new query](/12.0.0/query-builder/new-query).

### queryLog

Each instance of a `QueryBuilder` maintains a log of queries it executed.  This can be accessed by calling `getQueryLog`. This will return an array of structs like so:

```json
[
  {
    "sql": "SELECT * FROM `users` WHERE `active` = ?",
    "bindings": [ { "value": 1, "sqltype": "bit" } ],
    "options": { "datasource": "main" },
    "returnObject": "array",
    "pretend": false,
    "result": {},
    "executionTime": 21
  }
]
```

This can be very useful in combination with the [`pretend`](#pretend) feature to see what SQL will be executed before actually executing it.

## Debugging All Queries

### [sqlCommenter](/12.0.0/query-builder/debugging/sqlcommenter)

You can add contextual information as a comment to all executed queries using sqlCommenter, [a specification from Google](https://google.github.io/sqlcommenter/).

{% hint style="info" %}
For more information, check out the [dedicated sqlCommenter page](/12.0.0/query-builder/debugging/sqlcommenter).
{% endhint %}

{% content-ref url="/pages/X3oNqa1hvF9Bw01SeFxc" %}
[sqlCommenter](/12.0.0/query-builder/debugging/sqlcommenter)
{% endcontent-ref %}

### cbDebugger

Starting in [cbDebugger](https://forgebox.io/view/cbdebugger) 2.0.0 you can view all your qb queries for a request.  This is enabled by default if you have qb installed.  Make sure your debug output is configured correctly and scroll to the bottom of the page to find the debug output.

![](/files/-M6W633AL1y6DjHAk6pO)

### LogBox Appender

qb is set to log all queries to a debug log out of the box.  To enable this behavior, configure LogBox to allow debug logging from qb's grammar classes.

{% code title="config/ColdBox.cfc" %}

```sql
logbox = {
    debug = [ "qb.models.Grammars" ]
};
```

{% endcode %}

{% hint style="info" %}
qb can be quite chatty when executing many database queries.  Make sure that this logging is only enabled for your development environments using [ColdBox's environment controls](https://coldbox.ortusbooks.com/getting-started/configuration/coldbox.cfc/configuration-directives/environments).
{% endhint %}

### ColdBox Interception Points

ColdBox Interception Points can also be used for logging, though you may find it easier to use LogBox.  See the documentation for [qb's Interception Points](/12.0.0/query-builder/options-and-utilities/interception-points) for more information.


# sqlCommenter

qb supports the [sqlCommenter specification by Google](https://google.github.io/sqlcommenter/) for appending contextual information to executed queries.

sqlCommenter support is **off** by default, but can be activated by setting the `sqlCommenter.enabled` setting.

```cfscript
moduleSettings = {
    "qb": {
        "sqlCommenter": {
            "enabled": true
        }
    }
};
```

Once enabled, qb will append a comment on to every **non-commented** query. This happens as the query is ran, so you will not see this output when calling [`toSQL()`](#tosql) or [`dump()`](#dump).

{% hint style="warning" %}
sqlCommenter will only add a comment to **non-commented** queries.  If you query contains a comment anywhere in it, sqlCommenter will ignore it.
{% endhint %}

An example query with a sqlCommenter comment looks like this:

{% code overflow="wrap" %}

```sql
SELECT * FROM foo /*action='index',dbDriver='mysql-connector-java-8.0.25%20%28Revision%3A%2008be9e9b4cba6aa115f9b27b215887af40b159e0%29',event='Main.index',framework='coldbox-6.0.0',handler='Main',route='%2F'*/
```

{% endcode %}

### Configuring sqlCommenter

The default configuration structure for sqlCommenter is as follows:

```cfscript
settings = {
    "sqlCommenter": {
        "enabled": false,
        "commenters": [
            { "class": "FrameworkCommenter@qb", "properties": {} },
            { "class": "RouteInfoCommenter@qb", "properties": {} },
            { "class": "DBInfoCommenter@qb", "properties": {} }
        ]
    }
};
```

When the `enabled` flag is `false`, no comments will be appended.

The `commenters` array are the different components that will add contextual information to each query.  You define them by defining a struct with a `class` key pointing to a WireBox mapping and a `properties` key containing a struct of any necessary properties.

### Commenters

Each Commenter must implement the `ICommenter` interface. (The `implements` keyword is not required.). They will be called with the `sql` being commented and the current `datasource`.  It should return a struct of key/value pairs that will become comments.

Here is an example of the `FrameworkCommenter@qb`:

```cfscript
component singleton accessors="true" {

    property name="coldboxVersion" inject="coldbox:coldboxSetting:version";

    property name="properties";

    /**
     * Returns a struct of key/value comment pairs to append to the SQL.
     *
     * @sql         The SQL to append the comments to. This is provided if you need to
     *              inspect the SQL to make any decisions about what comments to return.
     * @datasource  The datasource that will execute the query. If null, the default datasource will be used.
     *              This can be used to make decisions about what comments to return.
     */
    public struct function getComments( required string sql, string datasource ) {
        return { "version": "coldbox-#variables.coldboxVersion#" };
    }

}
```

You may use any. all, or none of the `commenters` provided by qb.  You may also create your own for your application.  You may even see commenters pop up on [ForgeBox](https://forgebox.io) for popular use cases.

For example, if you use `cbauth` (or `cbsecurity` using `cbauth`), this commenter will add the current user ID to each query.

```cfscript
component singleton accessors="true" {

    property name="auth" inject="AuthenticationService@cbauth";

    property name="properties";

    /**
     * Returns a struct of key/value comment pairs to append to the SQL.
     *
     * @sql         The SQL to append the comments to. This is provided if you need to
     *              inspect the SQL to make any decisions about what comments to return.
     * @datasource  The datasource that will execute the query. If null, the default datasource will be used.
     *              This can be used to make decisions about what comments to return.
     */
    public struct function getComments( required string sql, string datasource ) {
        return { "userId": variables.auth.getUserId() };
    }

}
```

### Parsing Commented SQL

The comment generated by sqlCommenter is escaped and url-encoded.  It can be reversed by calling the `SQLCommenter.parseCommentedSQL` method with the full query or the `SQLCommenter.parseCommentString` method with just the comment.

#### parseCommentedSQL

| Name | Type   | Required | Default | Description                        |
| ---- | ------ | -------- | ------- | ---------------------------------- |
| sql  | string | `true`   | ​       | The commented SQL string to parse. |

Parses a commented SQL string into the SQL and a struct of the key/value pair comments.

{% code overflow="wrap" %}

```cfscript
getInstance( "ColdBoxSQLCommenter@qb" )
    .parseCommentedSQL( "SELECT * FROM foo /*action='index',dbDriver='mysql-connector-java-8.0.25%20%28Revision%3A%2008be9e9b4cba6aa115f9b27b215887af40b159e0%29',event='Main.index',framework='coldbox-6.0.0',handler='Main',route='%2F'*/" );
```

{% endcode %}

{% code title="Result" %}

```json
{
    "sql": "SELECT * FROM foo",
    "comments": {
        "action": "index",
        "dbDriver": "mysql-connector-java-8.0.25 (Revision: 08be9e9b4cba6aa115f9b27b215887af40b159e0)",
        "event": "Main.index",
        "framework": "coldbox-6.0.0",
        "handler": "Main",
        "route": "/"
    }
}
```

{% endcode %}

#### parseCommentString

| Name          | Type   | Required | Default | Description                                |
| ------------- | ------ | -------- | ------- | ------------------------------------------ |
| commentString | string | `true`   | ​       | The comment string to parse into a struct. |

Parses a comment string into a struct.

{% code overflow="wrap" %}

```cfscript
getInstance( "ColdBoxSQLCommenter@qb" )
    .parseCommentString(
        "/*action='index',dbDriver='mysql-connector-java-8.0.25%20%28Revision%3A%2008be9e9b4cba6aa115f9b27b215887af40b159e0%29',event='Main.index',framework='coldbox-6.0.0',handler='Main',route='%2F'*/"
    );
```

{% endcode %}

{% code title="Result" %}

```json
{
    "action": "index",
    "dbDriver": "mysql-connector-java-8.0.25 (Revision: 08be9e9b4cba6aa115f9b27b215887af40b159e0)",
    "event": "Main.index",
    "framework": "coldbox-6.0.0",
    "handler": "Main",
    "route": "/"
}
```

{% endcode %}

### Integration with non-ColdBox applications

Out of the box, qb includes a `ColdBoxSQLCommenter`. Since sqlCommenter adds contextual information, some level of framework or application integration is necessary.  You can create your own `sqlCommenter` instance by extending the `qb.models.SQLCommenter.SQLCommenter` abstract component. If you create a `SQLCommenter` for a specific framework, consider sharing it with others on [ForgeBox](https://forgebox.io).


# Overview

QB ships with a schema builder to help you build your database objects. This provides a few benefits:

* The syntax is expressive and fluent, making it easy to understand what is being executed
* The syntax is database-agnostic. Specific quirks are isolated in a Grammar file, making it easy to migrate between engines.

You start with a `SchemaBuilder` object. The `SchemaBuilder` takes the same Grammar that a `QueryBuilder` takes.  It can additionally take a struct of default query options forwarded on to `queryExecute` and a `defaultSchema` to use when calling `hasTable` and `hasColumn`. (A `schema` argument passed to those methods still takes precendence.)

```javascript
// manually
var schema = new qb.models.schema.SchemaBuilder(
    grammar = new qb.models.grammars.MySQLGrammar(),
    defaultOptions = { datasource: "my_datasource" }
    defaultSchema = ""
);

// WireBox
var schema = wirebox.getInstance( "SchemaBuilder@qb" );
```

> Note: the `SchemaBuilder` is a transient, and a new one should be created for each operation.

The `SchemaBuilder` has four main methods to start your database object creation:

### [`create`](https://github.com/ortus/qb/tree/b0b49b9b35032508e73231da3a39856a7bc9d21b/schema/schema/create.md)

Create a new table in the database.

| Argument | Type     | Required | Default | Description                                                                                         |
| -------- | -------- | -------- | ------- | --------------------------------------------------------------------------------------------------- |
| table    | string   | `true`   |         | The name of the table to create.                                                                    |
| callback | function | `true`   |         | A callback function used to define the table body. It is passed a `Blueprint` as the only argument. |
| options  | struct   | `false`  | `{}`    | Options to pass to `queryExecute`.                                                                  |
| execute  | boolean  | `false`  | `true`  | Run the query immediately after building it.                                                        |

The majority of the work comes from calling methods on the `Blueprint` object. A `Blueprint` defines the [columns](https://github.com/ortus/qb/tree/b0b49b9b35032508e73231da3a39856a7bc9d21b/schema/schema/columns.md) and [indexes](https://github.com/ortus/qb/tree/b0b49b9b35032508e73231da3a39856a7bc9d21b/schema/schema/indexes.md) for your tables.

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.increments( "id" );
    table.string( "email" );
    table.string( "password" );
    table.timestamp( "created_date" ).nullable();
    table.timestamp( "modified_date" ).nullable();
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
    `email` VARCHAR(255) NOT NULL,
    `password` VARCHAR(255) NOT NULL,
    `created_date` TIMESTAMP,
    `modified_date` TIMESTAMP,
    CONSTRAINT `pk_users_id` PRIMARY KEY (`id`)
)
```

### [`alter`](https://github.com/ortus/qb/tree/b0b49b9b35032508e73231da3a39856a7bc9d21b/schema/schema/alter.md)

Alter an existing table in the database.

| Argument | Type     | Required | Default | Description                                                                                                   |
| -------- | -------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------- |
| table    | string   | `true`   |         | The name of the table to alter.                                                                               |
| callback | function | `true`   |         | A callback function used to define the changes to the table. It is passed a `Blueprint` as the only argument. |
| options  | struct   | `false`  | `{}`    | Options to pass to `queryExecute`.                                                                            |
| execute  | boolean  | `false`  | `true`  | Run the query immediately after building it.                                                                  |

In addition to using the [columns](https://github.com/ortus/qb/tree/b0b49b9b35032508e73231da3a39856a7bc9d21b/schema/schema/columns.md) and [indexes](https://github.com/ortus/qb/tree/b0b49b9b35032508e73231da3a39856a7bc9d21b/schema/schema/indexes.md) off of the passed-in `Blueprint` object, the `Blueprint` contains helpers such as `addConstraint`, `removeConstraint`, `addColumn`, `renameColumn`, and `dropColumn` to assist in altering existing tables.

**Example:**

**SchemaBuilder**

```javascript
schema.alter( "users", function( table ) {
    table.addConstraint( table.unique( "username" ) );
    table.dropColumn( "last_logged_in" );
} );
```

**SQL (MySQL)**

```sql
ALTER TABLE `users` ADD CONSTRAINT `unq_users_username` UNIQUE (`username`);
ALTER TABLE `users` DROP COLUMN `last_logged_in`;
```

### [`drop` and `dropIfExists`](https://github.com/ortus/qb/tree/b0b49b9b35032508e73231da3a39856a7bc9d21b/schema/schema/drop.md)

Drop a table from the database.

| Argument | Type    | Required | Default | Description                                  |
| -------- | ------- | -------- | ------- | -------------------------------------------- |
| table    | string  | `true`   |         | The name of the table to drop.               |
| options  | struct  | `false`  | `{}`    | Options to pass to `queryExecute`.           |
| execute  | boolean | `false`  | `true`  | Run the query immediately after building it. |

**Example:**

**SchemaBuilder**

```javascript
schema.drop( "user_logins" );
```

**SQL (MySQL)**

```sql
DROP TABLE `user_logins`
```

## Additionally, there are a few utility methods defined on `SchemaBuilder` as well:

### `rename`

Rename a table from an old name to a new name

| Argument | Type    | Required | Default | Description                                  |
| -------- | ------- | -------- | ------- | -------------------------------------------- |
| from     | string  | `true`   |         | The old table name.                          |
| to       | string  | `true`   |         | The new table name.                          |
| options  | struct  | `false`  | `{}`    | Options to pass to `queryExecute`.           |
| execute  | boolean | `false`  | `true`  | Run the query immediately after building it. |

**Example:**

**SchemaBuilder**

```javascript
schema.rename( "posts", "blog_posts" );
```

**SQL (MySQL)**

```sql
RENAME TABLE `posts` TO `blog_posts`
```

### `hasTable`

Check if a table exists in the database.

| Argument | Type    | Required | Default | Description                                  |
| -------- | ------- | -------- | ------- | -------------------------------------------- |
| name     | string  | `true`   |         | The name of the table to check.              |
| options  | struct  | `false`  | `{}`    | Options to pass to `queryExecute`.           |
| execute  | boolean | `false`  | `true`  | Run the query immediately after building it. |

**Example:**

**SchemaBuilder**

```javascript
schema.hasTable( "users" );
```

**SQL (MySQL)**

```sql
SELECT 1
FROM `information_schema`.`tables`
WHERE `table_name` = 'users'
```

### `hasColumn`

Check if a column exists in a table in the database.

| Argument | Type    | Required | Default | Description                                       |
| -------- | ------- | -------- | ------- | ------------------------------------------------- |
| table    | string  | `true`   |         | The name of the table to check for the column in. |
| column   | string  | `true`   |         | The column to check for in the table.             |
| options  | struct  | `false`  | `{}`    | Options to pass to `queryExecute`.                |
| execute  | boolean | `false`  | `true`  | Run the query immediately after building it.      |

**Example:**

**SchemaBuilder**

```javascript
schema.hasColumn( "users", "last_logged_in" );
```

**SQL (MySQL)**

```sql
SELECT 1
FROM `information_schema`.`columns`
WHERE `table_name` = 'users'
    AND `column_name` = 'last_logged_in'
```

### pretend


# Creating Tables and Views

## create

This method allows you to create a table object.

| Argument | Type     | Required | Default | Description                                                                                         |
| -------- | -------- | -------- | ------- | --------------------------------------------------------------------------------------------------- |
| table    | string   | `true`   |         | The name of the table to create.                                                                    |
| callback | function | `true`   |         | A callback function used to define the table body. It is passed a `Blueprint` as the only argument. |
| options  | struct   | `false`  | `{}`    | Options to pass to `queryExecute`.                                                                  |
| execute  | boolean  | `false`  | `true`  | Run the query immediately after building it.                                                        |

The majority of the work comes from calling methods on the `Blueprint` object. A `Blueprint` defines the [columns](/12.0.0/schema-builder/columns) and [indexes](/12.0.0/schema-builder/column-modifiers) for your tables.

Example:

```javascript
schema.create( "users", function( table ) {
    table.increments( "id" );
    table.string( "email" );
    table.string( "password" );
    table.timestamp( "created_date" );
    table.timestamp( "modified_date" );
    table.timestamp( "last_logged_in" ).nullable();
} );
```

This would convert to the following SQL in MySQL:

```sql
CREATE TABLE `users` (
    `id` INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `email` VARCHAR(255) NOT NULL,
    `password` VARCHAR(255) NOT NULL,
    `created_date` TIMESTAMP NOT NULL,
    `modified_date` TIMESTAMP NOT NULL,
    `last_logged_in` TIMESTAMP,
    CONSTRAINT `pk_users_id` PRIMARY KEY (`id`)
)
```

Only one table can be created at a time. If you wanted to create multiple tables, you would call `create` multiple times.

The `callback` argument is where you define the schema of your table. It is passed a `Blueprint` object. This is commonly aliased as `table` in the callback. `Blueprint` defines the field, index and constraint methods to build your table. You can find a comprehensive list of all available methods here for [columns](https://github.com/ortus/qb/tree/b0b49b9b35032508e73231da3a39856a7bc9d21b/schema/columns.md) and here for [indexes and constraints](/12.0.0/schema-builder/column-modifiers).

## createAs

This method allows you to create a table using a query.  It is similar to a view except that the data is inserted once at table creation.

{% hint style="warning" %}
This is an `UnsupportedOperation` on `DerbyGrammar`.
{% endhint %}

| Argument     | Type     | Required | Default | Description                                                                                            |
| ------------ | -------- | -------- | ------- | ------------------------------------------------------------------------------------------------------ |
| newTableName | string   | `true`   |         | The name of the table to create.                                                                       |
| callback     | function | `true`   |         | A callback function used to define the table body. It is passed a `QueryBuilder` as the only argument. |
| options      | struct   | `false`  | `{}`    | Options to pass to `queryExecute`.                                                                     |
| execute      | boolean  | `false`  | `true`  | Run the query immediately after building it.                                                           |

Like with a `view`, the columns are defined by the data returned by the query.  The data returned by the query will be inserted into the table.

## createView

This method allows you to create a view using a query.

| Argument | Type     | Required | Default | Description                                                                                            |
| -------- | -------- | -------- | ------- | ------------------------------------------------------------------------------------------------------ |
| view     | string   | `true`   |         | The name of the view to create.                                                                        |
| callback | function | `true`   |         | A callback function used to define the table body. It is passed a `QueryBuilder` as the only argument. |
| options  | struct   | `false`  | `{}`    | Options to pass to `queryExecute`.                                                                     |
| execute  | boolean  | `false`  | `true`  | Run the query immediately after building it.                                                           |


# Columns

The `Blueprint` object has many column types available to construct your table schema. Additionally, you can modify the columns created [with an additional set of methods](/12.0.0/schema-builder/column-modifiers) and [indexes](/12.0.0/schema-builder/column-modifiers).

## bigIncrements

Create an auto-incrementing column using an unsigned `BIGINT` type. This column is also set as the primary key for the table.

| Argument  | Type   | Required | Default | Description                                                                                                                                     |
| --------- | ------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| name      | string | `true`   |         | The name for the column.                                                                                                                        |
| indexName | string | `false`  |         | The name for the primary key index.  If no name is passed in, the name will be dynamically created based off of the table name and column name. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.bigIncrements( "id" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    CONSTRAINT `pk_users_id` PRIMARY KEY (`id`)
)
```

## bigInteger

Create a column using a `BIGINT` equivalent type for your database.

| Argument  | Type    | Required | Default | Description                   |
| --------- | ------- | -------- | ------- | ----------------------------- |
| name      | string  | `true`   |         | The name for the column.      |
| precision | numeric | `false`  |         | The precision for the column. |

**Example (no precision):**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.bigInteger( "salary" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `salary` BIGINT NOT NULL
)
```

**Example (with precision):**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.bigInteger( "salary", 5 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `salary` BIGINT(5) NOT NULL
)
```

## bit

Create a column using a `BIT` equivalent type for your database. The length can be specified as the second argument.

| Argument | Type    | Required | Default | Description                |
| -------- | ------- | -------- | ------- | -------------------------- |
| name     | string  | `true`   |         | The name for the column.   |
| length   | numeric | `false`  | 1       | The length for the column. |

**Example (default length):**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.bit( "is_active" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `is_active` BIT(1) NOT NULL
)
```

**Example (custom length):**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.bit( "is_active", 2 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `is_active` BIT(2) NOT NULL
)
```

## boolean

Create a column using a `BOOLEAN` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.boolean( "is_subscribed" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `is_subscribed` TINYINT(1) NOT NULL
)
```

## char

Create a column using a `CHAR` equivalent type for your database.

| Argument | Type    | Required | Default | Description                |
| -------- | ------- | -------- | ------- | -------------------------- |
| name     | string  | `true`   |         | The name for the column.   |
| length   | numeric | `false`  | 1       | The length for the column. |

**Example (default length):**

**SchemaBuilder**

```javascript
schema.create( "students", function( table ) {
    table.char( "grade" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `students` (
    `grade` CHAR(1) NOT NULL
)
```

**Example (custom length):**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.char( "tshirt_size", 4 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `tshirt_size` CHAR(4) NOT NULL
)
```

## date

Create a column using a `DATE` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.date( "birthday" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `birthday` DATE NOT NULL
)
```

## datetime

Create a column using a `DATETIME` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.datetime( "hire_date" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `hire_date` DATETIME NOT NULL
)
```

## datetimeTz

Create a column using a timezone-specific `DATETIME` equivalent type for your database.

{% hint style="info" %}
Some databases do not have the concept of a timezone-specific datetime.  Those databases will use a normal `DATETIME` type.
{% endhint %}

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.datetimeTz( "posted_date" );
} );
```

**SQL (SQL Server)**

```sql
CREATE TABLE [posts] (
    [posted_date] DATETIMEOFFSET NOT NULL
)
```

## decimal

Create a column using a `DECIMAL` equivalent type for your database. The length and precision can be specified as the second and third arguments.

| Argument  | Type    | Required | Default | Description                  |
| --------- | ------- | -------- | ------- | ---------------------------- |
| name      | string  | `true`   |         | The name for the column.     |
| length    | numeric | `false`  | 10      | The length of the column.    |
| precision | numeric | `false`  | 0       | The precision of the column. |

**Example (with defaults):**

**SchemaBuilder**

```javascript
schema.create( "weather", function( table ) {
    table.decimal( "temperature" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `weather` (
    `temperature` DECIMAL(10,0) NOT NULL
)
```

**Example (with length):**

**SchemaBuilder**

```javascript
schema.create( "weather", function( table ) {
    table.decimal( "temperature", 4 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `weather` (
    `temperature` DECIMAL(4,0) NOT NULL
)
```

**Example (with precision):**

**SchemaBuilder**

```javascript
schema.create( "weather", function( table ) {
    table.decimal( name = "temperature", precision = 2 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `weather` (
    `temperature` DECIMAL(10,2) NOT NULL
)
```

## enum

Create a column using a `ENUM` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.enum( "tshirt_size", [ "S", "M", "L", "XL", "XXL" ] );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `tshirt_size` ENUM(`S`, `M`, `L`, `XL`, `XXL`) NOT NULL
)
```

## float

Create a column using a `FLOAT` equivalent type for your database. The length and precision can be specified as the second and third arguments.

| Argument  | Type    | Required | Default | Description                  |
| --------- | ------- | -------- | ------- | ---------------------------- |
| name      | string  | `true`   |         | The name for the column.     |
| length    | numeric | `false`  | 10      | The length of the column.    |
| precision | numeric | `false`  | 0       | The precision of the column. |

**Example (with defaults):**

**SchemaBuilder**

```javascript
schema.create( "weather", function( table ) {
    table.float( "temperature" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `weather` (
    `temperature` FLOAT(10,0) NOT NULL
)
```

**Example (with length):**

**SchemaBuilder**

```javascript
schema.create( "weather", function( table ) {
    table.float( "temperature", 4 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `weather` (
    `temperature` FLOAT(4,0) NOT NULL
)
```

**Example (with precision):**

**SchemaBuilder**

```javascript
schema.create( "weather", function( table ) {
    table.float( name = "temperature", precision = 2 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `weather` (
    `temperature` FLOAT(10,2) NOT NULL
)
```

## guid

**SQL Server**: Create a column using a `uniqueidentifier`.

**MySQL** and Others: Create a column using a `CHAR` equivalent type for your database and a length of 36. Used in conjunction with the Lucee `createGUID` method or Java's `java.util.UUID.randomUUID()`.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.guid( "id" ).primaryKey();
} );
```

**MySQL (SQL Server)**

```sql
CREATE TABLE `games` (
    `id` uniqueidentifier NOT NULL,
    CONSTRAINT `pk_games_id` PRIMARY KEY (`id`)
)
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `id` VARCHAR(36) NOT NULL,
    CONSTRAINT `pk_games_id` PRIMARY KEY (`id`)
)
```

## increments

Create an auto-incrementing column using an unsigned `INTEGER` type. This column is also set as the primary key for the table.

| Argument  | Type   | Required | Default | Description                                                                                                                                     |
| --------- | ------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| name      | string | `true`   |         | The name for the column.                                                                                                                        |
| indexName | string | `false`  |         | The name for the primary key index.  If no name is passed in, the name will be dynamically created based off of the table name and column name. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.increments( "id" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
    CONSTRAINT `pk_users_id` PRIMARY KEY (`id`)
)
```

## integer

Create a column using a `INTEGER` equivalent type for your database.

| Argument  | Type    | Required | Default | Description                   |
| --------- | ------- | -------- | ------- | ----------------------------- |
| name      | string  | `true`   |         | The name for the column.      |
| precision | numeric | `false`  |         | The precision for the column. |

**Example (no precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.integer( "score" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` INTEGER NOT NULL
)
```

**Example (with precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.integer( "score", 3 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` INTEGER(3) NOT NULL
)
```

## json

Create a column using a `JSON` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.json( "options" ).nullable();
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `options` JSON
)
```

## jsonb

Create a column using a `JSONB` equivalent type for your database.

{% hint style="info" %}
Currently, only `PostgresGrammar` makes a distinction between `json` and `jsonb`.
{% endhint %}

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.jsonb( "options" ).nullable();
} );
```

**Postgres**

```sql
CREATE TABLE "users" (
    "options" JSONB
)
```

## lineString

Create a column using a `LINESTRING` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.lineString( "positions" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `positions` LINESTRING NOT NULL
)
```

## longText

Create a column using a `LONGTEXT` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.longText( "body" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `posts` (
    `body` LONGTEXT NOT NULL
)
```

## mediumIncrements

Create an auto-incrementing column using an unsigned `MEDIUMINT` type. This column is also set as the primary key for the table.

| Argument  | Type   | Required | Default | Description                                                                                                                                     |
| --------- | ------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| name      | string | `true`   |         | The name for the column.                                                                                                                        |
| indexName | string | `false`  |         | The name for the primary key index.  If no name is passed in, the name will be dynamically created based off of the table name and column name. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.mediumIncrements( "id" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
    CONSTRAINT `pk_users_id` PRIMARY KEY (`id`)
)
```

## mediumInteger

Create a column using a `MEDIUMINT` equivalent type for your database.

| Argument  | Type    | Required | Default | Description                   |
| --------- | ------- | -------- | ------- | ----------------------------- |
| name      | string  | `true`   |         | The name for the column.      |
| precision | numeric | `false`  | 10      | The precision for the column. |

**Example (no precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.mediumInteger( "score" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` MEDIUMINT NOT NULL
)
```

**Example (with precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.mediumInteger( "score", 5 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` MEDIUMINT(5) NOT NULL
)
```

## mediumText

Create a column using a `MEDIUMTEXT` equivalent type for your database. For databases that distinguish between unicode and non-unicode fields, creates a non-unicode field.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.mediumText( "body" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `posts` (
    `body` MEDIUMTEXT NOT NULL
)
```

**SQL (MSSQL)**

```sql
CREATE TABLE `posts` (
    `body` VARCHAR(MAX) NOT NULL
)
```

## money

Create a column using a `MONEY` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "transactions", function( table ) {
    table.money( "amount" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `transactions` (
    `amount` INTEGER NOT NULL
)
```

**SQL (MSSQL)**

```sql
CREATE TABLE [transactions] (
    [amount] MONEY NOT NULL
)
```

## morphs

Creates the necessary columns for a polymorphic relationship. It takes the name provided and creates an `_id` and an `_type` column.

If you want different names for your polymorphic relationship columns, feel free to call other schema builder methods individually.

| Argument | Type   | Required | Default | Description                             |
| -------- | ------ | -------- | ------- | --------------------------------------- |
| name     | string | `true`   |         | The prefix for the polymorphic columns. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "tags", function( table ) {
    table.morphs( "taggable" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `tags` (
    `taggable_id` INTEGER UNSIGNED NOT NULL,
    `taggable_type` VARCHAR(255) NOT NULL,
    INDEX `taggable_index` (`taggable_id`, `taggable_type`)
)
```

## nullableMorphs

Creates the necessary columns for a polymorphic relationship. It takes the name provided and creates an `_id` and an `_type` column. The only difference between this method and `morphs` is that the columns created here are nullable.

If you want different names for your polymorphic relationship columns, feel free to call other schema builder methods individually.

| Argument | Type   | Required | Default | Description                             |
| -------- | ------ | -------- | ------- | --------------------------------------- |
| name     | string | `true`   |         | The prefix for the polymorphic columns. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "tags", function( table ) {
    table.nullableMorphs( "taggable" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `tags` (
    `taggable_id` INTEGER UNSIGNED,
    `taggable_type` VARCHAR(255),
    INDEX `taggable_index` (`taggable_id`, `taggable_type`)
)
```

## nullableTimestamps

Creates the `createdDate` and `modifiedDate` `TIMESTAMP` columns. It creates the columns as nullable.

If you want different names for your timestamp columns, feel free to call other schema builder methods individually.

| Argument     | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.nullableTimestamps();
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `posts` (
    `createdDate` TIMESTAMP,
    `modifiedDate` TIMESTAMP
)
```

## point

Create a column using a `POINT` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.point( "position" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `position` POINT NOT NULL
)
```

## polygon

Create a column using a `POLYGON` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.polygon( "positions" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `positions` POLYGON NOT NULL
)
```

## raw

An escape hatch to directly insert any sql in to the statement.

| Argument | Type   | Required | Default | Description                                    |
| -------- | ------ | -------- | ------- | ---------------------------------------------- |
| sql      | string | `true`   |         | The sql to insert directly into the statement. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.raw( "`profile_image` BLOB NOT NULL" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `profile_image` BLOB NOT NULL
)
```

## smallIncrements

Create an auto-incrementing column using an unsigned `SMALLINT` type. This column is also set as the primary key for the table.

| Argument  | Type   | Required | Default | Description                                                                                                                                     |
| --------- | ------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| name      | string | `true`   |         | The name for the column.                                                                                                                        |
| indexName | string | `false`  |         | The name for the primary key index.  If no name is passed in, the name will be dynamically created based off of the table name and column name. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.smallIncrements( "id" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `id` SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
    CONSTRAINT `pk_users_id` PRIMARY KEY (`id`)
)
```

## smallInteger

Create a column using a `SMALLINT` equivalent type for your database.

| Argument  | Type    | Required | Default | Description                   |
| --------- | ------- | -------- | ------- | ----------------------------- |
| name      | string  | `true`   |         | The name for the column.      |
| precision | numeric | `false`  |         | The precision for the column. |

**Example (no precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.smallInteger( "score" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` SMALLINT NOT NULL
)
```

**Example (with precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.smallInteger( "score", 3 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` SMALLINT(3) NOT NULL
)
```

## smallMoney

Create a column using a `SMALLMONEY` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "transactions", function( table ) {
    table.smallMoney( "amount" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `transactions` (
    `amount` INTEGER NOT NULL
)
```

**SQL (MSSQL)**

```sql
CREATE TABLE [transactions] (
    [amount] SMALLMONEY NOT NULL
)
```

## softDeletes

Creates a nullable `deletedDate` `TIMESTAMP` column.

If you want different names for your timestamp column, feel free to call other schema builder methods individually.

| Argument     | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.softDeletes();
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `posts` (
    `deletedDate` TIMESTAMP
)
```

## softDeletesTz

Creates a nullable `deletedDate` timezone-specific `TIMESTAMP` column.

If you want different names for your timestamp column, feel free to call other schema builder methods individually.

| Argument     | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.softDeletesTz();
} );
```

**SQL (SQL Server)**

```sql
CREATE TABLE [posts] (
    [deletedDate] DATETIMEOFFSET
)
```

## string

Create a column using a `VARCHAR` equivalent type for your database. For databases that distinguish between unicode- and non-unicode string data types, this function will create a non-unicode string.

| Argument | Type    | Required | Default | Description               |
| -------- | ------- | -------- | ------- | ------------------------- |
| name     | string  | `true`   |         | The name for the column.  |
| length   | numeric | `false`  | 255     | The length of the column. |

**Example (with defaults):**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.string( "username" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `username` VARCHAR(255) NOT NULL
)
```

**Example (with length):**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.string( "username", 50 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `username` VARCHAR(50) NOT NULL
)
```

## text

Create a column using a `TEXT` equivalent type for your database. For databases that distinguish between unicode- and non-unicode string data types, this function will create a non-unicode text field.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.text( "body" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `posts` (
    `body` TEXT NOT NULL
)
```

## time

Create a column using a `TIME` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "recurring_tasks", function( table ) {
    table.time( "fire_time" );
} );
```

**SQL (Postgres)**

```sql
CREATE TABLE "recurring_tasks" (
    "fire_time" TIME NOT NULL
)
```

## timeTz

Create a column using a timezone-specific `TIME` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "recurring_tasks", function( table ) {
    table.timeTz( "fire_time" );
} );
```

**SQL (Postgres)**

```sql
CREATE TABLE "recurring_tasks" (
    "fire_time" TIME WITH TIME ZONE NOT NULL
)
```

## timestamp

Create a column using a `TIMESTAMP` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.timestamp( "created_at" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `created_at` TIMESTAMP NOT NULL
)
```

## timestamps

Creates the `createdDate` and `modifiedDate` `TIMESTAMP` columns.

If you want different names for your timestamp columns, feel free to call other schema builder methods individually.

| Argument     | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.timestamps();
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `posts` (
    `createdDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `modifiedDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
)
```

## timestampTz

Create a column using a timezone-specific `TIMESTAMP` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.timestampTz( "posted_date" );
} );
```

**SQL (Postgres)**

```sql
CREATE TABLE "posts" (
    "posted_date" TIMESTAMP WITH TIME ZONE NOT NULL
)
```

## timestampsTz

Creates the `createdDate` and `modifiedDate` timezone-specific `TIMESTAMP` columns.

If you want different names for your timestamp columns, feel free to call other schema builder methods individually.

| Argument     | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.timestampsTz();
} );
```

**SQL (Postgres)**

```sql
CREATE TABLE "posts" (
    "createdDate" TIMESTAMP WITH TIME ZONE NOT NULL,
    "modifiedDate" TIMESTAMP WITH TIME ZONE NOT NULL
)
```

## tinyIncrements

Create an auto-incrementing column using an unsigned `TINYINT` type. This column is also set as the primary key for the table.

| Argument  | Type   | Required | Default | Description                                                                                                                                     |
| --------- | ------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| name      | string | `true`   |         | The name for the column.                                                                                                                        |
| indexName | string | `false`  |         | The name for the primary key index.  If no name is passed in, the name will be dynamically created based off of the table name and column name. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.tinyIncrements( "id" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `id` TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
    CONSTRAINT `pk_users_id` PRIMARY KEY (`id`)
)
```

## tinyInteger

Create a column using a `TINYINT` equivalent type for your database.

| Argument  | Type    | Required | Default | Description                   |
| --------- | ------- | -------- | ------- | ----------------------------- |
| name      | string  | `true`   |         | The name for the column.      |
| precision | numeric | `false`  |         | The precision for the column. |

**Example (no precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.tinyInteger( "score" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` TINYINT NOT NULL
)
```

**Example (with precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.tinyInteger( "score", 3 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` TINYINT(3) NOT NULL
)
```

## unicodeLongText

Create a column using a `LONGTEXT` equivalent type for your database. For databases that distinguish between unicode- and non-unicode string data types, this function will create a unicode text field.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.longText( "body" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `posts` (
    `body` LONGTEXT NOT NULL
)
```

**SQL (MSSQL)**

```sql
CREATE TABLE [posts] (
    [body] NVARCHAR(MAX) NOT NULL
)
```

## unicodeMediumText

Create a unicode-enabled column using a `MEDIUMTEXT` equivalent type for your database. For databases that distinguish between unicode- and non-unicode string data types, this function will create a unicode text field.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.unicodeMediumText( "body" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `posts` (
    `body` MEDIUMTEXT NOT NULL
)
```

**SQL (MSSQL)**

```sql
CREATE TABLE [posts] (
    [body] NVARCHAR(MAX) NOT NULL
)
```

## unicodeString

Create a column using a `NVARCHAR` equivalent type for your database. For databases that distinguish between unicode- and non-unicode string data types, this function will create a unicode string.

| Argument | Type    | Required | Default | Description               |
| -------- | ------- | -------- | ------- | ------------------------- |
| name     | string  | `true`   |         | The name for the column.  |
| length   | numeric | `false`  | 255     | The length of the column. |

**Example (with defaults):**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.unicodeString( "username" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `username` VARCHAR(255) NOT NULL
)
```

**SQL (MSSQL)**

```sql
CREATE TABLE [users] (
    [username] NVARCHAR(255) NOT NULL
)
```

**Example (with length):**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.unicodeString( "username", 50 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `username` VARCHAR(50) NOT NULL
)
```

**SQL (MSSQL)**

```sql
CREATE TABLE [users] (
    [username] NVARCHAR(50) NOT NULL
)
```

## unicodeText

Create a column using a `NTEXT` equivalent type for your database.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.unicodeText( "body" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `posts` (
    `body` TEXT NOT NULL
)
```

**SQL (MSSQL)**

```sql
CREATE TABLE [posts] (
    [body] NVARCHAR(MAX) NOT NULL
)
```

## unsignedBigInteger

Create a column using a `UNSIGNED BIGINT` equivalent type for your database.

| Argument  | Type    | Required | Default | Description                   |
| --------- | ------- | -------- | ------- | ----------------------------- |
| name      | string  | `true`   |         | The name for the column.      |
| precision | numeric | `false`  |         | The precision for the column. |

**Example (no precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.unsignedBigInteger( "score" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` BIGINT UNSIGNED NOT NULL
)
```

**Example (with precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.unsignedBigInteger( "score", 3 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` BIGINT(3) UNSIGNED NOT NULL
)
```

## unsignedInteger

Create a column using a `UNSIGNED INTEGER` equivalent type for your database.

| Argument  | Type    | Required | Default | Description                   |
| --------- | ------- | -------- | ------- | ----------------------------- |
| name      | string  | `true`   |         | The name for the column.      |
| precision | numeric | `false`  |         | The precision for the column. |

**Example (no precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.unsignedInteger( "score" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` INTEGER UNSIGNED NOT NULL
)
```

**Example (with precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.unsignedInteger( "score", 3 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` INTEGER(3) UNSIGNED NOT NULL
)
```

## unsignedMediumInteger

Create a column using a `UNSIGNED MEDIUMINT` equivalent type for your database.

| Argument  | Type    | Required | Default | Description                   |
| --------- | ------- | -------- | ------- | ----------------------------- |
| name      | string  | `true`   |         | The name for the column.      |
| precision | numeric | `false`  |         | The precision for the column. |

**Example (no precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.unsignedMediumInteger( "score" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` MEDIUMINT UNSIGNED NOT NULL
)
```

**Example (with precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.unsignedMediumInteger( "score", 3 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` MEDIUMINT(3) UNSIGNED NOT NULL
)
```

## unsignedSmallInteger

Create a column using a `UNSIGNED SMALLINT` equivalent type for your database.

| Argument  | Type    | Required | Default | Description                   |
| --------- | ------- | -------- | ------- | ----------------------------- |
| name      | string  | `true`   |         | The name for the column.      |
| precision | numeric | `false`  |         | The precision for the column. |

**Example (no precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.unsignedSmallInteger( "score" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` SMALLINT UNSIGNED NOT NULL
)
```

**Example (with precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.unsignedSmallInteger( "score", 3 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` SMALLINT(3) UNSIGNED NOT NULL
)
```

## unsignedTinyInteger

Create a column using a `UNSIGNED TINYINT` equivalent type for your database.

| Argument  | Type    | Required | Default | Description                   |
| --------- | ------- | -------- | ------- | ----------------------------- |
| name      | string  | `true`   |         | The name for the column.      |
| precision | numeric | `false`  |         | The precision for the column. |

**Example (no precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.unsignedTinyInteger( "score" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` TINYINT UNSIGNED NOT NULL
)
```

**Example (with precision):**

**SchemaBuilder**

```javascript
schema.create( "games", function( table ) {
    table.unsignedTinyInteger( "score", 3 );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `score` TINYINT(3) UNSIGNED NOT NULL
)
```

## uuid

Creates a column using a `CHAR` equivalent type for your database and a length of 35. Used in conjunction with the CFML `createUUID` method.

| Argument | Type   | Required | Default | Description              |
| -------- | ------ | -------- | ------- | ------------------------ |
| name     | string | `true`   |         | The name for the column. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.uuid( "id" ).primaryKey();
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `games` (
    `id` VARCHAR(35) NOT NULL,
    CONSTRAINT `pk_games_id` PRIMARY KEY (`id`)
)
```


# Column Modifiers

When [creating a column](/12.0.0/schema-builder/columns) from the `Blueprint` object, a `Column` object is returned. This `column` gives you access to a few modifier commands to further configure the column.

## comment

Attach a comment to the column.

| Argument | Type   | Required | Default | Description       |
| -------- | ------ | -------- | ------- | ----------------- |
| comment  | string | `true`   |         | The comment text. |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "users", function( table ) {
    table.integer( "age" ).comment( "Do not lie about your age" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `age` INTEGER NOT NULL COMMENT `Do not lie about your age`
)
```

## default

Sets a default value for the column.

**Note:** The value is not escaped, allowing you to specify functions like `NOW()` or literals like `1`. To specify a literal string, wrap the value in quotes.

| Argument | Type   | Required | Default | Description        |
| -------- | ------ | -------- | ------- | ------------------ |
| value    | string | `true`   |         | The default value. |

**Example:**

**SchemaBuilder**

```
schema.create( "users", function( table ) {
    table.boolean( "is_active" ).default( 1 );
    table.timestamp( "created_date" ).default( "NOW()" );
    tablVIRTUAL NOT NULLe.string( "country" ).default( "'USA'" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `is_active` TINYINT(1) DEFAULT 1,
    `created_date` TIMESTAMP DEFAULT NOW(),
    `country` VARCHAR(255) DEFAULT 'USA'
)
```

## nullable

Sets the column to allow null values.

| Argument     | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

All columns are created as `NOT NULL` by default. As such, there is no `notNull` method.

**Example:**

**SchemaBuilder**

```
schema.create( "users", function( table ) {
    table.timestamp( "last_logged_in" ).nullable()
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `last_logged_in` TIMESTAMP
)
```

## primaryKey

Adds the column as a primary key for the table.

| Argument  | Type   | Required | Default                                                   | Description                                     |
| --------- | ------ | -------- | --------------------------------------------------------- | ----------------------------------------------- |
| indexName | string | `false`  | A derived name built from the table name and column name. | The name to use for the primary key constraint. |

The `primaryKey` method returns a [`TableIndex` instance.](https://github.com/ortus/qb/tree/b0b49b9b35032508e73231da3a39856a7bc9d21b/schema/schema/indexes.md) Additional methods can be chained off of it.

**Example:**

**SchemaBuilder**

```
schema.create( "users", function( table ) {
    table.uuid( "id" ).primaryKey();
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `id` CHAR(35) NOT NULL,
    CONSTAINT `pk_users_id` PRIMARY KEY (`id`)
)
```

## references

Creates a foreign key constraint for the column.

| Argument | Type   | Required | Default | Description        |
| -------- | ------ | -------- | ------- | ------------------ |
| value    | string | `true`   |         | The default value. |

**IMPORTANT:** Additional configuration of the foreign constraint is done by calling methods on the returned [`TableIndex` instance.](https://github.com/ortus/qb/tree/b0b49b9b35032508e73231da3a39856a7bc9d21b/schema/schema/indexes.md)

**Example:**

**SchemaBuilder**

```
schema.create( "users", function( table ) {
    table.unsignedInteger( "country_id" ).references( "id" ).onTable( "countries" ).onDelete( "cascade" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `country_id` INTEGER UNSIGNED NOT NULL,
    CONSTRAINT `fk_users_country_id` FOREIGN KEY (`country_id`) REFERENCES `countries` (`id`) ON UPDATE NO ACTION ON DELETE CASCADE
)
```

## unsigned

Sets the column as unsigned.

| Argument     | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

**Example:**

**SchemaBuilder**

```
schema.create( "users", function( table ) {
    table.integer( age" ).unsigned();
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `age` INTEGER UNSIGNED NOT NULL
)
```

## unique

Sets the column to have the UNIQUE constraint.

| Argument     | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

**Example:**

**SchemaBuilder**

```
schema.create( "email", function( table ) {
    table.string( email" ).unique();
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `email` VARCHAR(255) NOT NULL UNIQUE
)
```

## withCurrent

Sets the column to have the a default value of `CURRENT_TIMESTAMP`.

| Argument     | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

**Example:**

**SchemaBuilder**

```javascript
schema.create( "posts", function( table ) {
    table.timestamp( "posted_date" ).withCurrent();
} );
```

**SQL (Postgres)**

```sql
CREATE TABLE "posts" (
    "posted_date" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
)
```

## storedAs

Creates a stored computed column.  Computed columns are defined as expressions between other columns and/or constant values.  Stored computed columns are saved in the database to avoid computing on every query.

{% hint style="info" %}
Your database grammar may not differentiate between stored computed columns and virtual computed columns.  Research your grammar's implementation for more details.
{% endhint %}

| Argument   | Type   | Required | Default | Description                                 |
| ---------- | ------ | -------- | ------- | ------------------------------------------- |
| expression | string | `true`   |         | The SQL used to define the computed column. |

{% tabs %}
{% tab title="SchemaBuilder" %}

```javascript
schema.create( "products", function( table ) {
    table.integer( "price" );
    table.integer( "tax" ).storedAs( "price * 0.0675" );
} );
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="MySQL" %}

```sql
CREATE TABLE `products` (
    `price` INTEGER NOT NULL,
    `tax` INTEGER GENERATED ALWAYS AS (price * 0.0675) STORED NOT NULL
)
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
CREATE TABLE [products] (
    [price] INTEGER NOT NULL,
    [tax] AS (price * 0.0675) PERSISTED
)
```

{% endtab %}

{% tab title="Postgres" %}

```sql
CREATE TABLE "products" (
    "price" INTEGER NOT NULL,
    "tax" INTEGER NOT NULL GENERATED ALWAYS AS (price * 0.0675) STORED
)
```

{% endtab %}

{% tab title="Oracle" %}

```sql
CREATE TABLE "PRODUCTS" (
    "PRICE" NUMBER(10, 0) NOT NULL,
    "TAX" NUMBER(10, 0) GENERATED ALWAYS AS (price * 0.0675)
)
```

{% endtab %}
{% endtabs %}

## virtualAs

Creates a virtual computed column.  Computed columns are defined as expressions between other columns and/or constant values.  Virtual computed columns are computed on every query.

{% hint style="info" %}
Your database grammar may not differentiate between stored computed columns and virtual computed columns.  Research your grammar's implementation for more details.
{% endhint %}

| Argument   | Type   | Required | Default | Description                                 |
| ---------- | ------ | -------- | ------- | ------------------------------------------- |
| expression | string | `true`   |         | The SQL used to define the computed column. |

{% tabs %}
{% tab title="SchemaBuilder" %}

```javascript
schema.create( "products", function( table ) {
    table.integer( "price" );
    table.integer( "tax" ).virtualAs( "price * 0.0675" );
} );
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="MySQL" %}

```sql
CREATE TABLE `products` (
    `price` INTEGER NOT NULL,
    `tax` INTEGER GENERATED ALWAYS AS (price * 0.0675) VIRTUAL NOT NULL
)
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
CREATE TABLE [products] (
    [price] INTEGER NOT NULL,
    [tax] AS (price * 0.0675)
)
```

{% endtab %}

{% tab title="Postgres" %}

```sql
CREATE TABLE "products" (
    "price" INTEGER NOT NULL,
    "tax" INTEGER GENERATED ALWAYS AS (price * 0.0675) STORED
)
```

{% endtab %}

{% tab title="Oracle" %}

```sql
CREATE TABLE "PRODUCTS" (
    "PRICE" NUMBER(10, 0) NOT NULL,
    "TAX" NUMBER(10, 0) GENERATED ALWAYS AS (price * 0.0675) VIRTUAL
)
```

{% endtab %}
{% endtabs %}


# Column Constraints

A `TableIndex` can be created directly from a [`Blueprint`](/12.0.0/schema-builder/creating-table-constraints) or from a existing [`Column`](/12.0.0/schema-builder/column-modifiers). The `TableIndex` includes methods for further configuring the index which is required when defining foreign keys.

## references

Set the referencing column for a foreign key relationship. For example, `id` for a `country_id` column.

| Argument | Type | Required | Default | Description                                                             |
| -------- | ---- | -------- | ------- | ----------------------------------------------------------------------- |
| columns  | any  | `true`   |         | A column or array of columns that represents the foreign key reference. |

**Example:**

**SchemaBuilder**

```
schema.create( "users", function( table ) {
    table.unsignedInteger( "country_id" ).references( "id" ).onTable( "countries" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `country_id` INTEGER UNSIGNED NOT NULL,
    CONSTRAINT `fk_users_country_id` FOREIGN KEY (`country_id`) REFERENCES `countries` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION
)
```

## onTable

Sets the referencing table for a foreign key relationship. For example, `countries` for a `country_id` column.

| Argument | Type   | Required | Default | Description                 |
| -------- | ------ | -------- | ------- | --------------------------- |
| table    | string | `true`   |         | The referencing table name. |

**Example:**

**SchemaBuilder**

```
schema.create( "users", function( table ) {
    table.unsignedInteger( "country_id" ).references( "id" ).onTable( "countries" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `country_id` INTEGER UNSIGNED NOT NULL,
    CONSTRAINT `fk_users_country_id` FOREIGN KEY (`country_id`) REFERENCES `countries` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION
)
```

## onUpdate

Set the strategy for updating foreign keys when the parent key is updated.

| Argument | Type   | Required | Default | Description                                                                                    |
| -------- | ------ | -------- | ------- | ---------------------------------------------------------------------------------------------- |
| option   | string | `true`   |         | The strategy to use. Available values are: RESTRICT, CASCADE, SET NULL, NO ACTION, SET DEFAULT |

**Example:**

**SchemaBuilder**

```
schema.create( "users", function( table ) {
    table.unsignedInteger( "country_id" )
        .references( "id" )
        .onTable( "countries" )
        .onUpdate( "CASCADE" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `country_id` INTEGER UNSIGNED NOT NULL,
    CONSTRAINT `fk_users_country_id` FOREIGN KEY (`country_id`) REFERENCES `countries` (`id`) ON UPDATE CASCADE ON DELETE NO ACTION
)
```

## onDelete

Set the strategy for updating foreign keys when the parent key is deleted.

| Argument | Type   | Required | Default | Description                                                                                    |
| -------- | ------ | -------- | ------- | ---------------------------------------------------------------------------------------------- |
| option   | string | `true`   |         | The strategy to use. Available values are: RESTRICT, CASCADE, SET NULL, NO ACTION, SET DEFAULT |

**Example:**

**SchemaBuilder**

```
schema.create( "users", function( table ) {
    table.unsignedInteger( "country_id" )
        .references( "id" )
        .onTable( "countries" )
        .onDelete( "SET NULL" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `country_id` INTEGER UNSIGNED NOT NULL,
    CONSTRAINT `fk_users_country_id` FOREIGN KEY (`country_id`) REFERENCES `countries` (`id`) ON UPDATE NO ACTION ON DELETE SET NULL
)
```


# Creating Table Constraints

Sometimes you want to add constraints on a table level, rather than a column level. The following methods will let you accomplish that.

## index

Create a generic index from one or more columns.

| Argument | Type            | Required | Default                                                           | Description                                            |
| -------- | --------------- | -------- | ----------------------------------------------------------------- | ------------------------------------------------------ |
| columns  | string or array | `true`   |                                                                   | The column or array of columns that make up the index. |
| name     | string          | `false`  | A generated name consisting of the table name and column name(s). | The name of the index constraint.                      |
|          |                 |          |                                                                   |                                                        |

**Example:**

**SchemaBuilder**

```
schema.create( "users", function( table ) {
    table.string( "first_name" );
    table.string( "last_name" );
    table.index( [ "first_name", "last_name" ], "idx_users_full_name" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `first_name` VARCHAR(255) NOT NULL,
    `last_name` VARCHAR(255) NOT NULL,
    INDEX `idx_users_full_name` (`first_name`, `last_name`)
)
```

## foreignKey

Create a foreign key constraint from one or more columns. Follow up this call with calls to the `TableIndex`'s [`references`](broken://pages/-LA-U_axqzow_9OdzTRT#references) and [`onTable`](broken://pages/-LA-U_axqzow_9OdzTRT#onTable) methods.

| Argument | Type            | Required | Default                                                           | Description                                                                    |
| -------- | --------------- | -------- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| columns  | string or array | `true`   |                                                                   | The column or array of columns that references a key or keys on another table. |
| name     | string          | `false`  | A generated name consisting of the table name and column name(s). | The name of the foreign key constraint.                                        |

**Example:**

**SchemaBuilder**

```
schema.create( "users", function( table ) {
    table.unsignedInteger( "country_id" );
    table.foreignKey( "country_id" ).references( "id" ).onTable( "countries" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `country_id` INTEGER UNSIGNED NOT NULL,
    CONSTRAINT `fk_users_country_id` FOREIGN KEY (`country_id`) REFERENCES `countries` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION
)
```

## primaryKey

Create a primary key constraint from one or more columns.

| Argument | Type            | Required | Default                                                           | Description                                                  |
| -------- | --------------- | -------- | ----------------------------------------------------------------- | ------------------------------------------------------------ |
| columns  | string or array | `true`   |                                                                   | The column or array of columns that make up the primary key. |
| name     | string          | `false`  | A generated name consisting of the table name and column name(s). | The name of the primary key constraint.                      |
|          |                 |          |                                                                   |                                                              |

**Example:**

**SchemaBuilder**

```
schema.create( "posts_users", function( table ) {
    table.unsignedInteger( "post_id" ).references( "id" ).onTable( "posts" );
    table.unsignedInteger( "user_id" ).references( "id" ).onTable( "users" );
    table.primaryKey( [ "post_id", "user_id" ], "pk_posts_users" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `posts_users` (
    `post_id` VARCHAR(255) NOT NULL,
    `user_id` VARCHAR(255) NOT NULL,
    INDEX `idx_users_full_name` (`first_name`, `last_name`),
    CONSTRAINT `fk_posts_users_post_id` FOREIGN KEY (`post_id`) REFERENCES `posts` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION,
    CONSTRAINT `fk_posts_users_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION,
    CONSTRAINT ""pk_users_first_name_last_name"" PRIMARY KEY (""first_name"", ""last_name"")
)
```

## unique

Create a unique constraint from one or more columns.

| Argument | Type            | Required | Default                                                           | Description                                                        |
| -------- | --------------- | -------- | ----------------------------------------------------------------- | ------------------------------------------------------------------ |
| columns  | string or array | `true`   |                                                                   | The column or array of columns that make up the unique constraint. |
| name     | string          | `false`  | A generated name consisting of the table name and column name(s). | The name of the unique constraint.                                 |

**Example:**

**SchemaBuilder**

```
schema.create( "users", function( table ) {
    table.increments( "id" );
    table.string( "username ");
    table.unique( "username" );
} );
```

**SQL (MySQL)**

```sql
CREATE TABLE `users` (
    `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
    UNIQUE (`username`)
)
```


# Altering Tables and Views

## alter

The alter method loads up an existing table in order to make modifications. These modifications may include adding, renaming, or dropping columns and constraints.

To begin altering an existing table, call the `alter` method off of the `SchemaBuilder`. This method takes a callback as the second parameter that is passed a `Blueprint` object, much like the [`create`](/12.0.0/schema-builder/create) method.

| Argument | Type     | Required | Default | Description                                                                                                       |
| -------- | -------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------- |
| table    | string   | `true`   |         | The name of the table to alter.                                                                                   |
| callback | function | `true`   |         | A callback function used to define the alterations to the table. It is passed a `Blueprint` as the only argument. |
| options  | struct   | `false`  | `{}`    | Options to pass to `queryExecute`.                                                                                |
| execute  | boolean  | `false`  | `true`  | Run the query immediately after building it.                                                                      |

> Calling multiple methods inside a single `alter` callback creates multiple SQL statements to be executed. qb takes care of this execution for you by default.

The following methods off of `Blueprint` let you modify the table inside the callback:

### addColumn

Add a new column to an existing table. Takes a `Column` instance as the only argument.

Any instance of `Column` is valid like those returned by the [column methods](/12.0.0/schema-builder/columns) (`integer`, `string`, etc.) as well as the [column modifier methods](/12.0.0/schema-builder/column-modifiers) (`unsigned`, `nullable`, etc.).

| Argument | Type     | Required | Default | Description                          |
| -------- | -------- | -------- | ------- | ------------------------------------ |
| column   | `Column` | `true`   |         | A column object to add to the table. |

**Example:**

**SchemaBuilder**

```javascript
schema.alter( "users", function( table ) {
    table.addColumn( table.boolean( "is_active" ) );
} );
```

**SQL (MySQL)**

```sql
ALTER TABLE `users` ADD `is_active` TINYINT(1) NOT NULL
```

### raw

An escape hatch to directly insert any sql in to the statement.

| Argument | Type   | Required | Default | Description                                    |
| -------- | ------ | -------- | ------- | ---------------------------------------------- |
| sql      | string | `true`   |         | The sql to insert directly into the statement. |

**Example:**

**SchemaBuilder**

```javascript
schema.alter( "registrars", function ( table ) {
    table.addColumn(
        table.raw( "HasDNSSecAPI bit NOT NULL CONSTRAINT DF_registrars_HasDNSSecAPI DEFAULT (0)" )
    );
} );
```

**SQL (MySQL)**

```sql
ALTER TABLE `registrars`
ADD HasDNSSecAPI bit NOT NULL
CONSTRAINT DF_registrars_HasDNSSecAPI DEFAULT (0)
```

### dropColumn

Drop a column on an existing table.

| Argument | Type   | Required | Default | Description                     |
| -------- | ------ | -------- | ------- | ------------------------------- |
| name     | string | `true`   |         | The name of the column to drop. |

**Example:**

**SchemaBuilder**

```javascript
schema.alter( "users", function( table ) {
    table.dropColumn( "username" );
} );
```

**SQL (MySQL)**

```sql
ALTER TABLE `users` DROP COLUMN `username`
```

### modifyColumn

Modify an existing column on a table.

| Argument | Type     | Required | Default | Description                                  |
| -------- | -------- | -------- | ------- | -------------------------------------------- |
| name     | string   | `true`   |         | The name of the column to modify.            |
| column   | `Column` | `true`   |         | A column object to replace the named column. |

**Example:**

**SchemaBuilder**

```javascript
schema.alter( "users", function( table ) {
    table.modifyColumn( "name", table.string( "username" ) );
} );
```

**SQL (MySQL)**

```sql
ALTER TABLE `users` CHANGE `name` `username` VARCHAR(255) NOT NULL
```

### renameColumn

Rename a column on a table. A full `Column` instance is required as the second argument for Grammars that need to redeclare the column definition when renaming.

| Argument | Type     | Required | Default | Description                                              |
| -------- | -------- | -------- | ------- | -------------------------------------------------------- |
| name     | string   | `true`   |         | The current name of a column.                            |
| column   | `Column` | `true`   |         | A column object with the new column name and definition. |

**Example:**

**SchemaBuilder**

```javascript
schema.alter( "users", function( table ) {
    table.renameColumn( "name", table.string( "username" ) );
} );
```

**SQL (MySQL)**

```sql
ALTER TABLE `users` CHANGE `name` `username` VARCHAR(255) NOT NULL
```

### addConstraint

Add an index or key to an existing table. Any `TableIndex` instance is valid, like those created by the [index methods](broken://pages/-LA-U_axqzow_9OdzTRT) (`unique`, `index`, `primaryKey`, etc.).

| Argument   | Type         | Required | Default | Description                                    |
| ---------- | ------------ | -------- | ------- | ---------------------------------------------- |
| constraint | `TableIndex` | `true`   |         | The `TableIndex` instance to add to the table. |

**Example:**

**SchemaBuilder**

```javascript
schema.alter( "users", function( table ) {
    table.addConstraint( table.unique( "username" ) );
} );
```

**SQL (MySQL)**

```sql
ALTER TABLE `users` ADD CONSTRAINT `unq_users_username` UNIQUE (`username`)
```

### dropConstraint

Drop an existing table constraint.

| Argument | Type                   | Required | Default | Description                                                                                                               |
| -------- | ---------------------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------- |
| name     | string OR `TableIndex` | `true`   |         | The name of the constraint to drop. You can alternatively pass a `TableIndex` instance to use the dynamic name generated. |

**Example:**

**SchemaBuilder**

```javascript
schema.alter( "users", function( table ) {
    table.dropConstraint( "unq_users_full_name" );
    table.dropConstraint( table.unique( "username" ) );
} );
```

**SQL (MySQL)**

```sql
ALTER TABLE `users` DROP INDEX `unq_users_full_name`
ALTER TABLE `users` DROP INDEX `unq_users_username`
```

### dropIndex

Drop an existing index.

| Argument | Type                   | Required | Default | Description                                                                                                          |
| -------- | ---------------------- | -------- | ------- | -------------------------------------------------------------------------------------------------------------------- |
| name     | string OR `TableIndex` | `true`   |         | The name of the index to drop. You can alternatively pass a `TableIndex` instance to use the dynamic name generated. |

**Example:**

**SchemaBuilder**

```javascript
schema.alter( "users", function( table ) {
    table.dropIndex( "idx_username" );
    table.dropIndex( table.index( "username" ) );
} );
```

**SQL (MySQL)**

```sql
ALTER TABLE `users` DROP INDEX `idx_username`
ALTER TABLE `users` DROP INDEX `idx_users_username`
```

**SQL (SQL Server)**

```sql
DROP INDEX [users].[idx_username]
DROP INDEX [users].[idx_users_username]
```

### renameConstraint

Rename an existing table constraint.

| Argument | Type                   | Required | Default | Description                                                                                                                                |
| -------- | ---------------------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| oldName  | string OR `TableIndex` | `true`   |         | The old or current name of the constraint to rename. You can alternatively pass a `TableIndex` instance to use the dynamic name generated. |
| newName  | string OR `TableIndex` | `true`   |         | The new name of the constraint.  You can alternatively pass a `TableIndex` instance to use the dynamic name generated.                     |

**Example:**

**SchemaBuilder**

```javascript
schema.alter( "users", function( table ) {
    table.renameConstraint( "unq_users_first_name_last_name", "unq_users_full_name" );
} );
```

**SQL (MySQL)**

```sql
ALTER TABLE `users` RENAME INDEX `unq_users_first_name_last_name` TO `unq_users_full_name`
```

## renameTable

Rename an existing table.

| Argument | Type   | Required | Default | Description                                     |
| -------- | ------ | -------- | ------- | ----------------------------------------------- |
| oldName  | string | `true`   |         | The old or current name of the table to rename. |
| newName  | string | `true`   |         | The new name of the table.                      |

**Example:**

**SchemaBuilder**

```javascript
schema.renameTable( "workers", "employees" );
```

**SQL (MySQL)**

```sql
RENAME TABLE `workers` TO `employees`
```

## rename

An alias for `renameTable`.

| Argument | Type   | Required | Default | Description                                     |
| -------- | ------ | -------- | ------- | ----------------------------------------------- |
| oldName  | string | `true`   |         | The old or current name of the table to rename. |
| newName  | string | `true`   |         | The new name of the table.                      |

**Example:**

**SchemaBuilder**

```javascript
schema.rename( "workers", "employees" );
```

**SQL (MySQL)**

```sql
RENAME TABLE `workers` TO `employees`
```

## alterView

Shortcut method frop `dropView` and `createView` together.

| Argument | Type     | Required | Default | Description                                                                                            |
| -------- | -------- | -------- | ------- | ------------------------------------------------------------------------------------------------------ |
| view     | string   | `true`   |         | The name of the view to drop and create.                                                               |
| callback | function | `true`   |         | A callback function used to define the table body. It is passed a `QueryBuilder` as the only argument. |
| options  | struct   | `false`  | `{}`    | Options to pass to `queryExecute`.                                                                     |
| execute  | boolean  | `false`  | `true`  | Run the query immediately after building it.                                                           |


# Dropping Tables and Views

Dropping tables straightforward in `qb`.

> For dropping columns or constraints, see [Alter](/12.0.0/schema-builder/alter).

## drop

Drop a table from the database.

| Argument | Type    | Required | Default | Description                                  |
| -------- | ------- | -------- | ------- | -------------------------------------------- |
| table    | string  | `true`   |         | The name of the table to drop.               |
| options  | struct  | `false`  | `{}`    | Options to pass to `queryExecute`.           |
| execute  | boolean | `false`  | `true`  | Run the query immediately after building it. |

**Example:**

**SchemaBuilder**

```javascript
schema.drop( "user_logins" );
```

**SQL (MySQL)**

```sql
DROP TABLE `user_logins`
```

## dropIfExists

Drop a table from the database if it exists.

| Argument | Type    | Required | Default | Description                                  |
| -------- | ------- | -------- | ------- | -------------------------------------------- |
| table    | string  | `true`   |         | The name of the table to drop.               |
| options  | struct  | `false`  | `{}`    | Options to pass to `queryExecute`.           |
| execute  | boolean | `false`  | `true`  | Run the query immediately after building it. |

**Example:**

**SchemaBuilder**

```javascript
schema.dropIfExists( "user_logins" );
```

**SQL (MySQL)**

```sql
DROP TABLE IF EXISTS `user_logins`
```

## dropView

Drop a table from the database.

| Argument | Type    | Required | Default | Description                                  |
| -------- | ------- | -------- | ------- | -------------------------------------------- |
| view     | string  | `true`   |         | The name of the view to drop.                |
| options  | struct  | `false`  | `{}`    | Options to pass to `queryExecute`.           |
| execute  | boolean | `false`  | `true`  | Run the query immediately after building it. |

**Example:**

**SchemaBuilder**

```javascript
schema.view( "user_logins" );
```

**SQL (MySQL)**

```sql
DROP VIEW `user_logins`
```

## truncate

Truncates the data from a table.

| Argument | Type    | Required | Default | Description                                  |
| -------- | ------- | -------- | ------- | -------------------------------------------- |
| table    | string  | `true`   |         | The name of the table to truncate the data.  |
| options  | struct  | `false`  | `{}`    | Options to pass to `queryExecute`.           |
| execute  | boolean | `false`  | `true`  | Run the query immediately after building it. |

**Example:**

**SchemaBuilder**

```javascript
schema.truncate( "user_logins" );
```

**SQL (MySQL)**

```sql
TRUNCATE TABLE `user_logins`
```


# Debugging

### pretend

A `SchemaBuilder` instance can be put into pretend mode by calling the `pretend` method.  In this mode, the `SchemaBuilder` will turn all query operations into no-ops. A log of the SQL that would have been executed can be retrieved from the query log.

Once a `SchemaBuilder` instance has been set to pretend mode, it cannot be unset.  Instead, you will need to obtain a new `SchemaBuilder` instance.

### queryLog

Each instance of a `SchemaBuilder` maintains a log of queries it executed.  This can be accessed by calling `getQueryLog`. This will return an array of structs like so:

```json
[
  {
    "sql": "CREATE TABLE `users` (`id` INT PRIMARY KEY AUTO_INCREMENT, `email` VARCHAR NOT NULL)",
    "bindings": [],
    "options": { "datasource": "main" },
    "returnObject": "array",
    "pretend": false,
    "result": {},
    "executionTime": 21
  }
]
```

This can be very useful in combination with the [`pretend`](#pretend) feature to see what SQL will be executed before actually executing it.


# Introduction

## Introduction

qb is a fluent query builder for CFML. It is **heavily** inspired by [Eloquent](https://laravel.com/docs/5.3/eloquent) from [Laravel](https://laravel.com/).

Using qb, you can:

* Quickly scaffold simple queries
* Make complex, out-of-order queries possible
* Abstract away differences between database engines

## Requirements

* Adobe ColdFusion 2018+
* Lucee 5+

qb supports four major database grammars:

* MySQL (`MySQLGrammar@qb`)
* Oracle (`OracleGrammar@qb`)
* Postgres (`PostgresGrammar@qb`)
* Microsoft SQL Server (`SqlServerGrammar@qb`)
* SQLite (`SQLiteGrammar@qb`)

### Discussion & Help

The Box modules discussion group and community can be found here:

<https://community.ortussolutions.com/c/box-modules/qb/27>

## Installation

Installation is easy through [CommandBox](https://www.ortussolutions.com/products/commandbox) and [ForgeBox](https://www.coldbox.org/forgebox). Simply type `box install qb` to get started.

## Code Samples

Compare these two examples:

```cfscript
// Plain old CFML
var results = queryExecute( "SELECT * FROM users" );

// qb
var qb = wirebox.getInstance( "QueryBuilder@qb" );
var results = qb.from( "users" ).get();
```

The differences become even more stark when we introduce more complexity:

```cfscript
// Plain old CFML
var results = queryExecute(
    "SELECT * FROM posts WHERE published_at IS NOT NULL AND author_id IN ?",
    [ { value = "5,10,27", cfsqltype = "CF_SQL_NUMERIC", list = true } ]
);

// qb
var qb = wirebox.getInstance( "QueryBuilder@qb" );
var results = qb.from( "posts" )
    .whereNotNull( "published_at" )
    .whereIn( "author_id", [ 5, 10, 27 ] )
    .get();
```

With qb you can easily handle setting order by statements before the columns you want or join statements after a where clause:

```cfscript
var qb = wirebox.getInstance( "QueryBuilder@qb" );
var results = qb.from( "posts" )
         .orderBy( "published_at" )
         .select( "post_id", "author_id", "title", "body" )
         .whereLike( "author", "Ja%" )
         .join( "authors", "authors.id", "=", "posts.author_id" )
         .get();

// Becomes
var results = queryExecute(
    "SELECT post_id, author_id, title, body FROM posts INNER JOIN authors ON authors.id = posts.author_id WHERE author LIKE ? ORDER BY published_at",
    [ { value = "Ja%", cfsqltype = "CF_SQL_VARCHAR", list = false, null = false } ]
);
```

qb enables you to explore new ways of organizing your code by letting you pass around a query builder object that will compile down to the right SQL without you having to keep track of the order, whitespace, or other SQL gotchas!

Here's a gist with an example of the powerful models you can create with this! <https://gist.github.com/elpete/80d641b98025f16059f6476561d88202>

## Usage

To start a new query, instantiate a new Builder: `wirebox.getInstance( "QueryBuilder@qb" )`.

By default, qb uses a generic Grammar. You can specify your specific grammar in ColdBox by setting the `defaultGrammar` in your `moduleSettings`.

```cfscript
moduleSettings = {
    qb = {
        defaultGrammar = "MySQLGrammar@qb"
    }
};
```

If you are not using WireBox, just make sure to wire up the `Builder` object with the correct grammar:

```cfscript
var grammar = new qb.models.Query.Grammars.MySQLGrammar();
var builder = new qb.models.Query.Builder( grammar );
```


# What's New?

## 11.1.0

**QueryBuilder:** Support JOINS in DELETE statements for supported grammars, like MySQL and SQL Server.

## 11.0.3

**QueryBuilder:** Don't overly specify that grammars must extend `BaseGrammar`. It's just an implicit interface, after all.

## 11.0.2

**QueryBuilder:** Have aliases work with full server qualifications, like `ServerName.schemaName.tableName`.

## 11.0.1

### Allow for disabling of wrapping values

Either a Grammar setting (`setShouldWrapValues( true|false )`) or for a one-off Query Builder ([`withoutWrappingValues()`](/11.1.0/query-builder/options-and-utilities/query-options#withoutwrappingvalues) / [`withWrappingValues()`](/11.1.0/query-builder/options-and-utilities/query-options#withwrappingvalues)) can control whether identifiers like table names, columns, etc. are wrapped.

### BoxLang Compatibility

This release includes updates to be compatible with the latest releases of BoxLang.

## 11.0.0

### Auto Boolean Casting

Grammars will be able to influence the `cfsqltype` and value when passing in a literal boolean value as a binding. Postgres and SQLite have boolean support, so they will keep the literal boolean value and use a `cfsqltype` of `CF_SQL_OTHER`. SQL Server uses `CF_SQL_BIT`, Oracle users `CF_SQL_NUMERIC`, and MySQL uses `CF_SQL_TINYINT` — all of these will convert literal boolean values to either 1 or 0. This behavior is skipped when providing a custom `cfsqltype`.

{% hint style="info" %}
Custom grammars can implement the `getBooleanSqlType` and `convertBooleanValue` methods to customize this behavior.
{% endhint %}

{% hint style="danger" %}
Additionally, attempting to change the grammar with any bindings currently configured will throw an exception. This is because the bindings are converted via the grammar when added to the builder and cannot be changed retroactively when setting a new grammar. Set the grammar first before configuring the query to avoid this exception.
{% endhint %}

## 10.0.2

**QueryUtils:** Fix timestamp formatting losing timezone information

## 10.0.1

**QueryUtils:** Manually construct ISO 8601 timestamps due to lack of Adobe support

## 10.0.0

* Full compatibility for running on [BoxLang](https://boxlang.io/) with the [`bx-compat-cfml`](https://forgebox.io/view/bx-compat-cfml) module.
* Internal property name changes for BoxLang compatibility as well as cleaner code. (This *may* cause breaking changes, in rare cases.  See the [Migration Guide](https://qb.ortusbooks.com/11.1.0/pages/-LA-U_b2vfkZD-h5AIUm#v10.0.0) for more details.)

## 9.8.1

* Fix missing `parseNumber` function for ACF
* Add alias to `clone()`

## 9.8.0

Support alias renaming using [`withAlias`](/11.1.0/query-builder/building-queries/from#withalias)&#x20;

## 9.7.1

Add in missing join compilations.

## 9.7.0

Implement [crossApply](/11.1.0/query-builder/building-queries/joins#crossapply) and [outerApply](/11.1.0/query-builder/building-queries/joins#outerapply) for supported Grammars

## 9.6.1

Expand type annotation for `from`. This can be a string or an Expression.

## 9.6.0

Make [`addBindings`](/11.1.0/query-builder/building-queries/parameters-and-bindings#addbindings) and [`addBindingsFromBuilder`](/11.1.0/query-builder/building-queries/parameters-and-bindings#addbindingsfrombuilder) publicly accessible.

## 9.5.1

Add MariaDB support to `AutoDiscover@qb` grammar. (It will choose the `MySQLGrammar@qb`.)

## 9.5.0

Add [`findOrFail`](/11.1.0/query-builder/executing-queries/retrieving-results#findorfail) and [`existsOrFail`](/11.1.0/query-builder/executing-queries/aggregates#existsorfail) methods, inspired by [Quick](https://quick.ortusbooks.com).

## 9.4.1

Better Support for OracleGrammar in SchemaBuilder

* Fix trigger creation by escaping colons (`:`).
* Try to drop associated sequences and triggers when dropping a table.
* Better support for creating a table in a different schema by only checking for the last identifier as the table name in [`hasTable`](/11.1.0/schema-builder/schema-builder#hastable) and [`hasColumn`](/11.1.0/schema-builder/schema-builder#hascolumn).

## 9.4.0

Allow for setting a [`defaultSchema`](/11.1.0/schema-builder/schema-builder) property on a `SchemaBuilder` instance.

The `defaultSchema` will be used for methods like [`hasTable`](/11.1.0/schema-builder/schema-builder#hastable) and [`hasColumn`](/11.1.0/schema-builder/schema-builder#hascolumn). A passed in `schema` will still take precedence.

## 9.3.1

* Use `CHAR` for `GUID` and `UUID` types in MySQL.
* Don't call `getUtils` from inside `QueryUtils`.

## 9.3.0

Make [`replaceBindings`](/11.1.0/query-builder/options-and-utilities/query-options#replacing-or-inlining-bindings) publicly available in `QueryUtils`.

This is used by qb to inline query bindings in `toSQL` or `dump` calls and can be used to inline the bindings in other tools like[ CommandBox Migrations](https://forgebox.io/view/commandbox-migrations).

## 9.2.5

Use named parameters when passing to `BaseGrammar`. This avoids problems where custom Grammars have extra arguments and we add arguments to the official grammar.

## 9.2.4

{% hint style="info" %}
We apologize for the new features in a patch release.
{% endhint %}

#### New Features

* Add the ability to pretend to run queries, both in [QueryBuilder](/11.1.0/query-builder/debugging#pretend) and [SchemaBuilder](/11.1.0/schema-builder/debugging#pretend).
* Add query logging to [QueryBuilder](/11.1.0/query-builder/debugging#querylog) and [SchemaBuilder](/11.1.0/schema-builder/debugging#querylog) instances.

#### Bug Fixes

* Use varchar for clob when converting to a CFML query. This is used when removing a column like in Oracle pagination.

## 9.2.3

Handle more numeric SQL types like `AtomicInteger` and `Long`.

## 9.2.2

Add millisecond accuracy to inline bindings.

## 9.2.1

Separate `having` bindings from `where` bindings.

## 9.2.0

### New Features

We now support the `returning` function inside `update` and `delete` statements for supported Grammars.  Supported grammars are SQL Server, Postgres, and SQLite.

### Bug Fixes

* Fix raw table name parsing in update queries for `SqlServerGrammar`.
* Fix truncating text in nested wheres inside joins.
* Fix out of order bindings in joinSub

## 9.1.5

Switch from `table_catalog` to `table_schema` when referencing schema for `PostgresGrammar`.

## 9.1.4

CommandBox-friendly injections for SQL Commenter.

## 9.1.3

Add support for `from` bindings, used especially in `fromSub` queries.

## 9.1.2

This release reverts the use of native `returntype`s.  There are too many bugs between engine implementations to make it viable.  No end-user changes should be visible.

## 9.1.1

Make `withReturnFormat` a public method.

## 9.1.0

### New Features

Add ability to inline bindings when calling `toSQL` and `dump`. These strings can be executed in a DBMS application.

### Bug Fixes

* Move `coldbox` namespace injection to the function body so CommandBox doesn't blow up.
* Correctly apply native returntypes after `newQuery` and `withReturnFormat`.

## 9.0.2

* Fix losing `defaultOptions` when calling `newQuery`.
* Shortcut for no return format using `none`.
* Allow for native struct returntypes. Requires a return format of `none`.

## 9.0.1

Fix `RouteInfoCommenter` file name.

## 9.0.0

### Breaking Changes

#### Dropped support for Adobe ColdFusion 2016

Adobe has ended support for ACF 2016, and so must we.

#### SchemaBuilder's `uuid` split into [guid()](/11.1.0/schema-builder/columns#guid) and [uuid()](/11.1.0/schema-builder/columns#uuid)

CFML's `uuid` does not match other languages; it's one character shorter. Because of this, the value from `createUUID()` cannot be used in some database column types like SQL Server's `uniqueidentifier`. This made for some confusion in SchemaBuilder since it wasn't clear if `uuid` meant CFML's definition or the wider world's definition.

So, the types have been split, following Lucee's pattern, into [`uuid`](/11.1.0/schema-builder/columns#uuid) (matching CFML's [`createUUID()`](https://cfdocs.org/createuuid)) and [`guid`](/11.1.0/schema-builder/columns#guid) (matching Java's UUID or [`createGUID()`](https://cfdocs.org/createguid) on Lucee).

#### Returning all rows from [paginate](/11.1.0/query-builder/executing-queries/retrieving-results#paginate) when maxRows is  0 or lower

Popular grid frameworks like Quasar and Datatables use values of 0 or -1 to return all rows from a query. This is now supported in qb. Previously, it generated an invalid query (`SELECT * FROM users LIMIT 0 OFFSET 0`).

This behavior can be customized by providing a callback to the `shouldMaxRowsOverrideToAll` setting or `init` argument. For instance, to revert to the previous behavior you would set the function as follows:

```cfscript
moduleSettings = {
    "qb": {
        "shouldMaxRowsOverrideToAll": function( maxRows ) {
            return false;
        }
    }
};
```

#### [`autoDeriveNumericType`](/11.1.0/query-builder/building-queries/parameters-and-bindings#numeric-sql-type) is now the default

Introduced in [8.10.0](#8.10.0), this feature uses separate SQL types for integers and decimals to increase performance in certain database grammars.  This feature is now the default, but the previous behavior can be enabled by setting `autoDeriveNumericType` to `false`.

{% hint style="warning" %}
**Note:** the option to revert to the old behavior will be removed in the next major version.
{% endhint %}

#### [`strictDateDetection`](/11.1.0/query-builder/building-queries/parameters-and-bindings#strict-date-detection) is now the default

Introduced in [8.1.0](#8.1.0), this feature only returns a SQL type of `CF_SQL_TIMESTAMP` if the param is a date object, not just a string that looks like a date.  This helps avoid situations where some strings were incorrectly interpreted as dates.  For many, the migration path is straightforward — calls to [`now()`](https://cfdocs.org/now) are already date objects as well as any function that operates on a date.  If you need to parse a string as a date, the [`parseDateTime`](https://cfdocs.org/parsedatetime) built-in function can accomplish that.

{% hint style="warning" %}
**Note:** the option to revert to the old behavior **may** be removed in the next major version.
{% endhint %}

### New Features and Improvements

#### SQLite Grammar Support

Thanks to [Jason Steinhouer](https://github.com/jsteinshouer), qb now supports SQLite for both `QueryBuilder` and `SchemaBuilder`.  You can use it in your apps by specifying `SQLiteGrammar@qb` as the default grammar.

#### [sqlCommenter Support](/11.1.0/query-builder/debugging/sqlcommenter)

sqlCommenter is a [specification by Google](https://google.github.io/sqlcommenter/) for adding contextual information as a comment at the end of a SQL statement.  This can give insights into your application, especially when diagnosing slow queries. Examples of the information you can append to your queries are `route`, `handler`, `action`, `version`, and others, as well as the ability to add your own, such as `loggedInUser` and more.

#### [sumRaw](/11.1.0/query-builder/executing-queries/aggregates#sumraw) helper function

There's a new shortcut method to return `qb.sum( qb.raw( expression ) )`. You're welcome. 😉

#### Dedicated [`dropIndex`](/11.1.0/schema-builder/alter#dropindex) method

Some grammars, like SQL Server, do not treat simple indexes as constraints.  For this reason, we've added a [`dropIndex`](/11.1.0/schema-builder/alter#dropindex) method alongside the existing [`dropConstraint`](/11.1.0/schema-builder/alter#dropconstraint).

#### [`columnList`](/11.1.0/query-builder/executing-queries/aggregates#columnlist) helper method

[`columnList`](/11.1.0/query-builder/executing-queries/aggregates#columnlist) will return either an array of column names for the configured table or the query that is generated by `cfdbinfo` for the configured table.  Especially useful when working with dynamically generated grids.&#x20;

### Bug Fixes

* Correctly compile `insertUsing` statements that use Common Table Expressions (CTEs).
* Update `announceInterception` calls for ColdBox 7. (Thank you, Michael Born.)
* Fixed `insertUsing` not placing Common Table Expressions (CTEs) in the correct order.
* Added the missing keyword in the Postgres [`upsert`](/11.1.0/query-builder/executing-queries/inserts-updates-deletes#upsert) syntax.
* Don't add `DISTINCT` when doing a `COUNT(*)`.
* Support aggregates for unioned queries.

## 8.10.0

* Add a [`firstOrFail`](/11.1.0/query-builder/executing-queries/retrieving-results#firstorfail) fetch method inspired by [Quick](https://quick.ortusbooks.com).
* There are now [specific numeric SQL types for integers and decimals](/11.1.0/query-builder/building-queries/parameters-and-bindings#numeric-sql-type) used during the `inferSQLType` check in `QueryUtils`.  This is an opt-in feature, enabled by setting the `autoDeriveNumericType` setting. The previous approach was to use `CF_SQL_NUMERIC` for all numeric types which could cause performance issues in some grammars as they interpreted all `CF_SQL_NUMERIC` as floating point numbers.

## 8.9.1

* `HOLDLOCK` and `READPAST` are mutually exclusive table locks in SQL Server but were mistakenly being applied together.

## 8.9.0

* Specify `defaultOptions` [inside of your ColdBox config.](/11.1.0/query-builder/options-and-utilities/query-options)

## 8.8.1

* Better parsing of `raw` statements when deriving [`insertUsing`](/11.1.0/query-builder/executing-queries/inserts-updates-deletes#insertusing) columns.

## 8.8.0

### New Features and Improvements

* Insert data based off of a callback or builder using [`insertUsing`](/11.1.0/query-builder/executing-queries/inserts-updates-deletes#insertusing).
* Insert data ignoring duplicate key errors using [`insertIgnore`](/11.1.0/query-builder/executing-queries/inserts-updates-deletes#insertignore).
* Use a callback or builder as the source for an [`upsert`](/11.1.0/query-builder/executing-queries/inserts-updates-deletes#upsert) statement.
* Allow for deleting unmatched source records in [upserts](/11.1.0/query-builder/executing-queries/inserts-updates-deletes#upsert) (SQL Server only).
* Add a new `skipLocked` flag to [`lockForUpdate`](/11.1.0/query-builder/building-queries/locks#lockforupdate).

### Bug Fixes

* Don't uppercase quoted aliases in Oracle.
* Fix for aliases in update statements.
* Don't sort columns for `insertUsing`.
* Add subquery bindings in insert and upsert statements.
* Maintain column order when using source in upsert.

## 8.7.8

* Fix for Oracle returning custom column types when renaming a column.

## 8.7.7

* Explicit arguments scoping.

## 8.7.6

* `arrayEach` is slow compared to merging arrays.

## 8.7.5

* Fix wheres with joins in update statements.

## 8.7.2

* Add better null handling to `inferSqlType`.

## 8.7.1

* Correctly format columns being updated.

## 8.7.0

### New Features and Improvements

* Add an [upsert](/11.1.0/query-builder/executing-queries/inserts-updates-deletes#upsert) method.  `upsert` can update or insert multiple records at once depending on if a column is matched.
* Allow expressions in [`value`](/11.1.0/query-builder/executing-queries/retrieving-results#value) and [`values`](/11.1.0/query-builder/executing-queries/retrieving-results#values).  Also add a [`valueRaw`](/11.1.0/query-builder/executing-queries/retrieving-results#valueraw) and [`valuesRaw`](/11.1.0/query-builder/executing-queries/retrieving-results#valuesraw) helper method to make that pattern more ergonomic.
* Allow [`JOIN` statements in `UPDATE` statements](/11.1.0/query-builder/executing-queries/inserts-updates-deletes#updating-with-joins).  (This is **not** supported on Oracle.)
* Allow [updates with subselects](/11.1.0/query-builder/executing-queries/inserts-updates-deletes#updating-with-subselects) using closures or builder instances.

### Bug Fixes

* Better handling of [`group by`](/11.1.0/query-builder/building-queries/group-by-and-having#groupby) and [`having`](/11.1.0/query-builder/building-queries/group-by-and-having#having) clauses in [pagination](/11.1.0/query-builder/building-queries/limit-offset-and-pagination#simplepaginate-and-paginate) queries.
* Allow any value to be returned from [aggregates](/11.1.0/query-builder/executing-queries/aggregates) including strings, numbers, and dates.
* Provide default values for [sum](/11.1.0/query-builder/executing-queries/aggregates#sum) and [count](/11.1.0/query-builder/executing-queries/aggregates#count) if no records are returned.
* Test in CI with [full](https://coldfusion.adobe.com/2018/07/null-support-in-coldfusion-2018/) [null](https://docs.lucee.org/guides/cookbooks/NullSupport.html) support.

## 8.6.1

* Correctly wrap CTE expressions with parenthesis when required in certain grammars.

## 8.6.0

* `SchemaBuilder` can now be configured with [default query options](/11.1.0/schema-builder/schema-builder).  (Default options will still be overridden by options passed to each `SchemaBuilder` method.)

## 8.5.0

### QueryBuilder

* Add a [`reset`](/11.1.0/query-builder/options-and-utilities/clone-and-reset#reset) method to QueryBuilder.
* Add [locking](/11.1.0/query-builder/building-queries/locks) helpers such as [`lock`](/11.1.0/query-builder/building-queries/locks#lock), [`noLock`](/11.1.0/query-builder/building-queries/locks#nolock), [`lockForUpdate`](/11.1.0/query-builder/building-queries/locks#lockforupdate), and [`sharedLock`](/11.1.0/query-builder/building-queries/locks#sharedlock).
* Correct return aggregate values for date values from `max` and `min` executors.
* [Automatically add a `scale`](/11.1.0/query-builder/building-queries/parameters-and-bindings#automatic-scale-detection) to an incoming query param when needed.
* Add a [`whereNotLike`](/11.1.0/query-builder/building-queries/wheres#wherenotlike) shortcut method.
* Correctly format a `COUNT(DISTINCT column)` query.
* Only use bulk insert syntax when needed in OracleGrammar due to interactions between the `result` parameter to `cfquery`, Lucee, and the Oracle JDBC driver.

### SchemaBuilder

* Add support for [stored computed columns](/11.1.0/schema-builder/column-modifiers#storedas) and [virtual computed columns](/11.1.0/schema-builder/column-modifiers#virtualas).

## 8.4.9

* Swap `master` branch to `main` branch.

## 8.4.8

* Remove unnecessary injection for QueryUtils.

## 8.4.7

* Account for raw expressions when generating mementos for comparison

## 8.4.6

* Add support for [mediumtext](/11.1.0/schema-builder/columns#mediumtext) & [longtext](/11.1.0/schema-builder/columns#longtext) types for MySQLGrammar.

## 8.4.5

* Fix limit on [simplePaginate](/11.1.0/query-builder/executing-queries/retrieving-results#simplepaginate).

## 8.4.1 - 8.4.4

* Migrate release process to GitHub Actions.

## 8.4.0

* Add a `simplePaginate` pagination method for quicker performance when total records or total pages are not needed or too slow.

## 8.3.0

* Introduce a [`numericSQLType`](/11.1.0/query-builder/building-queries/parameters-and-bindings#numeric-sql-type) setting to specify the default numeric SQL type.

## 8.2.2

* Default to `html` for the `dump` format argument to `writeDump`.

## 8.2.1

* Correctly use the passed in `strictDateDetection` to the `QueryUtils.cfc`.

## 8.2.0

{% hint style="success" %}
📹 [Watch a walkthrough of this change on CFCasts.](https://cfcasts.com/series/whats-new-in-qb-8)
{% endhint %}

* Added a [`dump`](/11.1.0/query-builder/debugging#dump) command to aid in debugging a query while chaining.

## 8.1.0

{% hint style="success" %}
📹 [Watch a walkthrough of these changes on CFCasts.](https://cfcasts.com/series/whats-new-in-qb-8)
{% endhint %}

* [`orderByRaw`](/11.1.0/query-builder/building-queries/ordering-grouping-and-limit#order-by-raw) now can accept bindings.
* A new, optional [`strictDateDetection`](/11.1.0/query-builder/building-queries/parameters-and-bindings#strict-date-detection) setting is available to check the underlying Java class of a date object instead of using `isDate`.

## 8.0.3

* Ignore select bindings for aggregate queries.
* Allow spaces in table aliases.
* Split FLOAT and DECIMAL column types in SQL Server.

## 8.0.2

* Clear orderBy bindings when calling `clearOrders`.

## 8.0.1

* Trim table definitions before searching for aliases.  Makes qb more lenient with extra whitespace.

## 8.0.0

{% hint style="success" %}
📹 [Watch a walkthrough of these changes on CFCasts.](https://cfcasts.com/series/whats-new-in-qb-8)
{% endhint %}

#### BREAKING CHANGES

* \`\`[`when`](/11.1.0/query-builder/building-queries/when#when) callbacks now automatically scope and group where clauses when an `OR` combinator is used.

#### Other Changes

* Combine [`clearOrders`](/11.1.0/query-builder/building-queries/ordering-grouping-and-limit#clearorders) and `orderBy` with a new [`reorder`](/11.1.0/query-builder/building-queries/ordering-grouping-and-limit#reorder)method.
* Clear current selected columns with [`clearSelect`](/11.1.0/query-builder/building-queries/selects#clearselect).
* Combine [`clearSelect`](/11.1.0/query-builder/building-queries/selects#clearselect) and either [`select`](/11.1.0/query-builder/building-queries/selects#get) or [`selectRaw`](/11.1.0/query-builder/building-queries/selects#get-3) with [`reselect`](/11.1.0/query-builder/building-queries/selects#reselect) and [`reselectRaw`](/11.1.0/query-builder/building-queries/selects#reselectraw) respectively.

## 7.10.0

* Expose nested where functions to enable advanced query manipulation in downstream libraries like Quick.

## 7.9.9

* Fixes for OracleGrammar including table aliases and wrapped subqueries.

## 7.9.8

* Allow nullable [timestamps](/11.1.0/schema-builder/columns#timestamp) in MySQL.

## 7.9.7

* Return 0 on null [aggregates](/11.1.0/query-builder/executing-queries/aggregates).

## 7.9.6

* Match type hints to documentation for [join](/11.1.0/query-builder/building-queries/joins) functions

## 7.9.5

* Handle enhanced numeric checks with Secure Profile enabled.

## 7.9.4

* Allow raw statements in basic where clauses.

## 7.9.3

* Passed along the options struct to the [`count`](/11.1.0/query-builder/executing-queries/aggregates#count) method when calling [`paginate`](/11.1.0/query-builder/building-queries/limit-offset-and-pagination#paginate).

## 7.9.2

* Allow for space-delimited [sort](/11.1.0/query-builder/building-queries/ordering-grouping-and-limit) directions like `column DESC`.
* Add helpful message when trying to use a closure with [`from`](/11.1.0/query-builder/building-queries/from#get) instead of [`fromSub`](/11.1.0/query-builder/building-queries/from#get-3).
* \`\`[`value`](/11.1.0/query-builder/executing-queries/retrieving-results#value) and [`values`](/11.1.0/query-builder/executing-queries/retrieving-results#values) now work with [column formatters.](/11.1.0/query-builder/options-and-utilities/column-formatter)
* Correctly format RETURNING clauses with [column formatters](/11.1.0/query-builder/options-and-utilities/column-formatter) and ignoring table qualifiers.

## 7.9.1

* Handle multi-word columns in `queryRemoveColumns`.

## 7.9.0

* Remove elvis operator due to ACF compatibility issues

## 7.8.0

* Add support for [MONEY](/11.1.0/schema-builder/columns#money) and [SMALLMONEY](/11.1.0/schema-builder/columns#smallmoney) data types to [SchemaBuilder](/11.1.0/schema-builder/create).

## 7.7.3

* Fix wrapping of [enum](/11.1.0/schema-builder/columns#enum) types for Postgres.

## 7.7.2

* Compatibility fix for ACF 2018 and `listLast` parsing.
* Include current\_timestamp default for [`timestamp`](/11.1.0/schema-builder/columns#timestamp) columns in SchemaBuilder.
* Ignore table qualifiers for insert and update.

## 7.7.1

* Fix a bug with preventDuplicateJoins when using the closure syntax with a join.

## 7.7.0

* Add executionTime to the data output from BaseGrammar, including being available in interceptors.

## 7.6.2

* Fix a case where a column was not wrapped correctly when a `where` used a subquery for the value.

## 7.6.1

* Avoid `duplicate` function due to cbORM / Hibernate bugs when used in the same application.

## 7.6.0

* Split off a private `whereBasic` method.  This is used in Quick to provide extra sql type features.
* Add a [`clearOrders`](/11.1.0/query-builder/building-queries/ordering-grouping-and-limit#clearorders) method.  Any already configured orders are cleared.  Any orders added after this call will be added as normal.
* [`selectRaw`](/11.1.0/query-builder/building-queries/selects#get-3) now can take an array of expressions.

## 7.5.1

Fixed an issue using column formatters with `update` and `insert`.

## 7.5.0

Using a new `preventDuplicateJoins` setting in the module settings, qb can detect duplicate joins and ignore them. This is especially useful in a heavily filtered and dynamic query where you may or may not need the join at all or more than one column may need the same join. `preventDuplicateJoins` defaults to `false`, so it is opt-in. It may be turned on by default in a future breaking release of qb.

## 7.4.0

Enhance order by's with more direction options ([c767ac8](https://github.com/coldbox-modules/qb/commit/c767ac8764fab70d70dc77baa7bb9fb27c1d4eeb))

You can now use two shortcut methods: `orderByAsc` and `orderByDesc`. Additionally, `orderBySub` or using `orderBy` with a closure or builder instance will respect the direction argument.

## 7.3.15

* Fix using `whereBetween` with query param structs ([07c9b72](https://github.com/coldbox-modules/qb/commit/07c9b728bdbad6bf02ccd9d21dbdf6968062c02e))

## 7.3.14

* Ignore orders in aggregate queries ([39e1338](https://github.com/coldbox-modules/qb/commit/39e1338a147838165e05225bd91ef7e6cde2319a))

## 7.3.13

* Format with cfformat ([dc2a9b6](https://github.com/coldbox-modules/qb/commit/dc2a9b61503690d753a71c3b7bce002ebdf4ccda))

## 7.3.12

* Improve column wrapping with trimming ([d98a5cb](https://github.com/coldbox-modules/qb/commit/d98a5cb65851c154b6755e90254d1a2c1df82833))
* Prefer the parent query over magic methods when the parent query has the exact method. ([f9fd8d1](https://github.com/coldbox-modules/qb/commit/f9fd8d157cdc0d7480811c4659c130ee1d58888f))

## 7.3.9, 7.3.10, 7.3.11

* Switch to using [ForgeBox Storage](https://commandbox.ortusbooks.com/forgebox-enterprise/storage#storing-package-binaries-on-forgebox).

## 7.3.8

* Allow passing query options in to paginate ([cdecfb3](https://github.com/coldbox-modules/qb/commit/cdecfb36f5acab87edd3a478c570f77d285df554))

## 7.3.7

* Fix for inserting null values directly ([1de27a6](https://github.com/coldbox-modules/qb/commit/1de27a697f65bfdeed63442ad66be47cd0d30344))

## 7.3.5, 7.3.6

* Use cfformat for automatic formatting ([119e434](https://github.com/coldbox-modules/qb/commit/119e434b307a2cc2323b857a214c20842cafbbd4))
* Add a type to the onMissingMethod exception ([90d1093](https://github.com/coldbox-modules/qb/commit/90d109312b2ea86c00db34020b12b5ab22bb377b))

## 7.3.4

* Correctly wrap [comments](/11.1.0/schema-builder/column-modifiers#comment) in `MySQLGrammar`.

## 7.3.2, 7.3.3

* Publish qb apidocs to [Ortus API Docs](https://apidocs.ortussolutions.com/#/coldbox-modules/qb/).

## 7.3.1

* Fix for null values breaking the new `checkIsActuallyNumeric` method in `QueryUtils`.

## 7.3.0

* Add a `parameterLimit` public property to `SqlServerGrammar`.  This property is used in Quick to split up eager loading to work around the 2100 param limit of SQL Server.

## 7.2.0

* Allow a [parent query](broken://pages/-LxZv7a5KIrwcD1HJyVa) to be set.  A parent query will receive any method calls that are not found on the Query Builder instance.  This is especially useful for instances like [Quick](https://quick.ortusbooks.com/) to allow Quick features like scopes to be available inside any closures.

## 7.1.0

* Lambdas (arrow functions) are now allowed wherever closures are allowed.
* Add an [`orderByRaw`](/11.1.0/query-builder/building-queries/ordering-grouping-and-limit#order-by-raw) method.
* Allow for fully-qualified column names (`table_name.column.name`) in the [`value`](/11.1.0/query-builder/executing-queries/retrieving-results#value) and [`values`](/11.1.0/query-builder/executing-queries/retrieving-results#values) methods.

## 7.0.0

#### **BREAKING CHANGES**

*Please see the* [*Migration Guide*](/11.1.0/migration-guide#v-7-0-0) *for more information on these changes.*

* Drop support for Lucee 4.5 and Adobe ColdFusion 11.
* `MSSQLGrammar` renamed to `SqlServerGrammar`
* Remove variadic parameters support in builder functions like `select`.
* The `defaultGrammar` mapping needs to be the full WireBox mapping, including the `@qb`, if needed.
  * For instance, `MSSQLGrammar` would become `MSSQLGrammar@qb`.
  * This will allow for other grammars to be more easily contributed via third party modules.
* The argument names of `forPage` changed to match the new `paginate` method.
* Add `defaultValue` and optional exception throwing to `value`. (This changed the argument order.)
* All methods that could conceivably take a subquery as well as a value now accept a closure or another builder instance to use as a subquery. (This changed the argument names in some instances.)

#### **Other Changes**

* Completely revamped documentation! (You're looking at it right now.)
* Add new flag to [`toSQL( showBindings = true )`](/11.1.0/query-builder/debugging#tosql) to replace question marks (`?`) with `cfqueryparam`-compatible structs for debugging.
* Preserve column case and order when converting a query to an array using the default `"array"` return format.
* Add a new [paginate](/11.1.0/query-builder/executing-queries/retrieving-results#paginate) method to generate a pagination struct alongside the results.  This can be customized using a custom [PaginationCollector](/11.1.0/query-builder/executing-queries/retrieving-results#custom-pagination-collectors).
* Allow raw values in [`insert`](/11.1.0/query-builder/executing-queries/inserts-updates-deletes#insert) calls.
* Allow [default `queryExecute` `options`](/11.1.0/query-builder/options-and-utilities/query-options#default-options) to be configure at a Query Builder level.  This also enables custom `QueryBuilders` a la [Hyper](https://www.forgebox.io/view/hyper).
* Add a [`whereLike`](/11.1.0/query-builder/building-queries/wheres#wherelike) method.
* Allow closures to be used in left and right joins.
* Provide an [`addUpdate`](/11.1.0/query-builder/executing-queries/inserts-updates-deletes#addupdate) method to programmatically build the `SET` clause of an update query.
* [Add a new `chunk` method](/11.1.0/query-builder/executing-queries/retrieving-results#chunking-results) to grab records from the database in small sets.
* Add `raw` in `alterTable` segments.
* Add `dropAllObjects` support for `SqlServerGrammar` and `OracleGrammar` to support `migrate fresh` from cfmigrations.
* Add a `renameTable` alias for `rename`.
* Remove default constraints when dropping columns with a default on `SqlServerGrammar`.
* Add more column types and column helpers to `SchemaBuilder`, including:
  * `datetimeTz`
  * `lineString`
  * `nullableTimestamps`
  * `point`
  * `polygon`
  * `softDeletes`
  * `softDeletesTz`
  * `timeTz`
  * `timestamps`
  * `timestampTz`
  * `timestampsTz`
  * `withCurrent`

\*\*\*\*

## 6.4.0

* [Allow Expressions (`query.raw`) in update statements.](/11.1.0/whats-new)


# Installation & Usage

## Installation

Installation is easy through [CommandBox](https://www.ortussolutions.com/products/commandbox) and [ForgeBox](https://www.forgebox.io/). Simply type `box install qb` to get started.

## Usage

To start a new query, instantiate a new Builder: `wirebox.getInstance('QueryBuilder@qb')`.

By default, qb uses a generic Grammar. You can specify your specific grammar in ColdBox by setting the `defaultGrammar` in your `moduleSettings`.

```cfscript
moduleSettings = {
    qb = {
        defaultGrammar = "MySQLGrammar@qb"
    }
};
```

The grammars provided by qb are:

* MySQLGrammar
* OracleGrammar
* PostgresGrammar
* SqlServerGrammar
* SQLiteGrammar

If you are not using WireBox, make sure to wire up the `Builder` object with the correct grammar:

```cfscript
var grammar = new qb.models.Grammars.MySQLGrammar();
var builder = new qb.models.Query.QueryBuilder( grammar );
```

## Configuration Settings

Here are the full configuration settings you can use in the module settings:

```javascript
moduleSettings = {

    qb : {
        "defaultGrammar": "AutoDiscover@qb",
        "defaultReturnFormat": "array",
        "preventDuplicateJoins": false,
        "strictDateDetection": true,
        "numericSQLType": "CF_SQL_NUMERIC",
        "integerSQLType": "CF_SQL_INTEGER",
        "decimalSQLType": "CF_SQL_DECIMAL",
        "autoAddScale": true,
        "autoDeriveNumericType": true,
        "defaultOptions": {},
        "sqlCommenter": {
            "enabled": false,
            "commenters": [
                { "class": "FrameworkCommenter@qb", "properties": {} },
                { "class": "RouteInfoCommenter@qb", "properties": {} },
                { "class": "DBInfoCommenter@qb", "properties": {} }
            ]
        },
        "shouldMaxRowsOverrideToAll": function( maxRows ) {
            return maxRows <= 0;
        }
    }

}
```

## SQL Type Inferral

QB binds all parameters by default and guesses the SQL type based on passed values. The default SQL type for numeric values is `CF_SQL_NUMERIC`, which is a floating point number, for the widest compatibility. This can cause performance problems with large recordsets in some database engines. You can provide a different default in `coldbox.cfc` if you wish to override this setting:

```cfscript
moduleSettings = {
    qb = {
        defaultGrammar = "MySQLGrammar@qb",
        numericSQLType = "CF_SQL_BIGINT"
    }
};
```

## Integrating With FW/1

> Note: These instructions assume a basic knowledge of FW/1, a working FW/1 application structure with qb installed in the `/subsystems` directory (manually or via CommandBox), and a database configured to run with your application.

### Wiring Up With DI/1

Once the application structure is setup, now we need to wire up qb to a bean factory using DI/1.

First we will add a mapping in `Application.cfc`.

```cfscript
this.mappings = {
    "/qb" = expandPath("./subsystems/qb")
};
```

Next we need to tell DI/1 where qb's components are and how to reference them for later use in the application. We can do so by defining the configuration settings in the `variables.framework.subsystems` struct in `Application.cfc`. The example below makes use of a load listener to declare each component instance and pass in any constructor arguments.

```cfscript
qb = {
  diLocations = "/qb/models",
  diConfig = {
    loadListener = function( di1 ) {
      di1.declare( "BaseGrammar" ).instanceOf( "qb.models.Query.Grammars.Grammar" ).done()
         .declare( "MySQLGrammar" ).instanceOf( "qb.models.Query.Grammars.MySQLGrammar" ).done()
         .declare( "QueryUtils" ).instanceOf( "qb.models.Query.QueryUtils" ).done()
         .declare( "QueryBuilder" ).instanceOf( "qb.models.Query.QueryBuilder" )
         .withOverrides({
            grammar = di1.getBean( "MySQLGrammar" ),
            utils = di1.getBean( "QueryUtils" ),
            returnFormat = "array"
         })
         .asTransient();
    }
  }
}
```

### Usage In Your FW/1 Application

Now that everything is configured, you can launch your application with CommandBox by entering `start` in the terminal or use whatever method you're accustomed to.

To access qb from your application's code, you can call on it by using `getBeanFactory()`.

```cfscript
// Create an instance of qb
builder = getBeanFactory( "qb" ).getBean( "QueryBuilder" );
// Query the database
posts = builder.from( "Posts" ).get();
posts = builder.from( "Posts" ).where( "IsDraft", "=", 0 ).get();
```

#### For further instructions on getting started with qb & FW/1, refer to [this blog post](http://tonyjunkes.com/blog/working-with-fw1-and-qb/).


# Migration Guide

## v10.0.0

### Dropped Support for Adobe Coldfusion 2018

### Internal variables renamed for compatibility with BoxLang and cleaner code in general

In certifying qb for BoxLang, we discovered that some of the way qb had worked for years was due to a lucky interaction between properties and functions sharing a name.  Both of these values are put into the `variables` scope, and the way qb shared some of these names like the `from` method as well as the `from` property only worked because of the way Lucee and ACF ordered defining the function and properties.  BoxLang is more strict in this regard and probably for the best.  You can probably imagine how setting `variables.from` inside a function called `from` would maybe work once and then cause a very strange bug when trying to call the `from` function internally again.  Because of these reasons, the following properties have had their names changed:

#### QueryBuilder

* `from` -> `tableName`

#### Column

* `nullable` -> `isNullable`
* `unique` -> `isUnique`
* `unsigned` -> `isUnsigned`
* `default` -> `defaultValue`
* `comment` -> `commentValue`
* `onUpdate` -> `onUpdateAction`
* `onDelete` -> `onDeleteAction`

The following functions have had their signatures updated:

#### BaseGrammar

* `compileFrom` -> `compileTableName( required QueryBuilder query, required any tableName )`

For the majority of users, this will not take any updates to their code to work with qb 10.  For users who have created a custom grammar, column type, or a custom QueryBuilder class, you will need to make sure you code uses the updated property names and functions.

## v9.0.0

### Dropped support for Adobe ColdFusion 2016

Adobe has ended support for ACF 2016, and so must we.

### SchemaBuilder's `uuid` split into [guid()](/11.1.0/schema-builder/columns#guid) and [uuid()](/11.1.0/schema-builder/columns#uuid)

CFML's `uuid` does not match other languages; it's one character shorter. Because of this, the value from `createUUID()` cannot be used in some database column types like SQL Server's `uniqueidentifier`. This made for some confusion in SchemaBuilder since it wasn't clear if `uuid` meant CFML's definition or the wider world's definition.

So, the types have been split, following Lucee's pattern, into [`uuid`](/11.1.0/schema-builder/columns#uuid) (matching CFML's [`createUUID()`](https://cfdocs.org/createuuid)) and [`guid`](/11.1.0/schema-builder/columns#guid) (matching Java's UUID or [`createGUID()`](https://cfdocs.org/createguid) on Lucee).

{% hint style="warning" %}
If you are using `uuid` with 36 character UUIDs or SQL Server's `uniqueidentifier` columns, please migrate your `uuid` calls to `guid`.
{% endhint %}

### Returning all rows from [paginate](/11.1.0/query-builder/executing-queries/retrieving-results#paginate) when maxRows is  0 or lower

Popular grid frameworks like Quasar and Datatables use values of 0 or -1 to return all rows from a query. This is now supported in qb. Previously, it generated an invalid query (`SELECT * FROM users LIMIT 0 OFFSET 0`).

{% hint style="success" %}
If this behavior is fine for your application, you don't need to change anything.
{% endhint %}

This behavior can be customized by providing a callback to the `shouldMaxRowsOverrideToAll` setting or `init` argument.&#x20;

{% hint style="danger" %}
If you need to revert to the previous behavior, provide the following as the `shouldMaxRowsOverrideToAll` setting:

```cfscript
moduleSettings = {
    "qb": {
        "shouldMaxRowsOverrideToAll": function( maxRows ) {
            return false;
        }
    }
};
```

{% endhint %}

### [`autoDeriveNumericType`](/11.1.0/query-builder/building-queries/parameters-and-bindings#numeric-sql-type) is now the default

Introduced in [8.10.0](#8.10.0), this feature uses separate SQL types for integers and decimals to increase performance in certain database grammars.  This feature is now the default, but the previous behavior can be enabled by setting `autoDeriveNumericType` to `false`.

{% hint style="success" %}
This behavior *should* be an improvement in most every case without any changes needed.
{% endhint %}

{% hint style="danger" %}
If you need to revert to the previous behavior, provide the following as the `autoDeriveNumericType` setting:

```cfscript
moduleSettings = {
    "qb": {
        "autoDeriveNumericType": false
    }
};
```

{% endhint %}

{% hint style="warning" %}
**Note:** The option to revert to the old behavior will be removed in the next major version.
{% endhint %}

#### [`strictDateDetection`](/11.1.0/query-builder/building-queries/parameters-and-bindings#strict-date-detection) is now the default

Introduced in [8.1.0](#8.1.0), this feature only returns a SQL type of `CF_SQL_TIMESTAMP` if the param is a date object, not just a string that looks like a date.  This helps avoid situations where some strings were incorrectly interpreted as dates.  For many, the migration path is straightforward — calls to [`now()`](https://cfdocs.org/now) are already date objects as well as any function that operates on a date.  If you need to parse a string as a date, the [`parseDateTime`](https://cfdocs.org/parsedatetime) built-in function can accomplish that.

{% hint style="warning" %}
If you are relying on qb treating any strings as dates you will need to parse them as actual date objects first. (You can do so using functions like [`parseDateTime`](https://cfdocs.org/parsedatetime).
{% endhint %}

{% hint style="danger" %}
If you need to revert to the previous behavior, provide the following as the `strictDateDetection` setting:

```cfscript
moduleSettings = {
    "qb": {
        "strictDateDetection": false
    }
};
```

{% endhint %}

{% hint style="warning" %}
**Note:** The option to revert to the old behavior **may** be removed in the next major version.
{% endhint %}

## v8.0.0

### Where clauses with an OR combinator are now automatically wrapped inside [`when`](/11.1.0/query-builder/building-queries/when#when) callbacks

This isn't a breaking change that will affect most people.  In fact, it will most likely improve your code.

Previously, when using the [`when`](/11.1.0/query-builder/building-queries/when#when) control flow function, you were fully responsible for the wrapping of your where statements.  For example, the following query:

```javascript
qb.from( "users" )
    .where( "active", 1 )
    .when( len( url.q ), function( q ) {
        q.where( "username", "LIKE", q & "%" )
            .orWhere( "email", "LIKE", q & "%" );   
    } );
```

Would generate the following SQL:

```sql
SELECT *
FROM "users"
WHERE "active" = ?
    AND "username" = ?
    OR "email" = ?
```

The problem with this statement is that the `OR` can short circuit the `active` check.

The fix is to wrap the `LIKE` statements in parenthesis.  This is done in qb using a function callback to `where`.

```javascript
qb.from( "users" )
    .where( "active", 1 )
    .where( function( q ) {
        q.where( "username", "LIKE", q & "%" )
            .orWhere( "email", "LIKE", q & "%" );
    } );
```

```sql
SELECT *
FROM "users"
WHERE "active" = ?
    AND (
        "username" = ?
        OR "email" = ?
    )
```

When using the `when` control flow function, it was easy to miss this.  This is because you are already in a closure - it looks the same as when using `where` to group the clauses.

In qb 8.0.0, `when` will automatically group added where clauses when needed.  That means our original example now produces the SQL we probably expected.

```javascript
// qb 8.0.0
qb.from( "users" )
    .where( "active", 1 )
    .when( len( url.q ), function( q ) {
        q.where( "username", "LIKE", q & "%" )
            .orWhere( "email", "LIKE", q & "%" );   
    } );
```

```sql
SELECT *
FROM "users"
WHERE "active" = ?
    AND (
        "username" = ?
        OR "email" = ?
    )
```

Grouping is not needed if there is no `OR` combinator.  In these cases no grouping is added.

```javascript
// qb 8.0.0
qb.from( "users" )
    .where( "active", 1 )
    .when( url.keyExists( "admin" ), function( q ) {
        q.where( "admin", 1 )
            .whereNotNull( "hireDate" );
    } );
```

```sql
SELECT *
FROM "users"
WHERE "active" = ?
    AND "admin" = ?
    AND "hireDate IS NOT NULL
```

If you had already wrapped your expression in a group inside the `when` callback, nothing changes.  Your code works as before.  The `OR` combinator check only works on the top most level of added where clauses.

```javascript
qb.from( "users" )
    .where( "active", 1 )
    .when( len( url.q ), function( q ) {
        q.where( function( q2 ) {
            q2.where( "username", "LIKE", q & "%" )
                .orWhere( "email", "LIKE", q & "%" );
        } );
    } );
```

```sql
SELECT *
FROM "users"
WHERE "active" = ?
    AND (
        "username" = ?
        OR "email" = ?
    )
```

Additionally, if you do not add any where clauses inside a `when` callback, nothing changes from qb 7.

The breaking change part is if you were relying on these statements residing at the same level without grouping.  In those cases, you may pass the `withoutScoping` flag to the `when` callback.

```javascript
// qb 8.0.0
qb.from( "users" )
    .where( "active", 1 )
    .when(
        condition = len( url.q ),
        onTrue = function( q ) {
            q.where( "username", "LIKE", q & "%" )
                .orWhere( "email", "LIKE", q & "%" );   
        },
        withoutScoping = true
    );
```

```sql
SELECT *
FROM "users"
WHERE "active" = ?
    AND "username" = ?
    OR "email" = ?
```

## v7.0.0

### Lucee 4.5 and Adobe ColdFusion 11 EOL

Support for Lucee 4.5 and Adobe ColdFusion 11 has been dropped. If you need support for these engines, please remain on an earlier version of qb.

### MSSQLGrammar renamed to SqlServerGrammar

`MSSQLGrammar` was visually too close to `MySQLGrammar` and was hard to differentiate quickly. `SqlServerGrammar` is much more unique and easily identifiable. Additionally, more people that use this library refer to their database engine as "SQL Server" than "MSSQL".

To migrate, replace any instances of `MSSQLGrammar` with `SqlServerGrammar`. Make sure to also append the `@qb` namespace, if needed, [as explained below.](/11.1.0/migration-guide#defaultgrammar-updated-to-be-the-full-wirebox-mapping)

### Variadic Parameters Support Removed

Variadic parameter support was the ability to pass any number of arguments to certain methods like `select`.

```javascript
qb.select( "name", "email", "createdDate" );
```

This code came with a slight performance cost and readability cost. That, combined with the fact that the above syntax is very close to an array, we are dropping support for variadic parameters. To migrate, wrap instances of variadic parameters in an array:

```javascript
qb.select( [ "name", "email", "createdDate" ] );
```

### defaultGrammar updated to be the full WireBox mapping

In previous versions, the value passed to `defaultGrammar` was used to look up a mapping in the `@qb` namespace. This made it difficult to add or use grammars that weren't part of qb. (You could get around this be registering your custom grammar in the `@qb` namespace, but doing so seemed strange.)

To migrate this code, change your `defaultGrammar` to be the full WireBox mapping in your `moduleSettings`:

```javascript
moduleSettings = {
    "qb": {
        "defaultGrammar": "MSSQLGrammar@qb"
    }
};
```

### value method argument order changed

A `defaultValue` parameter and optional exception throwing was added to `value`. This pushed the `options` struct to the end of the method. If you are using positional parameters with `value`, you will need to update your method calls to either use named parameters or the new positions.

```javascript
public any function value(
    required string column,
    string defaultValue = "",
    boolean throwWhenNotFound = false,
    struct options = {}
);
```

### Some methods renamed `callback` to `query`

All methods that could conceivably take a subquery as well as a value now accept a closure or another builder instance to use as a subquery. This led to changing the `callback` argument to `query` in the following cases:

* `whereSub`
* `whereInSub`
* `whereExists`
* `orWhereExists`
* `whereNotExists`
* `andWhereNotExists`
* `orWhereNotExists`
* `whereNullSub`
* `orderBySub`
* `subSelect`

If you are using named parameters with any of the above methods you will need to migrate your method calls.

## v5.0.0

Version `v5.0.0` brings support for `SchemaBuilder` inside `qb`. To avoid naming confusion, `Builder` was renamed to `QueryBuilder`. Any references in your code to `Builder@qb` need to be updated to `QueryBuilder@qb`.


# Contributing & Filing Issues

We welcome all types of contributions!

The most common type of contribution is to fix an incorrect SQL generation for a database grammar.

To debug what SQL is being ran, you can always call `toSQL` on any `QueryBuilder` or `SchemaBuilder` object. Additionally, you can listen to the `preQBExecute` interception point for the generated SQL.

Each of the database grammars have two tests — `{Grammar}QueryBuilderSpec.cfc` and `{Grammar}SchemaBuilderSpec.cfc`. These tests run the same qb syntax across the different grammars. In each test are methods that return SQL strings like so:

```javascript
// MSSQLQueryBuilderSpec.cfc
function orWhere() {
    // If just a string is returned, we assume the bindings is an empty array ([])
    return {
        sql = "SELECT * FROM [users] WHERE [id] = ? OR [email] = ?",
        bindings = [ 1, "foo" ]
    };
}
```

```javascript
// OracleSchemaBuilderSpec.cfc
function boolean() {
    // returns an array since schema builder can execute multiple statements.
    return [ "CREATE TABLE ""USERS"" (""ACTIVE"" NUMBER(1, 0) NOT NULL)" ];
}
```

If you find an issue with the SQL generated from a grammar, please file a pull request with the correct SQL in these tests. It's okay if you don't submit a fix as well. (But we'd greatly appreciate it!) Doing so will help expedite the fix.

If you want to add support for a new database grammar, simply copy these two tests from an existing grammar, rename them, change the `getBuilder` method to return your new grammar, and fill out the SQL as it should be. That will guide your implementation to be 100% compatible with the other grammars in qb.


# Getting a New Query

A query builder is a stateful, transient object. That means that if you want to execute two different queries, you need two separate instances of `QueryBuilder`.

{% code title="QueryBuilder" %}

```javascript
// This will cause you pain and grief...

var user = query.from( "users" )
  .where( "username", rc.username )
  .first();

var posts = query.from( "posts" ).get();
// This will error because `username` is not a column in `posts`.
```

{% endcode %}

As such, be careful when injecting QueryBuilder in to a component. If the component is a singleton, you will need to create the QueryBuilder inline or use a provider. This applies to ColdBox handlers as well.

{% code title="handlers/posts.cfc" %}

```javascript
component {

    property name="query" inject="QueryBuilder@qb";

    function create( event, rc, prc ) {
        // This will cause you pain and grief...
        query.table( "posts" )
            .where( "id", rc.id )
            .update( event.getOnly( [ "body" ] ) );
    }

}
```

{% endcode %}

While the above may seem innoculous, it can run in to issues as multiple requests come in to your application. Each request is sharing the same query builder instance and subsequent requests will have unintended results as the `where` clause keeps growing request after request.

The solution is to either create the QueryBuilder inline, ensuring that each request has its own query to execute:

{% code title="handlers/posts.cfc" %}

```javascript
component {

    function create( event, rc, prc ) {
        getInstance( "QueryBuilder@qb" )
            .table( "posts" )
            .where( "id", rc.id )
            .update( event.getOnly( [ "body" ] ) );
    }

}
```

{% endcode %}

Or to use a WireBox provider to create a new query each time it is accessed:

{% code title="handlers/posts.cfc" %}

```javascript
component {

    property name="query" inject="provider:QueryBuilder@qb";

    function create( event, rc, prc ) {
        query.table( "posts" )
            .where( "id", rc.id )
            .update( event.getOnly( [ "body" ] ) );
    }

}
```

{% endcode %}

{% hint style="warning" %}
One caveat when using a WireBox Provider: WireBox Providers proxy methods on to a new instance of the provided mapping on all methods except `get`. `get` is a method on the Provider itself. If you call `get` as the first method on a Provider it will return a new instance of QueryBuilder, not execute the query. In those (rare) cases you will need to call `query.get().get()`.
{% endhint %}

## newQuery

Once you have access to a QueryBuilder instance, you can create a new query using the same datasource, utils, returnFormat, paginationCollector, columnFormatter, and defaultOptions as the current QueryBuilder instance.

```javascript
// This will cause you pain and grief...

var user = query.from( "users" )
  .where( "username", rc.username )
  .first();

var posts = query.newQuery().from( "posts" ).get();
// This will work as we expect it to.
```


# Building Queries


# Selects

## Specifying A Select Clause

You may not always want to select all columns from a database table. You can influence the select list of a query with the following methods.

Individual columns can contain fully-qualified names (`some_table.some_column`), table aliases (`alias.some_column`), and even set column aliases themselves (`some_column AS c`). The `columns` argument can be a single column, a list of columns (comma-separated), or an array of columns.

## select <a href="#get" id="get"></a>

| Name    | Type            | Required | Default | Description                                                        |
| ------- | --------------- | -------- | ------- | ------------------------------------------------------------------ |
| columns | string \| array | `false`  | ​`"*"`  | A single column, list of columns, or array of columns to retrieve. |

When calling `select` any previous columns are discarded. If you want to incrementally select columns, use the `addSelect` method.

If you pass no columns to this method, it will default to `"*"`.

{% code title="QueryBuilder" %}

```javascript
query.select( [ "fname AS firstName", "age" ] ).from( "users" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT `fname` AS `firstName`, `age` FROM `users`
```

{% endcode %}

## distinct <a href="#get" id="get"></a>

| Name  | Type    | Required | Default | Description                     |
| ----- | ------- | -------- | ------- | ------------------------------- |
| state | boolean | `false`  | ​`true` | Value to set the distinct flag. |

Calling distinct will cause the query to be executed with the `DISTINCT` keyword.

{% code title="QueryBuilder" %}

```javascript
query.select( "username" ).distinct().from( "users" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT DISTINCT `username` FROM `users`
```

{% endcode %}

{% hint style="info" %}
`distinct` applies to the entire query, not just certain fields.
{% endhint %}

## addSelect <a href="#get" id="get"></a>

| Name    | Type            | Required | Default | Description                                                                 |
| ------- | --------------- | -------- | ------- | --------------------------------------------------------------------------- |
| columns | string \| array | `true`   | ​       | A single column, list of columns, or array of columns to add to the select. |

This method adds the columns passed to it to the currently selected columns.

{% hint style="warning" %}
If the `QueryBuilder` is currently selecting all columns (`"*"`) when this method is called, the incoming columns will becoming the only columns selected.
{% endhint %}

{% code title="QueryBuilder" %}

```javascript
query.addSelect( [ "fname AS firstName", "age" ] ).from( "users" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT `fname` AS `firstName`, `age` FROM `users`
```

{% endcode %}

## selectRaw <a href="#get" id="get"></a>

| Name       | Type  | Required | Default | Description                                  |
| ---------- | ----- | -------- | ------- | -------------------------------------------- |
| expression | any   | `true`   | ​       | The raw expression for the select statement. |
| bindings   | array | `false`  | `[]`    | Any bindings needed for the raw expression.  |

A shortcut to use a raw expression in the select clause.

The expression is added to the other already selected columns.

*(To learn more about raw and expressions, check out the docs on* [*Raw Expressions*](/11.1.0/query-builder/building-queries/raw-expressions)*.)*

{% code title="QueryBuilder" %}

```javascript
query.selectRaw( "YEAR(birthdate) AS birth_year" ).from( "users" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT YEAR(birthdate) AS birth_year FROM `users`
```

{% endcode %}

## subSelect <a href="#get" id="get"></a>

| Name  | Type                     | Required | Default | Description                                    |
| ----- | ------------------------ | -------- | ------- | ---------------------------------------------- |
| alias | string                   | `true`   | ​       | The alias for the subselect expression.        |
| query | Function \| QueryBuilder | `true`   |         | The callback or query to use in the subselect. |

The method lets you pass either a callback or a `QueryBuilder` instance to be used as a subselect expression. If a callback is passed it will be passed a new query instance as the only parameter.

The subselect is added to the other already selected columns.

{% code title="QueryBuilder" %}

```javascript
query.subSelect( "last_login_date", function( q ) {
    q.selectRaw( "MAX(created_date)" )
        .from( "logins" )
        .whereColumn( "users.id", "logins.user_id" );
} ) ).from( "users" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT (
    SELECT MAX(created_date)
    FROM `logins`
    WHERE `users`.`id` = `logins`.`user_id`
) AS `last_login_date`
FROM `users
```

{% endcode %}

## clearSelect <a href="#clearselect" id="clearselect"></a>

| Name         | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      | \`\`     |         |             |

Clears out the selected columns for a query along with any configured select bindings.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .select( [ "fname AS firstName", "age" ] )
    .clearSelect();
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT * FROM `users`
```

{% endcode %}

## reselect <a href="#reselect" id="reselect"></a>

| Name    | Type            | Required | Default | Description                                                        |
| ------- | --------------- | -------- | ------- | ------------------------------------------------------------------ |
| columns | string \| array | `false`  | ​`"*"`  | A single column, list of columns, or array of columns to retrieve. |

Clears out the selected columns for a query along with any configured select bindings. Then sets a selection of columns to select from the query. Any valid argument to [`select`](/11.1.0/query-builder/building-queries/selects#get) can be passed here.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .select( [ "fname AS firstName", "age" ] )
    .reselect( "username" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT `username` FROM `users`
```

{% endcode %}

## reselectRaw <a href="#reselectraw" id="reselectraw"></a>

| Name       | Type  | Required | Default | Description                                  |
| ---------- | ----- | -------- | ------- | -------------------------------------------- |
| expression | any   | `true`   | ​       | The raw expression for the select statement. |
| bindings   | array | `false`  | `[]`    | Any bindings needed for the raw expression.  |

Clears out the selected columns for a query along with any configured select bindings. Then adds an Expression or array of expressions to the already selected columns.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .select( [ "fname AS firstName", "age" ] )
    .reselectRaw( "YEAR(birthdate) AS birth_year" );
```

{% endcode %}

{% code title="SQL (MySQL)" %}

```sql
SELECT YEAR(birthdate) AS birth_year FROM `users`
```

{% endcode %}


# From

## from <a href="#from" id="from"></a>

| Name | Type                 | Required | Default | Description                                                                 |
| ---- | -------------------- | -------- | ------- | --------------------------------------------------------------------------- |
| from | string \| Expression | `true`   | ​       | The name of the table or a Expression object from which the query is based. |

Used to set the base table for the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT * FROM `users`
```

{% endcode %}

You can optionally specify an alias for the table.

{% code title="QueryBuilder" %}

```javascript
query.from( "users as u" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT * FROM `users` AS `u`
```

{% endcode %}

## table <a href="#table" id="table"></a>

| Name  | Type                 | Required | Default | Description                                                                 |
| ----- | -------------------- | -------- | ------- | --------------------------------------------------------------------------- |
| table | string \| Expression | `true`   | ​       | The name of the table or a Expression object from which the query is based. |

An alias for `from` where you like how calling `table` looks.

{% code title="QueryBuilder" %}

```javascript
query.table( "users" ).insert( { "name" = "jon" } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
INSERT INTO `users` (`name`) VALUES (?)
```

{% endcode %}

## fromRaw <a href="#fromraw" id="fromraw"></a>

| Name     | Type   | Required | Default | Description                             |
| -------- | ------ | -------- | ------- | --------------------------------------- |
| from     | string | `true`   | ​       | The sql snippet to use as the table.    |
| bindings | array  | `false`  | `[]`    | Any bindings needed for the expression. |

Sometimes you need more control over your `from` clause in order to add grammar specific instructions, such as adding SQL Server table hints to your queries.

{% code title="QueryBuilder" %}

```javascript
query.fromRaw( "[users] u (nolock)" ).get();
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT * FROM [users] u (nolock) 
```

{% endcode %}

Since the `fromRaw()` takes your string verbatim, it's important that you make sure your SQL declaration is escaped properly. Failure to properly escape your table names may result in SQL errors.

{% hint style="warning" %}
Using `fromRaw` will most likely tie your code to a specific database, so think carefully before using the `fromRaw` method if you want your project to be database agnostic.
{% endhint %}

Many database engines allow you to define User Defined Functions. For example, SQL Server allows you to define UDFs that will return a table. In these type of cases, it may be necessary to bind parameters to your `from` clause.

You can bind parameters to the `fromRaw()` method by passing a secondary argument that is an array of the parameters to bind.

{% code title="QueryBuilder" %}

```javascript
query.fromRaw(
    "dbo.generateDateTable(?, ?, ?) as dt",
    [ "2017-01-01", "2017-12-31", "m" ]
).get();
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT * FROM dbo.generateDateTable(?, ?, ?) as dt
```

{% endcode %}

## fromSub <a href="#fromsub" id="fromsub"></a>

| Name  | Type                     | Required | Default | Description                                                                |
| ----- | ------------------------ | -------- | ------- | -------------------------------------------------------------------------- |
| alias | string                   | `true`   | ​       | The alias for the derived table.                                           |
| input | Function \| QueryBuilder | `true`   |         | Either a `QueryBuilder` instance or a closure to define the derived query. |

Complex queries often contain derived tables. Derived tables are essentially a temporal table defined as a subquery in the `from` statement.

{% code title="QueryBuilder" %}

```javascript
query.select( [ "firstName", "lastName" ] )
    .fromSub( "legalUsers", function ( q ) {
        q.select( [ "lName as lastName", "fName as firstName" ] )
            .from( "users" )
            .where( "age", ">=", 21 )
        ;
    } )
    .orderBy( "lastName" )
    .get()
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT `firstName`, `lastName`
FROM (
    SELECT `lName` as `lastName`, `fName` as `firstName`
    FROM `users`
    WHERE `age` >= 21
) AS `legalUsers`
ORDER BY `lastName`
```

{% endcode %}

In additional a function callback, a separate `QueryBuilder` instance can be passed to the `fromSub` method.

{% code title="QueryBuilder" %}

```javascript
var legalUsersQuery = query
    .select( [ "lName as lastName", "fName as firstName" ] )
    .from( "users" )
    .where( "age", ">=", 21 );

query.select( [ "firstName", "lastName" ] )
    .fromSub( "legalUsers", legalUsersQuery )
    .orderBy( "lastName" )
    .get();
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT `firstName`, `lastName`
FROM (
    SELECT `lName` as `lastName`, `fName` as `firstName`
    FROM `users`
    WHERE `age` >= 21
) AS `legalUsers`
ORDER BY `lastName`
```

{% endcode %}

## withAlias

<table><thead><tr><th>Name</th><th>Type</th><th data-type="checkbox">Required</th><th>Default Value</th><th>Description</th></tr></thead><tbody><tr><td>alias</td><td><code>string</code></td><td>true</td><td></td><td>The new alias to use for the table.</td></tr></tbody></table>

Adds an alias to the specified `from` table or renames a current alias.  Any existing aliased values in `columns`, `wheres`, `joins`, `groupBys`, or `orders` that match the previous alias will be remapped to the new alias.  This includes the full table name when used as an alias.

```cfscript
qb.from( "users" ).select( [ "users.name", "birthdate" ] );
// SELECT "users"."name", "birthdate" FROM "users"
qb.withAlias( "u1" );
// SELECT "u1"."name", "birthdate" FROM "users" AS "u1"
```


# Joins

Join clauses range from simple to complex including joining complete subqueries on multiple conditions. qb has your back with all of these use cases.

| Table of Contents                                                   |                                                                           |                                                                           |                                                                       |
| ------------------------------------------------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------- |
| [join](/11.1.0/query-builder/building-queries/joins#join)           | [joinRaw](/11.1.0/query-builder/building-queries/joins#joinraw)           | [joinSub](/11.1.0/query-builder/building-queries/joins#joinsub)           | [joinWhere](/11.1.0/query-builder/building-queries/joins#joinwhere)   |
| [leftJoin](/11.1.0/query-builder/building-queries/joins#leftjoin)   | [leftJoinRaw](/11.1.0/query-builder/building-queries/joins#leftjoinraw)   | [leftJoinSub](/11.1.0/query-builder/building-queries/joins#leftjoinsub)   | [newJoin](/11.1.0/query-builder/building-queries/joins#newjoin)       |
| [rightJoin](/11.1.0/query-builder/building-queries/joins#get)       | [rightJoinRaw](/11.1.0/query-builder/building-queries/joins#rightjoinraw) | [rightJoinSub](/11.1.0/query-builder/building-queries/joins#rightjoinsub) | [JoinClause](/11.1.0/query-builder/building-queries/joins#joinclause) |
| [crossJoin](/11.1.0/query-builder/building-queries/joins#crossjoin) | [crossJoinRaw](/11.1.0/query-builder/building-queries/joins#crossjoinraw) | [crossJoinSub](/11.1.0/query-builder/building-queries/joins#crossjoinsub) |                                                                       |

## join <a href="#join" id="join"></a>

| Name     | Type                                                                                                                                                    | Required | Default   | Description                                                                                                                                                                                                                                                               |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| table    | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) \| [JoinClause](/11.1.0/query-builder/building-queries/joins#joinclause) | `true`   | ​         | The name of the table or a [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) object from which the query is based.  Alternatively, a configured [`JoinClause`](/11.1.0/query-builder/building-queries/joins#joinclause) instance can be passed.      |
| first    | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) \| Function                                                              | `false`  |           | The first column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) to join the table on.  Alternatively, a function can be passed to configure complex join statements.                                                                           |
| operator | string                                                                                                                                                  | `false`  | `"="`     | The boolean operator for the join clause.                                                                                                                                                                                                                                 |
| second   | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions)                                                                          | `false`  |           | The second column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) to join the table on.                                                                                                                                                         |
| type     | string                                                                                                                                                  | `false`  | `"inner"` | The type of the join.  Passing this as an argument is discouraged for readability. Use the dedicated methods like [`leftJoin`](/11.1.0/query-builder/building-queries/joins#leftjoin) and [`rightJoin`](/11.1.0/query-builder/building-queries/joins#get) where possible. |
| where    | boolean                                                                                                                                                 | `false`  | `false`   | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use the dedicated [`joinWhere`](/11.1.0/query-builder/building-queries/joins#joinwhere) or a join closure where possible.                         |

Applies a join to the query. The simplest join is to a table based on two columns:

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .join( "posts", "users.id", "=", "posts.author_id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
```

{% endcode %}

When doing a simple join using `=` as the operator, you can omit it and pass just the column names:

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .join( "posts", "users.id", "posts.author_id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
```

{% endcode %}

\`\`[`Expressions`](/11.1.0/query-builder/building-queries/raw-expressions) are also supported as the `table` argument (though you may prefer the readability of the [`joinRaw`](/11.1.0/query-builder/building-queries/joins#joinraw) method):

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .join( query.raw( "posts (nolock)" ), "users.id", "=", "posts.author_id" );
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT *
FROM [users]
JOIN posts (nolock)
  ON [users].[id] = [posts].[author_id]
```

{% endcode %}

{% hint style="warning" %}
Using `raw` will most likely tie your code to a specific database, so think carefully before using the `raw` method if you want your project to be database agnostic.
{% endhint %}

When you need to specify more clauses to join, you can pass a function as the second argument:

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .join( "posts", function( j ) {
        j.on( "users.id", "=", "posts.author_id" );
        j.on( "users.prefix", "=", "posts.prefix" );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
  AND `users`.`prefix` = `posts`.`prefix`
```

{% endcode %}

You can specify [`where`](/11.1.0/query-builder/building-queries/wheres) clauses in your joins as well.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .join( "posts", function( j ) {
        j.on( "users.id", "=", "posts.author_id" );
        j.whereNotNull( "posts.published_date" );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
  AND `posts`.`published_date` IS NOT NULL
```

{% endcode %}

Conditions inside a join clause can be grouped using a function.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .join( "posts", function( j ) {
        j.on( function( j1 ) {
            j1.on( "users.id", "posts.author_id" )
                .orOn( "users.id", "posts.reviewer_id" );
        } );
        j.whereNotNull( "posts.published_date" );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON (
      `users`.`id` = `posts`.`author_id`
      OR `users`.`id` = `posts`.`reviewer_id`
  )
  AND `posts`.`published_date` IS NOT NULL
```

{% endcode %}

A preconfigured [`JoinClause`](/11.1.0/query-builder/building-queries/joins#joinclause) can also be passed to the join function. This allows you to extract shared pieces of code out to different functions.

{% code title="QueryBuilder" %}

```javascript
var j = query.newJoin( "contacts" )
    .on( "users.id", "posts.author_id" );

query.from( "users" ).join( j );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
```

{% endcode %}

## joinWhere <a href="#joinwhere" id="joinwhere"></a>

| Name     | Type                                                                                       | Required | Default   | Description                                                                                                                                                                                                                                                                                    |
| -------- | ------------------------------------------------------------------------------------------ | -------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| table    | string                                                                                     | `true`   | ​         | The raw SQL string to use as the table.                                                                                                                                                                                                                                                        |
| first    | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) \| Function | `false`  |           | The first column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) to join the table on.  Alternatively, a function can be passed to configure complex join statements.                                                                                                |
| operator | string                                                                                     | `false`  | `"="`     | The boolean operator for the join clause.                                                                                                                                                                                                                                                      |
| second   | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions)             | `false`  |           | The second column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) to join the table on.                                                                                                                                                                              |
| type     | string                                                                                     | `false`  | `"inner"` | The type of the join.  Passing this as an argument is discouraged for readability. Use the dedicated methods like [`leftJoin`](/11.1.0/query-builder/building-queries/joins#leftjoin) and [`rightJoin`](/11.1.0/query-builder/building-queries/joins#get) with a join function where possible. |

Adds a join to another table based on a `WHERE` clause instead of an `ON` clause. `WHERE` clauses introduce parameters and parameter bindings whereas `on` clauses join between columns and don't need parameter bindings.

For simple joins, this specifies a column on which to join the two tables:

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .joinWhere( "contacts", "contacts.balance", "<", 100 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `contacts`
  WHERE `contacts`.`balance` < ?
```

{% endcode %}

For complex joins, a function can be passed to `first`. This allows multiple `on` and `where` conditions to be applied to the join. See the documentation for [`join`](/11.1.0/query-builder/building-queries/joins#join) for more information.

## joinRaw <a href="#joinraw" id="joinraw"></a>

| Name     | Type                                                                                       | Required | Default   | Description                                                                                                                                                                                                                                                                                 |
| -------- | ------------------------------------------------------------------------------------------ | -------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| table    | string                                                                                     | `true`   | ​         | The raw SQL string to use as the table.                                                                                                                                                                                                                                                     |
| first    | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) \| Function | `false`  |           | The first column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) to join the table on.  Alternatively, a function can be passed to configure complex join statements.                                                                                             |
| operator | string                                                                                     | `false`  | `"="`     | The boolean operator for the join clause.                                                                                                                                                                                                                                                   |
| second   | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions)             | `false`  |           | The second column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) to join the table on.                                                                                                                                                                           |
| type     | string                                                                                     | `false`  | `"inner"` | The type of the join.  Passing this as an argument is discouraged for readability. Use the dedicated methods like [`leftJoinRaw`](/11.1.0/query-builder/building-queries/joins#leftjoinraw) and [`rightJoinRaw`](/11.1.0/query-builder/building-queries/joins#rightjoinraw) where possible. |
| where    | boolean                                                                                    | `false`  | `false`   | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use a closure to define the where clauses where possible.                                                                                                           |

Uses the raw SQL provided to as the table for the join clause. All the other functionality of `joinRaw` matches the [`join`](/11.1.0/query-builder/building-queries/joins#join) method. Additionally, there are [`leftJoinRaw`](/11.1.0/query-builder/building-queries/joins#leftjoinraw), [`rightJoinRaw`](/11.1.0/query-builder/building-queries/joins#rightjoinraw), and `crossJoinRaw` methods available.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .joinRaw( "posts (nolock)", "users.id", "posts.author_id" );
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT *
FROM [users]
JOIN posts (nolock)
  ON [users].[id] = [posts].[author_id]
```

{% endcode %}

{% hint style="warning" %}
Using `joinRaw` will most likely tie your code to a specific database, so think carefully before using the `joinRaw` method if you want your project to be database agnostic.
{% endhint %}

## joinSub <a href="#joinsub" id="joinsub"></a>

| Name     | Type                                                                                       | Required | Default   | Description                                                                                                                                                                                                                                                                                 |
| -------- | ------------------------------------------------------------------------------------------ | -------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| alias    | string                                                                                     | `true`   |           | The alias for the derived table.                                                                                                                                                                                                                                                            |
| input    | Function \| QueryBuilder                                                                   | `true`   | ​         | Either a `QueryBuilder` instance or a function to define the derived query.                                                                                                                                                                                                                 |
| first    | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) \| Function | `true`   |           | The first column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) to join the table on.  Alternatively, a function can be passed to configure complex join statements.                                                                                             |
| operator | string                                                                                     | `false`  | `"="`     | The boolean operator for the join clause.                                                                                                                                                                                                                                                   |
| second   | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions)             | `false`  |           | The second column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) to join the table on.                                                                                                                                                                           |
| type     | string                                                                                     | `false`  | `"inner"` | The type of the join.  Passing this as an argument is discouraged for readability. Use the dedicated methods like [`leftJoinSub`](/11.1.0/query-builder/building-queries/joins#leftjoinsub) and [`rightJoinSub`](/11.1.0/query-builder/building-queries/joins#rightjoinsub) where possible. |
| where    | boolean                                                                                    | `false`  | `false`   | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use a closure to define the where clauses where possible.                                                                                                           |

Adds a join to a derived table. All the functionality of the [`join`](/11.1.0/query-builder/building-queries/joins#join) method applies to constrain the query. The derived table can be defined using a `QueryBuilder` instance:

{% code title="QueryBuilder" %}

```javascript
var sub = query.newQuery()
    .select( "id" )
    .from( "contacts" )
    .whereNotIn( "id", [ 1, 2, 3 ] );

query.from( "users as u" )
    .joinSub( "c", sub, "u.id", "=", "c.id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users` AS `u`
JOIN (
  SELECT `id`
  FROM `contacts`
  WHERE `id` NOT IN (?, ?, ?)
) AS `c`
  ON `u`.`id` = `c`.`id`
```

{% endcode %}

Alternatively, a function may be used to define the derived table:

{% code title="QueryBuilder" %}

```javascript
query.from( "users as u" )
    .joinSub( "c", function ( q ) {
        q.select( "id" )
            .from( "contacts" )
            .whereNotIn( "id", [ 1, 2, 3 ] );
    }, "u.id", "=", "c.id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users` AS `u`
JOIN (
  SELECT `id`
  FROM `contacts`
  WHERE `id` NOT IN (?, ?, ?)
) AS `c`
  ON `u`.`id` = `c`.`id`
```

{% endcode %}

Complex join conditions are also possible by passing a function as the third parameter:

{% code title="QueryBuilder" %}

```javascript
query.from( "users as u" )
    .joinSub( "c", function ( q ) {
        q.select( "id" )
            .from( "contacts" )
            .whereNotIn( "id", [ 1, 2, 3 ] );
    }, function( j ) {
        j.on( "u.id", "c.id" );
        j.on( "u.type", "c.type" );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users` AS `u`
JOIN (
  SELECT `id`
  FROM `contacts`
  WHERE `id` NOT IN (?, ?, ?)
) AS `c`
  ON `u`.`id` = `c`.`id`
  AND `u`.`type` = `c`.`type`
```

{% endcode %}

## leftJoin <a href="#leftjoin" id="leftjoin"></a>

| Name | Type | Required | Default | Description |
| ---- | ---- | -------- | ------- | ----------- |

| table | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) \| [JoinClause](/11.1.0/query-builder/building-queries/joins#joinclause) | `true` | ​ | <p>The name of the table or a <a href="/pages/-LqPwKuMTnx51m1fvv9o"><code>Expression</code></a> object from which the query is based. Alternatively, a configured <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance can be passed.</p><p>(Note: a <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance may have a different join type than a <code>left</code> join. The <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance's join type will be used.)</p> |
| ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

| first | string \| Expression \| Function | `false` |   | The first column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) to join the table on. Alternatively, a function can be passed to configure complex join statements. |
| ----- | -------------------------------- | ------- | - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

| operator | string | `false` | `"="` | The boolean operator for the join clause. |
| -------- | ------ | ------- | ----- | ----------------------------------------- |

| second | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) | `false` |   | The second column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) to join the table on. |
| ------ | ------------------------------------------------------------------------------ | ------- | - | ----------------------------------------------------------------------------------------------------------------- |

| where | boolean | `false` | `false` | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use a closure to define the where clauses where possible. |
| ----- | ------- | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

{% code title="QueryBuilder" %}

```javascript
query.from( "posts" )
    .leftJoin( "users", "users.id", "posts.author_id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `posts`
LEFT JOIN `users`
  ON `users`.`id` = `posts`.`author_id`
```

{% endcode %}

## leftJoinRaw <a href="#leftjoinraw" id="leftjoinraw"></a>

| Name     | Type                                                                                       | Required | Default | Description                                                                                                                                                                                     |
| -------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| table    | string                                                                                     | `true`   | ​       | The raw SQL string to use as the table.                                                                                                                                                         |
| first    | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) \| Function | `false`  |         | The first column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) to join the table on.  Alternatively, a function can be passed to configure complex join statements. |
| operator | string                                                                                     | `false`  | `"="`   | The boolean operator for the join clause.                                                                                                                                                       |
| second   | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The second column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) to join the table on.                                                                               |
| where    | boolean                                                                                    | `false`  | `false` | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use a closure to define the where clauses where possible.               |

Uses the raw SQL provided to as the table for the left join clause. All the other functionality of `leftJoinRaw` matches the [`join`](/11.1.0/query-builder/building-queries/joins#join) method.

{% code title="QueryBuilder" %}

```javascript
query.from( "posts" )
    .leftJoinRaw( "users (nolock)", "users.id", "posts.author_id" );
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT *
FROM [posts]
LEFT JOIN users (nolock)
  ON [users].[id] = [posts].[author_id]
```

{% endcode %}

{% hint style="warning" %}
Using `leftJoinRaw` will most likely tie your code to a specific database, so think carefully before using the `leftJoinRaw` method if you want your project to be database agnostic.
{% endhint %}

## leftJoinSub <a href="#leftjoinsub" id="leftjoinsub"></a>

| Name     | Type                                                                                       | Required | Default | Description                                                                                                                                                                                     |
| -------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| alias    | string                                                                                     | `true`   |         | The alias for the derived table.                                                                                                                                                                |
| input    | Function \| QueryBuilder                                                                   | `true`   | ​       | Either a `QueryBuilder` instance or a function to define the derived query.                                                                                                                     |
| first    | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) \| Function | `true`   |         | The first column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) to join the table on.  Alternatively, a function can be passed to configure complex join statements. |
| operator | string                                                                                     | `false`  | `"="`   | The boolean operator for the join clause.                                                                                                                                                       |
| second   | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The second column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) to join the table on.                                                                               |
| where    | boolean                                                                                    | `false`  | `false` | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use a closure to define the where clauses where possible.               |

Adds a left join to a derived table. All the functionality of the [`joinSub`](/11.1.0/query-builder/building-queries/joins#joinsub) method applies to define and constrain the query.

{% code title="QueryBuilder" %}

```javascript
var sub = query.newQuery()
    .select( "id" )
    .from( "contacts" )
    .whereNotIn( "id", [ 1, 2, 3 ] );

query.from( "users as u" )
    .leftJoinSub( "c", sub, "u.id", "=", "c.id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users` AS `u`
LEFT JOIN (
  SELECT `id`
  FROM `contacts`
  WHERE `id` NOT IN (?, ?, ?)
) AS `c`
  ON `u`.`id` = `c`.`id`
```

{% endcode %}

## rightJoin <a href="#get" id="get"></a>

| Name | Type | Required | Default | Description |
| ---- | ---- | -------- | ------- | ----------- |

| table | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) \| [JoinClause](/11.1.0/query-builder/building-queries/joins#joinclause) | `true` | ​ | <p>The name of the table or a <a href="/pages/-LqPwKuMTnx51m1fvv9o"><code>Expression</code></a> object from which the query is based. Alternatively, a configured <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance can be passed.</p><p>(Note: a <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance may have a different join type than a <code>right</code> join. The <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance's join type will be used.)</p> |
| ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

| first | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) \| Function | `false` |   | The first column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) to join the table on. Alternatively, a function can be passed to configure complex join statements. |
| ----- | ------------------------------------------------------------------------------------------ | ------- | - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

| operator | string | `false` | `"="` | The boolean operator for the join clause. |
| -------- | ------ | ------- | ----- | ----------------------------------------- |

| second | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) | `false` |   | The second column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) to join the table on. |
| ------ | ------------------------------------------------------------------------------ | ------- | - | ----------------------------------------------------------------------------------------------------------------- |

| where | boolean | `false` | `false` | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use a closure to define the where clauses where possible. |
| ----- | ------- | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .rightJoin( "posts", "users.id", "posts.author_id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
RIGHT JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
```

{% endcode %}

## rightJoinRaw <a href="#rightjoinraw" id="rightjoinraw"></a>

| Name     | Type                                                                                       | Required | Default | Description                                                                                                                                                                                     |
| -------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| table    | string                                                                                     | `true`   | ​       | The raw SQL string to use as the table.                                                                                                                                                         |
| first    | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) \| Function | `false`  |         | The first column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) to join the table on.  Alternatively, a function can be passed to configure complex join statements. |
| operator | string                                                                                     | `false`  | `"="`   | The boolean operator for the join clause.                                                                                                                                                       |
| second   | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The second column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) to join the table on.                                                                               |
| where    | boolean                                                                                    | `false`  | `false` | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use a closure to define the where clauses where possible.               |

Uses the raw SQL provided to as the table for the right join clause. All the other functionality of `rightJoinRaw` matches the [`join`](/11.1.0/query-builder/building-queries/joins#join) method.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .rightJoinRaw( "posts (nolock)", "users.id", "posts.author_id" );
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT *
FROM [users]
LEFT JOIN posts (nolock)
  ON [users].[id] = [posts].[author_id]
```

{% endcode %}

{% hint style="warning" %}
Using `rightJoinRaw` will most likely tie your code to a specific database, so think carefully before using the `rightJoinRaw` method if you want your project to be database agnostic.
{% endhint %}

## rightJoinSub <a href="#rightjoinsub" id="rightjoinsub"></a>

| Name     | Type                                                                                       | Required | Default | Description                                                                                                                                                                                     |
| -------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| alias    | string                                                                                     | `true`   |         | The alias for the derived table.                                                                                                                                                                |
| input    | Function \| QueryBuilder                                                                   | `true`   | ​       | Either a `QueryBuilder` instance or a function to define the derived query.                                                                                                                     |
| first    | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) \| Function | `true`   |         | The first column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) to join the table on.  Alternatively, a function can be passed to configure complex join statements. |
| operator | string                                                                                     | `false`  | `"="`   | The boolean operator for the join clause.                                                                                                                                                       |
| second   | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The second column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) to join the table on.                                                                               |
| where    | boolean                                                                                    | `false`  | `false` | Sets if the value of `second` should be interpreted as a column or a value. Passing this as an argument is discouraged. Use a closure to define the where clauses where possible.               |

Adds a right join to a derived table. All the functionality of the [`joinSub`](/11.1.0/query-builder/building-queries/joins#joinsub) method applies to define and constrain the query.

{% code title="QueryBuilder" %}

```javascript
var sub = query.newQuery()
    .select( "id" )
    .from( "contacts" )
    .whereNotIn( "id", [ 1, 2, 3 ] );

query.from( "users as u" )
    .rightJoinSub( "c", sub, "u.id", "=", "c.id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users` AS `u`
RIGHT JOIN (
  SELECT `id`
  FROM `contacts`
  WHERE `id` NOT IN (?, ?, ?)
) AS `c`
  ON `u`.`id` = `c`.`id`
```

{% endcode %}

## crossJoin <a href="#crossjoin" id="crossjoin"></a>

| Name | Type | Required | Default | Description |
| ---- | ---- | -------- | ------- | ----------- |

| table | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) \| [JoinClause](/11.1.0/query-builder/building-queries/joins#joinclause) | `true` | ​ | <p>The name of the table or a <a href="/pages/-LqPwKuMTnx51m1fvv9o"><code>Expression</code></a> object from which the query is based. Alternatively, a configured <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance can be passed.</p><p>(Note: a <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance may have a different join type than a <code>cross</code> join. The <a href="/pages/-LA-U_amB-_HaM0_d6Es#joinclause"><code>JoinClause</code></a> instance's join type will be used.)</p> |
| ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).crossJoin( "posts" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
CROSS JOIN `posts`
```

{% endcode %}

## crossJoinRaw <a href="#crossjoinraw" id="crossjoinraw"></a>

| Name  | Type   | Required | Default | Description                             |
| ----- | ------ | -------- | ------- | --------------------------------------- |
| table | string | `true`   | ​       | The raw SQL string to use as the table. |

Uses the raw SQL provided to as the table for the cross join clause. Cross joins cannot be further constrained with `on` or `where` clauses.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" ).crossJoinRaw( "posts (nolock)" );
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT *
FROM [users]
CROSS JOIN posts (nolock)
```

{% endcode %}

{% hint style="warning" %}
Using `crossJoinRaw` will most likely tie your code to a specific database, so think carefully before using the `crossJoinRaw` method if you want your project to be database agnostic.
{% endhint %}

## crossJoinSub <a href="#crossjoinsub" id="crossjoinsub"></a>

| Name  | Type                     | Required | Default | Description                                                                 |
| ----- | ------------------------ | -------- | ------- | --------------------------------------------------------------------------- |
| alias | string                   | `true`   |         | The alias for the derived table.                                            |
| input | Function \| QueryBuilder | `true`   | ​       | Either a `QueryBuilder` instance or a function to define the derived query. |

Adds a cross join to a derived table. The derived table can be defined using a `QueryBuilder` instance or a function just as with [`joinSub`](/11.1.0/query-builder/building-queries/joins#joinsub). Cross joins cannot be constrained, however.

{% code title="QueryBuilder" %}

```javascript
var sub = query.newQuery()
    .select( "id" )
    .from( "contacts" )
    .whereNotIn( "id", [ 1, 2, 3 ] );

query.from( "users as u" ).crossJoinSub( "c", sub );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users` AS `u`
CROSS JOIN (
  SELECT `id`
  FROM `contacts`
  WHERE `id` NOT IN (?, ?, ?)
)
```

{% endcode %}

## crossApply <a href="#crossapply" id="crossapply"></a>

| Name     | Type                         | Required | Default | Description                                                                                   |
| -------- | ---------------------------- | -------- | ------- | --------------------------------------------------------------------------------------------- |
| name     | string                       | `true`   |         | The name for the cross apply table                                                            |
| tableDef | `function` \| `QueryBuilder` | `true`   |         | A QueryBuilder instance or a function that accepts a new query builder instance to configure. |

Adds a cross apply join using a derived table. The derived table can be defined using a `QueryBuilder` instance or a function just as with [`joinSub`](/11.1.0/query-builder/building-queries/joins#joinsub).

{% code title="QueryBuilder" %}

```javascript
qb.from( "users as u" )
    .select( [ "u.ID", "childCount.c" ] )
    .crossApply( "childCount", function( qb ) {
        qb.selectRaw( "count(*) c" )
            .from( "children" )
            .whereColumn( "children.parentID", "=", "users.ID" )
            .where( "children.someCol", "=", 0 );
    } )
    .where( "childCount.c", ">", 1 )
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT
    [u].[ID],
    [childCount].[c]
FROM [users] AS [u]
CROSS APPLY (
    SELECT count(*) c
    FROM [children]
    WHERE [children].[parentID] = [users].[ID]
    AND [children].[someCol] = ?
) AS [childCount]
WHERE [childCount].[c] > ?
```

{% endcode %}

## outerApply <a href="#outerapply" id="outerapply"></a>

| Name     | Type                         | Required | Default | Description                                                                                   |
| -------- | ---------------------------- | -------- | ------- | --------------------------------------------------------------------------------------------- |
| name     | string                       | `true`   |         | The name for the cross apply table                                                            |
| tableDef | `function` \| `QueryBuilder` | `true`   |         | A QueryBuilder instance or a function that accepts a new query builder instance to configure. |

Adds a outer apply join using a derived table. The derived table can be defined using a `QueryBuilder` instance or a function just as with [`joinSub`](/11.1.0/query-builder/building-queries/joins#joinsub).

{% code title="QueryBuilder" %}

```javascript
qb.from( "users as u" )
    .select( [ "u.ID", "childCount.c" ] )
    .outerApply( "childCount", function( qb ) {
        qb.selectRaw( "count(*) c" )
            .from( "children" )
            .whereColumn( "children.parentID", "=", "users.ID" )
            .where( "children.someCol", "=", 0 );
    } )
    .where( "childCount.c", ">", 1 )
```

{% endcode %}

{% code title="SQL Server" %}

```sql
SELECT
    [u].[ID],
    [childCount].[c]
FROM [users] AS [u]
OUTER APPLY (
    SELECT count(*) c
    FROM [children]
    WHERE [children].[parentID] = [users].[ID]
    AND [children].[someCol] = ?
) AS [childCount]
WHERE [childCount].[c] > ?
```

{% endcode %}

## newJoin <a href="#newjoin" id="newjoin"></a>

| Name  | Type                                                                           | Required | Default   | Description                                                                                                                             |
| ----- | ------------------------------------------------------------------------------ | -------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| table | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) | `true`   | ​         | The name of the table or a [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) object from which the query is based. |
| type  | string                                                                         | `false`  | `"inner"` | The type of the join.  Valid types are `inner`, `left`, `right`, or `cross`.                                                            |

Creates a new [`JoinClause`](/11.1.0/query-builder/building-queries/joins#joinclause). A [`JoinClause`](/11.1.0/query-builder/building-queries/joins#joinclause) is a specialized version of a `QueryBuilder`. You may call `on` or `orOn` to constrain the [`JoinClause`](/11.1.0/query-builder/building-queries/joins#joinclause). You may also call any [`where`](/11.1.0/query-builder/building-queries/wheres) methods.

Creating a [`JoinClause`](/11.1.0/query-builder/building-queries/joins#joinclause) directly is useful when you need to share a join between different queries. You can create and configure the [`JoinClause`](/11.1.0/query-builder/building-queries/joins#joinclause) in a function and pass it to queries as needed.

{% code title="QueryBuilder" %}

```javascript
var j = query.newJoin( "contacts" )
    .on( "users.id", "posts.author_id" );

query.from( "users" ).join( j );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
```

{% endcode %}

{% hint style="warning" %}
Although a [`JoinClause`](/11.1.0/query-builder/building-queries/joins#joinclause) can be passed to [`join`](/11.1.0/query-builder/building-queries/joins#join), [`leftJoin`](/11.1.0/query-builder/building-queries/joins#leftjoin), [`rightJoin`](/11.1.0/query-builder/building-queries/joins#get), and `crossJoin`, the type of the [`JoinClause`](/11.1.0/query-builder/building-queries/joins#joinclause) will override the type of the function.
{% endhint %}

{% code title="QueryBuilder" %}

```javascript
// This is still an inner join because
// the JoinClause is an inner join
var j = query.newJoin( "contacts", "inner" )
    .on( "users.id", "posts.author_id" );

query.from( "users" ).leftJoin( j );
```

{% endcode %}

{% code title="MySQL" %}

```sql
-- This is still an inner join because
-- the JoinClause is an inner join
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
```

{% endcode %}

## JoinClause

A `JoinClause` is a specialized version of a `QueryBuilder`. You may call `on` or `orOn` to constrain the `JoinClause`. You may also call any [`where`](/11.1.0/query-builder/building-queries/wheres) methods.

### on

| Name       | Type                                                                                       | Required | Default | Description                                                                                                                                                                               |
| ---------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| first      | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) \| Function | `false`  |         | The first column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions)of the condition.  Alternatively, a function can be passed to nest conditions with parenthesis. |
| operator   | string                                                                                     | `false`  | `"="`   | The boolean operator for the condition.                                                                                                                                                   |
| second     | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The second column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) of the condition.                                                                             |
| combinator | string                                                                                     | `false`  | `"and"` | The boolean combinator for the clause (e.g. "and" or "or").                                                                                                                               |

Applies a join condition to the `JoinClause`. An alias for `whereColumn`.

{% code title="QueryBuilder" %}

```javascript
var j = query.newJoin( "contacts" )
    .on( "users.id", "posts.author_id" );

query.from( "users" ).join( j );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
```

{% endcode %}

### orOn

| Name     | Type                                                                                       | Required | Default | Description                                                                                                                                                                               |
| -------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| first    | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) \| Function | `false`  |         | The first column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions)of the condition.  Alternatively, a function can be passed to nest conditions with parenthesis. |
| operator | string                                                                                     | `false`  | `"="`   | The boolean operator for the condition.                                                                                                                                                   |
| second   | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The second column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) of the condition.                                                                             |

Applies a join condition to the `JoinClause` using an `or` combinator. An alias for `orWhereColumn`.

{% code title="QueryBuilder" %}

```javascript
var j = query.newJoin( "contacts" )
    .on( "users.id", "posts.author_id" )
    .orOn( "users.id", "posts.reviewer_id" );

query.from( "users" ).join( j );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
JOIN `posts`
  ON `users`.`id` = `posts`.`author_id`
  OR `users`.`id` = `posts`.`reviewer_id`
```

{% endcode %}

## Preventing Duplicate Joins

You can optionally configure qb to ignore duplicate joins.  With this setting turned on each `JoinClause` is inspected and checked if it matches any existing `JoinClause` instances on the query.  This is useful if you have a table shared between optional constraints and want to ensure it is only added once.

You can opt-in to this behavior by setting `preventDuplicateJoins = true` in your `moduleSettings` in `config/ColdBox.cfc`.

```javascript
moduleSettings = {
    "qb": {
         "preventDuplicateJoins": true  
    }
};
```


# Wheres

| Table of Contents                                                          |                                                                                  |                                                                          |
| -------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| [where](/11.1.0/query-builder/building-queries/wheres#where)               | [andWhere](/11.1.0/query-builder/building-queries/wheres#andwhere)               | [orWhere](/11.1.0/query-builder/building-queries/wheres#orwhere)         |
| [whereBetween](/11.1.0/query-builder/building-queries/wheres#wherebetween) | [whereNotBetween](/11.1.0/query-builder/building-queries/wheres#wherenotbetween) | [whereColumn](/11.1.0/query-builder/building-queries/wheres#wherecolumn) |
| [whereExists](/11.1.0/query-builder/building-queries/wheres#whereexists)   | [whereNotExists](/11.1.0/query-builder/building-queries/wheres#wherenotexists)   | [whereLike](/11.1.0/query-builder/building-queries/wheres#wherelike)     |
| [whereIn](/11.1.0/query-builder/building-queries/wheres#wherein)           | [whereNotIn](/11.1.0/query-builder/building-queries/wheres#wherenotin)           | [whereRaw](/11.1.0/query-builder/building-queries/wheres#whereraw)       |
| [whereNull](/11.1.0/query-builder/building-queries/wheres#wherenull)       | [whereNotNull](/11.1.0/query-builder/building-queries/wheres#wherenotnull)       |                                                                          |

## Where Methods

### where

| Name       | Type                                                                                       | Required | Default | Description                                                                                                                                                                                                                                                                                                 |
| ---------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) \| Function | `true`   |         | The name of the column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) with which to constrain the query. A function can be passed to begin a nested where statement.                                                                                                             |
| operator   | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The operator to use for the constraint (i.e. "=", "<", ">=", etc.). A value can be passed as the `operator` and the `value` left null as a shortcut for equals (e.g. where( "column", 1 ) == where( "column", "=", 1 ) ).                                                                                   |
| value      | any                                                                                        | `false`  |         | The value with which to constrain the column.  An [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) can be passed as well.  If a QueryBuilder or Function is passed, it will be used as a subselect expression.                                                                        |
| combinator | string                                                                                     | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the [`andWhere`](/11.1.0/query-builder/building-queries/wheres#andwhere) and [`orWhere`](/11.1.0/query-builder/building-queries/wheres#orwhere) methods instead. |

Adds a where clause to a query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "active", "=", 1 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `active` = ?
```

{% endcode %}

{% hint style="info" %}
Using the `where` method will parameterize the `value` passed.  If you want to constrain a column to another column, use the [`whereColumn`](/11.1.0/query-builder/building-queries/wheres#wherecolumn) method.
{% endhint %}

You can also pass an [Expression](/11.1.0/query-builder/building-queries/raw-expressions) as the value.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "last_logged_in", ">", query.raw( "NOW()" ) );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `last_logged_in` > NOW()
```

{% endcode %}

Any of the following operators can be used in a where clause.

| Valid Operators |                |             |
| --------------- | -------------- | ----------- |
| =               | <              | >           |
| <=              | >=             | <>          |
| !=              | like           | like binary |
| not like        | between        | ilike       |
| &               | \|             | ^           |
| <<              | >>             | rlike       |
| regexp          | not regexp     | \~          |
| \~\*            | !\~            | !\~\*       |
| similar to      | not similar to |             |

When using the `"="` constraint, you can use a shortcut and define the value as the second argument.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "active", 1 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `active` = ?
```

{% endcode %}

{% hint style="info" %}
You may also use [dynamic where{Column}](/11.1.0/query-builder/building-queries/wheres#dynamic-where-methods) statements to simplify this further.
{% endhint %}

To group where statements together, pass a function to the where clause as the only parameter.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( function( q ) {
        q.where( "active", 1 )
            .where( "last_logged_in", ">", dateAdd( "ww", -1, now() ) )
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE (
    `active` = ?
    AND
    `last_logged_in` > ?
)
```

{% endcode %}

{% hint style="info" %}
This grouping can be nested as many levels as you require.
{% endhint %}

A Function or QueryBuilder can be used as a subselect expression when passed to `value`.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "email", "foo" )
    .orWhere( "id", "=", function( q ) {
        q.select( q.raw( "MAX(id)" ) )
            .from( "users" )
            .where( "email", "bar" );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `email` = ?
  OR `id` = (
    SELECT MAX(id)
    FROM `users`
    WHERE `email` = ?
  )
```

{% endcode %}

### andWhere

| Name     | Type                                                                                       | Required | Default | Description                                                                                                                                                                                                                          |
| -------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| column   | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) \| Function | `true`   |         | The name of the column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) with which to constrain the query. A function can be passed to begin a nested where statement.                                      |
| operator | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The operator to use for the constraint (i.e. "=", "<", ">=", etc.). A value can be passed as the `operator` and the `value` left null as a shortcut for equals (e.g. where( "column", 1 ) == where( "column", "=", 1 ) ).            |
| value    | any                                                                                        | `false`  |         | The value with which to constrain the column.  An [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) can be passed as well.  If a QueryBuilder or Function is passed, it will be used as a subselect expression. |

This method is simply an alias for [`where`](/11.1.0/query-builder/building-queries/wheres#where) with the combinator set to `"and"`.

### orWhere

| Name     | Type                                                                                       | Required | Default | Description                                                                                                                                                                                                                          |
| -------- | ------------------------------------------------------------------------------------------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| column   | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) \| Function | `true`   |         | The name of the column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) with which to constrain the query. A function can be passed to begin a nested where statement.                                      |
| operator | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions)             | `false`  |         | The operator to use for the constraint (i.e. "=", "<", ">=", etc.). A value can be passed as the `operator` and the `value` left null as a shortcut for equals (e.g. where( "column", 1 ) == where( "column", "=", 1 ) ).            |
| value    | any                                                                                        | `false`  |         | The value with which to constrain the column.  An [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) can be passed as well.  If a QueryBuilder or Function is passed, it will be used as a subselect expression. |

This method is simply an alias for [`where`](/11.1.0/query-builder/building-queries/wheres#where) with the combinator set to `"or"`.

### whereBetween

| Name       | Type                            | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | ------------------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| Expression            | `true`   |         | The name of the column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                                                                    |
| start      | any \| Function \| QueryBuilder | `true`   |         | The beginning value of the BETWEEN statement.  If a function or QueryBuilder is passed it is used as a subselect expression.                                                                                                                                           |
| end        | any \| Function \| QueryBuilder | `true`   |         | The end value of the BETWEEN statement. If a function or QueryBuilder is passed it is used as a subselect expression.                                                                                                                                                  |
| combinator | string                          | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods](/11.1.0/query-builder/building-queries/wheres#andwhere-and-orwhere) instead. |
| negate     | boolean                         | `false`  | `false` | False for BETWEEN, True for NOT BETWEEN.                                                                                                                                                                                                                               |

Adds a where between clause to the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereBetween( "id", 1, 2 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `id` BETWEEN ? AND ?
```

{% endcode %}

If a function or QueryBuilder is passed it is used as a subselect expression.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereBetween(
        "id",
        function( q ) {
            q.select( q.raw( "MIN(id)" ) )
                .from( "users" )
                .where( "email", "bar" );
        },
        builder.newQuery()
            .select( builder.raw( "MAX(id)" ) )
            .from( "users" )
            .where( "email", "bar" )
    );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `id` BETWEEN (
    SELECT MIN(id)
    FROM `users`
    WHERE `email` = ?
)
AND (
    SELECT MAX(id)
    FROM `users`
    WHERE `email` = ?
)
```

{% endcode %}

### whereNotBetween

| Name       | Type                            | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | ------------------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| Expression            | `true`   |         | The name of the column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                                                                    |
| start      | any \| Function \| QueryBuilder | `true`   |         | The beginning value of the BETWEEN statement.  If a function or QueryBuilder is passed it is used as a subselect expression.                                                                                                                                           |
| end        | any \| Function \| QueryBuilder | `true`   |         | The end value of the BETWEEN statement. If a function or QueryBuilder is passed it is used as a subselect expression.                                                                                                                                                  |
| combinator | string                          | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods](/11.1.0/query-builder/building-queries/wheres#andwhere-and-orwhere) instead. |

Adds a where not in clause to the query.  This behaves identically to the [`whereBetween`](/11.1.0/query-builder/building-queries/wheres#wherebetween) method with the `negate`flag set to `true`.  See the documentation for [`whereBetween`](/11.1.0/query-builder/building-queries/wheres#wherebetween) for usage and examples.

### whereColumn

| Name       | Type                                                                           | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | ------------------------------------------------------------------------------ | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| first      | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) | `true`   |         | The name of the first column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                                                              |
| operator   | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) | `true`   |         | The operator to use for the constraint (i.e. "=", "<", ">=", etc.). A value can be passed as the `operator` and the `value` left null as a shortcut for equals (e.g. where( "column", 1 ) == where( "column", "=", 1 ) ).                                              |
| second     | string \| Expression                                                           | `false`  |         | The name of the second column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                                                             |
| combinator | string                                                                         | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods](/11.1.0/query-builder/building-queries/wheres#andwhere-and-orwhere) instead. |

Adds a where clause to a query that compares two columns.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereColumn( "first_name", "=", "last_name" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `first_name` = `last_name`
```

{% endcode %}

Just as with `where`, when using `"="` as the operator you can use a shorthand passing the second column in as the operator and leaving the second column `null`.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereColumn( "first_name", "last_name" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `first_name` = `last_name`
```

{% endcode %}

`Expressions` can be passed in place of either column.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereColumn( "first_name", query.raw( "LOWER(first_name)" ) );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `first_name` = LOWER(first_name)
```

{% endcode %}

### whereExists

| Name       | Type                     | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | ------------------------ | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| query      | Function \| QueryBuilder | `true`   |         | A function or QueryBuilder instance to be used as the exists subquery.                                                                                                                                                                                                 |
| combinator | string                   | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/11.1.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead. |
| negate     | boolean                  | `false`  | `false` | False for EXISTS, True for NOT EXISTS.                                                                                                                                                                                                                                 |

Adds a where exists clause to the query.

It can be configured with a function.

{% code title="QueryBuilder" %}

```javascript
query.from( "orders" )
    .whereExists( function( q ) {
        q.select( q.raw( 1 ) )
            .from( "products" )
            .whereColumn( "products.id", "orders.id" );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `orders`
WHERE EXISTS (
    SELECT 1
    FROM `products`
    WHERE `products`.`id` = `orders`.`id`
)
```

{% endcode %}

It can also be configured with a QueryBuilder instance.

{% code title="QueryBuilder" %}

```javascript
var existsQuery = query.newQuery()
    .select( q.raw( 1 ) )
    .from( "products" )
    .whereColumn( "products.id", "orders.id" );

query.from( "orders" )
    .whereExists( existsQuery );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `orders`
WHERE EXISTS (
    SELECT 1
    FROM `products`
    WHERE `products`.`id` = `orders`.`id`
)
```

{% endcode %}

### whereNotExists

| Name       | Type                     | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | ------------------------ | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| query      | Function \| QueryBuilder | `true`   |         | A function or QueryBuilder instance to be used as the not exists subquery.                                                                                                                                                                                             |
| combinator | string                   | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/11.1.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead. |

Adds a where not in clause to the query.  This behaves identically to the [`whereExists`](/11.1.0/query-builder/building-queries/wheres#whereexists) method with the `negate`flag set to `true`.  See the documentation for [`whereExists`](/11.1.0/query-builder/building-queries/wheres#whereexists) for usage and examples.

### whereLike

| Name       | Type                                                                           | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | ------------------------------------------------------------------------------ | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) | `true`   |         | The name of the column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                                                                    |
| value      | any                                                                            | `false`  |         | The value with which to constrain the column.  An [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) can be passed as well.  If a QueryBuilder or Function is passed, it will be used as a subselect expression.                                   |
| combinator | string                                                                         | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/11.1.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead. |

A shortcut for calling [`where`](/11.1.0/query-builder/building-queries/wheres#where) with `"like"` set as the operator.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereLike( "username", "J%" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `username` LIKE ?
```

{% endcode %}

### whereNotLike

| Name       | Type                                                                           | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | ------------------------------------------------------------------------------ | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) | `true`   |         | The name of the column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                                                                    |
| value      | any                                                                            | `false`  |         | The value with which to constrain the column.  An [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) can be passed as well.  If a QueryBuilder or Function is passed, it will be used as a subselect expression.                                   |
| combinator | string                                                                         | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/11.1.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead. |

A shortcut for calling [`where`](/11.1.0/query-builder/building-queries/wheres#where) with `"not like"` set as the operator.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereNotLike( "username", "J%" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `username` NOT LIKE ?
```

{% endcode %}

### whereIn

| Name       | Type                                                                                                                | Required | Default | Description                                                                                                                                                                                                                                                                                                 |
| ---------- | ------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| Expression                                                                                                | `true`   |         | The name of the column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                                                                                                         |
| values     | string \| array \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) \| Function \| QueryBuilder | `true`   |         | A single value, list of values, or array of values to constrain a column with.  [`Expressions`](/11.1.0/query-builder/building-queries/raw-expressions) may be used in any place a value is used.  Alternatively, a function or QueryBuilder instance can be passed in to be used as a subquery expression. |
| combinator | string                                                                                                              | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/11.1.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead.                                      |
| negate     | boolean                                                                                                             | `false`  | `false` | False for IN, True for NOT IN.                                                                                                                                                                                                                                                                              |

Adds a where in clause to the query.

The values passed to `whereIn` can be a single value, a list of values, or an array of values.

{% code title="QueryBuilder" %}

```javascript
query.from( "orders" )
    .whereIn( "id", [ 1, 4, 66 ] );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `orders`
WHERE `id` IN (?, ?, ?)
```

{% endcode %}

{% hint style="warning" %}
Some database grammars have a hard limit on the number of parameters passed to a SQL statement.  Keep this in mind while writing your queries.
{% endhint %}

If a list of values is passed in, it is converted to an array of values using a single comma (`","`) delimiter.

{% code title="QueryBuilder" %}

```javascript
query.from( "orders" )
    .whereIn( "id", "1,4,66" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `orders`
WHERE `id` IN (?, ?, ?)
```

{% endcode %}

Any value in the list or array can also be passed using a [custom parameter type](/11.1.0/query-builder/building-queries/parameters-and-bindings#custom-parameter-types) to have more control over the parameter settings.

{% code title="QueryBuilder" %}

```javascript
query.from( "orders" )
    .whereIn( "id", [ 1, 4, { value = "66", cfsqltype = "CF_SQL_VARCHAR" } ] );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `orders`
WHERE `id` IN (?, ?, ?)
```

{% endcode %}

`Expressions` can be freely mixed in with other values.

{% code title="QueryBuilder" %}

```javascript
query.from( "orders" )
    .whereIn( "id", [ query.raw( "MAX(id)" ), 4, 66 ] );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `orders`
WHERE `id` IN (MAX(id), ?, ?)
```

{% endcode %}

A function or QueryBuilder instance can be passed to be used as a subquery expression instead of a list of values.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereIn( "id", function( q ) {
        q.select( "id" )
            .from( "users" )
            .where( "age", ">", 25 );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE IN (
    SELECT `id`
    FROM `users`
    WHERE `age` > ?
)
```

{% endcode %}

{% hint style="warning" %}
You may find a `whereExists` method performs better for you than a `whereIn` with a subquery.
{% endhint %}

### whereNotIn

| Name       | Type                                                                                                                | Required | Default | Description                                                                                                                                                                                                                                                                                                 |
| ---------- | ------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| Expression                                                                                                | `true`   |         | The name of the column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                                                                                                         |
| values     | string \| array \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) \| Function \| QueryBuilder | `true`   |         | A single value, list of values, or array of values to constrain a column with.  [`Expressions`](/11.1.0/query-builder/building-queries/raw-expressions) may be used in any place a value is used.  Alternatively, a function or QueryBuilder instance can be passed in to be used as a subquery expression. |
| combinator | string                                                                                                              | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/11.1.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead.                                      |

Adds a where not in clause to the query.  This behaves identically to the `whereIn` method with the `negate`flag set to `true`.  See the documentation for [`whereIn`](/11.1.0/query-builder/building-queries/wheres#wherein) for usage and examples.

### whereRaw

| Name          | Type   | Required | Default | Description                                                                                                                                                                                                                                                            |
| ------------- | ------ | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| sql           | string | `true`   |         | The raw SQL to add to the query.                                                                                                                                                                                                                                       |
| whereBindings | array  | `false`  | `[]`    | Any bindings needed for the raw SQL.  Bindings can be simple values or [custom parameters](/11.1.0/query-builder/building-queries/parameters-and-bindings#custom-parameter-types).                                                                                     |
| combinator    | string | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/11.1.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead. |

Shorthand to add a raw SQL statement to the where clauses.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereRaw(
        "id = ? OR email = ? OR is_admin = 1",
        [ 1, "foo" ]
    );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE id = ? OR email = ? OR is_admin = 1
```

{% endcode %}

### whereNull

| Name       | Type                 | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | -------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| Expression | `true`   |         | The name of the column to check if it is NULL.  Can also pass an [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions).                                                                                                                               |
| combinator | string               | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/11.1.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead. |
| negate     | boolean              | `false`  | `false` | False for NULL, True for NOT NULL.                                                                                                                                                                                                                                     |

Adds a where null clause to the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereNull( "id" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `id` IS NULL
```

{% endcode %}

### whereNotNull

| Name       | Type                 | Required | Default | Description                                                                                                                                                                                                                                                            |
| ---------- | -------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| Expression | `true`   |         | The name of the column to check if it is NULL.  Can also pass an [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions).                                                                                                                               |
| combinator | string               | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andWhere` and `orWhere` [dynamic methods ](/11.1.0/query-builder/building-queries/wheres#andwhere-and-orwhere)instead. |
| negate     | boolean              | `false`  | `false` | False for NULL, True for NOT NULL.                                                                                                                                                                                                                                     |

Adds a where not in clause to the query.  This behaves identically to the [`whereNull`](/11.1.0/query-builder/building-queries/wheres#wherenull) method with the `negate`flag set to `true`.  See the documentation for [`whereNull`](/11.1.0/query-builder/building-queries/wheres#wherenull) for usage and examples.

## Dynamic Where Methods

qb uses `onMissingMethod` to provide a few different helpers when working with `where...` methods.

### andWhere... and orWhere...

Every `where...` method in qb can be called prefixed with either `and` or `or`.  Doing so will call the original method using the corresponding combinator.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "username", "like", "j%" )
    .andWhere( function( q ) {
        q.where( "isSubscribed", 1 )
            .orWhere( "isOnFreeTrial", 1 );
     } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `username` LIKE ?
  AND (
    `isSubscribed` = ?
    OR
    `isOnFreeTrial` = ?
  )
```

{% endcode %}

### where{Column}

If you call a method starting with `where` that does not match an existing qb method, qb will instead call the `where` method using the rest of the method name as the first column name.  (The rest of the arguments will be shifted to account for this.)  This also applies to `andWhere{Column}` and `orWhere{Column}` method signatures.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .whereUsername( "like", "j%" )
    .whereActive( 1 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `username` LIKE ?
  AND `active` = ?
```

{% endcode %}


# Order By

The `orderBy` method seems simple but has a lot of depth depending on the type of arguments you pass in.

{% hint style="info" %}
Calling `orderBy` multiple times appends to the order list.
{% endhint %}

## Order By (String)

| Name      | Type   | Required | Default | Description                                                                                                                          |
| --------- | ------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| column    | any    | `true`   |         | The name of the column to order by. An [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) can be passed as well. |
| direction | string | `false`  | `"asc"` | The direction by which to order the query. Accepts `"asc"`or `"desc"`.                                                               |

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( "email" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY `email` ASC
```

{% endcode %}

Calling `orderBy` multiple times will append to the order list.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( "email" )
    .orderBy( "username", "desc" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY
  `email` ASC,
  `username` DESC
```

{% endcode %}

You can also provide an [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions).

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( query.raw( "DATE(created_at)" ) );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY DATE(created_at)
```

{% endcode %}

## Order By (List)

| Name      | Type   | Required | Default | Description                                                                                                                                                                                                     |           |
| --------- | ------ | -------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
| column    | any    | `true`   |         | The list of the columns to order by.  Each column can optionally declare it's sort direction after a pipe delimiter. (e.g. \`"height                                                                            | desc"\`). |
| direction | string | `false`  | `"asc"` | The direction by which to order the query. Accepts `"asc"`or `"desc"`.  This value will be used as the default value for all entries in the column list that fail to specify a direction for a specific column. |           |

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( "email|asc,username", "desc" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY
  `email` ASC,
  `username` DESC
```

{% endcode %}

## Order By (Array of Strings)

| Name      | Type   | Required | Default | Description                                                                                                                                                                                                      |           |
| --------- | ------ | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
| column    | any    | `true`   |         | The array of the columns to order by.  Each column can optionally declare it's sort direction after a pipe delimiter. (e.g. \`"height                                                                            | desc"\`). |
| direction | string | `false`  | `"asc"` | The direction by which to order the query. Accepts `"asc"`or `"desc"`.  This value will be used as the default value for all entries in the column array that fail to specify a direction for a specific column. |           |

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( [ "email|asc", "username" ], "desc" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY
  `email` ASC,
  `username` DESC
```

{% endcode %}

## Order By (Array of Structs)

| Name      | Type   | Required | Default | Description                                                                                                                                                                                                                                   |
| --------- | ------ | -------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column    | any    | `true`   |         | The array of the columns to order by.  Each column can optionally declare it's sort direction using a struct.  The struct should have a column key and an optional direction key. (e.g. `{ column = "favorite_color", direction = "desc" }`). |
| direction | string | `false`  | `"asc"` | The direction by which to order the query. Accepts `"asc"`or `"desc"`.  This value will be used as the default value for all entries in the column array that fail to specify a direction for a specific column.                              |

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( [
        { "column": "email", "direction": "asc" },
        "username"
    ], "desc" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY
  `email` ASC,
  `username` DESC
```

{% endcode %}

## Order By (Subquery)

| Name      | Type   | Required | Default | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| --------- | ------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column    | any    | `true`   |         | The name of the column to order by. An [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) can be passed as well. An array can be passed with any combination of simple values, array, struct, or list for each entry in the array (an example with all possible value styles: column = \[ "last\_name", \[ "age", "desc" ], { column = "favorite\_color", direction = "desc" }, "height\|desc" ];. The column argument can also just accept a comman delimited list with a pipe ( \| ) as the secondary delimiter denoting the direction of the order by. The pipe delimiter is also used when parsing the column argument when it is passed as an array and the entry in the array is a pipe delimited string. |
| direction | string | `false`  | `"asc"` | Ignored when using a Function or QueryBuilder instance.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |

You can order with a subquery using either a function or a QueryBuilder instance.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( function( q ) {
        q.selectRaw( "MAX(created_date)" )
            .from( "logins" )
            .whereColumn( "users.id", "logins.user_id" );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY (
    SELECT MAX(created_date)
    FROM `logins`
    WHERE `users`.`id` = `logins`.`user_id`
)
```

{% endcode %}

## Order By Raw

| Name       | Type   | Required | Default | Description                                |
| ---------- | ------ | -------- | ------- | ------------------------------------------ |
| expression | string | `true`   |         | The raw SQL expression to use.             |
| bindings   | array  | `false`  | `[]`    | Any bindings (`?`) used in the expression. |

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderByRaw( "CASE WHEN status = ? THEN 1 ELSE 0 END DESC", [ 1 ] );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY CASE WHEN status = ? THEN 1 ELSE 0 END DESC
```

{% endcode %}

## clearOrders

| Name         | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

Clears the currently configured orders for the query.  Usually used by downstream libraries like [Quick](https://quick.ortusbooks.com/).

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( "email" )
    .clearOrders();
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
```

{% endcode %}

## reorder

| Name      | Type   | Required | Default | Description                                                                                                                          |
| --------- | ------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| column    | any    | `true`   |         | The name of the column to order by. An [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) can be passed as well. |
| direction | string | `false`  | `"asc"` | The direction by which to order the query. Accepts `"asc"`or `"desc"`.                                                               |

Clears the currently configured orders for the query and sets the new orders passed in.  Any valid argument to [`orderBy`](/11.1.0/query-builder/building-queries/ordering-grouping-and-limit) can be passed here.  Usually used by downstream libraries like [Quick](https://quick.ortusbooks.com/).

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .orderBy( "email" )
    .reorder( "username" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
ORDER BY `username` ASC
```

{% endcode %}


# Group By and Having

## groupBy

| Name   | Type            | Required | Default | Description                                                                                                                                                                              |
| ------ | --------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| groups | string \| array | `true`   |         | A single column name, a list of column names, or an array of column names to group by.  An [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) can be passed as well. |

Passing a single string will group by that one column.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .groupBy( "country" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
GROUP BY `country`
```

{% endcode %}

You can also pass a list of column names.  A single comma (`","`) will be used as the delimiter.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .groupBy( "country,city" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
GROUP BY `country`, `city`
```

{% endcode %}

An array of column names can be provided.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .groupBy( [ "country", "city" ] );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
GROUP BY `country`, `city`
```

{% endcode %}

Calling `groupBy` multiple times will to the current groups.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .groupBy( "country" )
    .groupBy( "city" );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
GROUP BY `country`, `city`
```

{% endcode %}

An [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) can be passed in place of a column.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .groupBy( query.raw( "DATE(created_at)" ) );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
GROUP BY DATE(created_at)
```

{% endcode %}

## having

| Name       | Type                                                                           | Required | Default | Description                                                                                                                                                                                                               |
| ---------- | ------------------------------------------------------------------------------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| column     | string \| [Expression](/11.1.0/query-builder/building-queries/raw-expressions) | `true`   |         | The name of the column or [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) with which to constrain the query.                                                                                       |
| operator   | any                                                                            | `false`  |         | The operator to use for the constraint (i.e. "=", "<", ">=", etc.). A value can be passed as the `operator` and the `value` left null as a shortcut for equals (e.g. where( "column", 1 ) == where( "column", "=", 1 ) ). |
| value      | any                                                                            | `false`  |         | The value with which to constrain the column.  An [`Expression`](/11.1.0/query-builder/building-queries/raw-expressions) can be passed as well.                                                                           |
| combinator | string                                                                         | `false`  | `"and"` | The boolean combinator for the clause.  Valid options are `"and"` or `"or"`.  Avoid passing this parameter explicitly.  Where possible use the `andHaving` and `orHaving` methods instead.                                |

Adds a having clause to a query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .groupBy( "email" )
    .having( "email", ">", 1 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
GROUP BY `email`
HAVING `email` > ?
```

{% endcode %}

`Expressions` can be used in place of the column or the value.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .groupBy( "email" )
    .having( query.raw( "COUNT(email)" ), ">", 1 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
GROUP BY `email`
HAVING COUNT(email) > ?
```

{% endcode %}


# Limit, Offset, and Pagination

## limit

| Name  | Type    | Required | Default | Description                    |
| ----- | ------- | -------- | ------- | ------------------------------ |
| value | numeric | `true`   |         | The limit value for the query. |

Sets the limit value for the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .limit( 5 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
LIMIT 5
```

{% endcode %}

## take

| Name  | Type    | Required | Default | Description                    |
| ----- | ------- | -------- | ------- | ------------------------------ |
| value | numeric | `true`   |         | The limit value for the query. |

Sets the limit value for the query.  Alias for [`limit`](/11.1.0/query-builder/building-queries/limit-offset-and-pagination#limit).

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .take( 5 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
LIMIT 5
```

{% endcode %}

## offset

| Name  | Type    | Required | Default | Description                     |
| ----- | ------- | -------- | ------- | ------------------------------- |
| value | numeric | `true`   |         | The offset value for the query. |

Sets the offset value for the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .offset( 25 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
OFFSET 25
```

{% endcode %}

## forPage

| Name    | Type    | Required | Default | Description                                                                            |
| ------- | ------- | -------- | ------- | -------------------------------------------------------------------------------------- |
| page    | numeric | `true`   |         | The page number to retrieve.                                                           |
| maxRows | numeric | `true`   |         | The number of records per page.  If a number less than 0 is passed, 0 is used instead. |

Helper method to calculate the limit and offset given a page number and count per page.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .forPage( 3, 15 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT *
FROM `users`
LIMIT 15
OFFSET 30
```

{% endcode %}

## simplePaginate & paginate

This method combines `forPage`, `count`, and `get` to create a pagination struct alongside the results. Information on the `simplePaginate` or `paginate` methods, including custom pagination collectors, can be found in the [Retreiving Results](/11.1.0/query-builder/executing-queries/retrieving-results#paginate) section of the documentation.


# Locks

qb includes a few methods to help you lock certain rows when executing `select` statements.

{% hint style="warning" %}
**Note:** For locks to work properly, they must be nested inside a `transaction`.  qb does not handle any of the transaction lifecycle for you.
{% endhint %}

## sharedLock

| Name         | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

A shared lock prevents the selected rows from being modified until your transaction is committed.

{% tabs %}
{% tab title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "id", 1 )
    .sharedLock();
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `id` = ?
LOCK IN SHARE MODE
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
SELECT *
FROM [users] WITH (ROWLOCK,HOLDLOCK)
WHERE [id] = ?
```

{% endtab %}

{% tab title="Postgres" %}

```sql
SELECT *
FROM "users"
WHERE "id" = ?
FOR SHARE
```

{% endtab %}

{% tab title="Oracle" %}

```sql
LOCK TABLE "USERS"
IN SHARE MODE NOWAIT;

SELECT *
FROM "USERS"
WHERE "ID" = ?
```

{% endtab %}
{% endtabs %}

## lockForUpdate

| Name       | Type    | Required | Default | Description |
| ---------- | ------- | -------- | ------- | ----------- |
| skipLocked | Boolean | `false`  | `false` |             |

A lock for update lock prevents the selected rows from being modified or selected with another shared lock until your transaction is committed.

The main difference between a `sharedLock` and `lockForUpdate` is that a `lockForUpdate` prevents other reads or selects as well as updates.

{% tabs %}
{% tab title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "id", 1 )
    .lockForUpdate();
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `id` = ?
FOR UPDATE
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
SELECT *
FROM [users] WITH (ROWLOCK,UPDLOCK,HOLDLOCK)
WHERE [id] = ?
```

{% endtab %}

{% tab title="Postgres" %}

```sql
SELECT *
FROM "users"
WHERE "id" = ?
FOR UPDATE
```

{% endtab %}

{% tab title="Oracle" %}

```sql
SELECT *
FROM "USERS"
WHERE "ID" = ?
FOR UPDATE
```

{% endtab %}
{% endtabs %}

When using the `skipLocked` flag, the query will skip over locked records and only return and lock available records.

{% tabs %}
{% tab title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "id", 1 )
    .lockForUpdate( skipLocked = true )
    .orderBy( "id" )
    .limit( 5 );
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="MySQL" %}

```sql
SELECT *
FROM `users`
WHERE `id` = ?
ORDER BY `id`
LIMIT 5
FOR UPDATE SKIP LOCKED
```

{% endtab %}

{% tab title="SQL Server" %}

```sql
SELECT TOP 5 *
FROM [users] WITH (ROWLOCK,UPDLOCK,HOLDLOCK,READPAST)
WHERE [id] = ?
ORDER BY [id]
```

{% endtab %}

{% tab title="Postgres" %}

```sql
SELECT *
FROM "users"
WHERE "id" = ?
ORDER BY "id"
LIMIT 1
FOR UPDATE SKIP LOCKED
```

{% endtab %}
{% endtabs %}

## noLock

| Name         | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

`noLock` will instruct your grammar to ignore any shared locks when executing the query.

Currently this only makes a difference in SQL Server grammars.

{% tabs %}
{% tab title="QueryBuilder" %}

```javascript
query.from( "users" )
    .where( "id", 1 )
    .noLock();
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="SQL Server" %}

```sql
SELECT *
FROM [users] WITH (NOLOCK)
WHERE [id] = ?
```

{% endtab %}
{% endtabs %}

## lock

| Name  | Type   | Required | Default | Description                                    |
| ----- | ------ | -------- | ------- | ---------------------------------------------- |
| value | string | `true`   |         | The custom lock directive to add to the query. |

The `lock` method will allow you to add a custom lock directive to your query.  Think of it as the `raw` method for lock directives.

These lock directives vary from grammar to grammar.

## clearLock

| Name         | Type | Required | Default | Description |
| ------------ | ---- | -------- | ------- | ----------- |
| No arguments |      |          |         |             |

Clears any lock directive on the query.


# Unions

The query builder also lets you create union statements on your queries using either `UNION` or `UNION ALL` strategies.

The `union` methods take either a Query Builder instance or a closure which you use to define a new QueryBuilder instance.

Union statements are added in the order in which the `union` methods are invoked, but the `union` statements can be in any order in your API call stack. This means you can safely declare your `union` method calls before the `select`, `from` and `orderBy` calls on the source Query Builder instance.

* `union()` — This method builds a SQL statement using the `UNION` clause which combines two SQL queries into a single result set containing all the matching rows. The two queries *must* have the same defined columns and compatible data types or the SQL engine will generate an error. The `union` clause only returns unique rows.
* `unionAll()` — This builds a SQL statement using the `UNION ALL` clause. This is the same as `union` but includes duplicate rows.&#x20;

{% hint style="danger" %}
**IMPORTANT:** The QueryBuilder instances passed to a `union` statement *cannot* contain a defined order. Any use of the `orderBy()` method on the unioned QueryBuilder instances will result in an `OrderByNotAllowed`exception. To order the results, add an `orderBy()` call to the parent source Query Builder instance.
{% endhint %}

## union

| Name  | Type                     | Required | Default | Description                                                                                                                               |
| ----- | ------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| input | Function \| QueryBuilder | `true`   |         | The function or QueryBuilder instance to use as the unioned query.                                                                        |
| all   | boolean                  | `false`  | `false` | Determines if statement should be a "UNION ALL". Passing this as an argument is discouraged. Use the dedicated `unionAll` where possible. |

Adds a UNION statement to the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .select( "name" )
    .where( "id", 1 )
    .union( function ( q ) {
        q.from( "users" )
            .select( "name" )
            .where( "id", 2 );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION
SELECT `name`
FROM `users`
WHERE `id` = ?
```

{% endcode %}

Adding multiple union statements will append it to the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .select( "name" )
    .where( "id", 1 )
    .union( function ( q ) {
        q.from( "users" )
            .select( "name" )
            .where( "id", 2 );
    } )
    .union( function ( q ) {
        q.from( "users" )
            .select("name")
            .where( "id", 3 );
    } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION
SELECT `name`
FROM `users`
WHERE `id` = ?
```

{% endcode %}

It can also add union queries as QueryBuilder instances.

{% code title="QueryBuilder" %}

```javascript
var q1 = query.newQuery()
    .from( "users" )
    .select( "name" )
    .where( "id", 2 );
    
var q2 = query.newQuery()
    .from( "users" )
    .select( "name" )
    .where( "id", 3 );

query.from( "users" )
    .select( "name" )
    .where( "id", 1 )
    .union( q1 )
    .union( q2 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION
SELECT `name`
FROM `users`
WHERE `id` = ?
```

{% endcode %}

## unionAll

| Name  | Type                     | Required | Default | Description                                                        |
| ----- | ------------------------ | -------- | ------- | ------------------------------------------------------------------ |
| input | Function \| QueryBuilder | `true`   |         | The function or QueryBuilder instance to use as the unioned query. |

Adds a UNION ALL statement to the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .select( "name" )
    .where( "id", 1 )
    .unionAll( function( q ) {
        q.from( "users" )
            .select( "name" )
            .where( "id", 2 );
     } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION ALL
SELECT `name`
FROM `users`
WHERE `id` = ?
```

{% endcode %}

Adding multiple `unionAll` statements will append it to the query.

{% code title="QueryBuilder" %}

```javascript
query.from( "users" )
    .select( "name" )
    .where( "id", 1 )
    .unionAll( function( q ) {
        q.from( "users" )
            .select( "name" )
            .where( "id", 2 );
     } )
    .unionAll( function( q ) {
        q.from( "users" )
            .select( "name" )
            .where( "id", 3 );
     } );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION ALL
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION ALL
SELECT `name`
FROM `users`
WHERE `id` = ?
```

{% endcode %}

It can also add union queries as QueryBuilder instances.

{% code title="QueryBuilder" %}

```javascript
var q1 = query.newQuery()
    .from( "users" )
    .select( "name" )
    .where( "id", 2 );
    
var q2 = query.newQuery()
    .from( "users" )
    .select( "name" )
    .where( "id", 3 );

query.from( "users" )
    .select( "name" )
    .where( "id", 1 )
    .unionAll( q1 )
    .unionAll( q2 );
```

{% endcode %}

{% code title="MySQL" %}

```sql
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION ALL
SELECT `name`
FROM `users`
WHERE `id` = ?
UNION ALL
SELECT `name`
FROM `users`
WHERE `id` = ?
```

{% endcode %}




---

[Next Page](/llms-full.txt/1)

