标识符语法

在API的许多地方,可以将诸如表名或列名之类的标识符传递给方法。
通常一个最需要的只是普通的tableName.columnNametableName或者columnName,但在许多情况下,人们还需要通过一个别名怎么说标识符后来在查询简称。
有两种方法来声明标识符的别名。可以直接给as aliasName标识符加上后缀(例如identifierName as aliasName),也可以通过一个对象{ aliasName: 'identifierName' }
如果对象具有多个别名{ alias1: 'identifier1', alias2: 'identifier2' },则所有别名标识符都将扩展为逗号分隔的列表。
注意:标识符语法没有选择模式的位置,因此,如果这样做schemaName.tableName,查询可能会显示为错误。使用.withSchema('schemaName')代替。

  1. knex({ a: 'table', b: 'table' })
  2. .select({
  3. aTitle: 'a.title',
  4. bTitle: 'b.title'
  5. })
  6. .whereRaw('?? = ??', ['a.column_1', 'b.column_2'])

输出:

select [a].[title] as [aTitle], [b].[title] as [bTitle] from [table] as [a], [table] as [b] where [a].[column_1] = [b].[column_2]

关节 -knex(tableName, options={only: boolean}) / knex.[methodName]
通过指定要查询的tableName或直接在knex对象上调用任何方法,查询构建器开始。这将启动类似于jQuery的链,您可以根据需要调用其他查询构建器方法来构建查询,最终调用任何接口方法来转换为toString或使用promise,回调或流执行查询。传递选项的可选第二个参数: :如果:true,则在之前使用ONLY关键字tableName来丢弃继承表的数据。*注意:目前仅在PostgreSQL中受支持。

TypeScript的用法

如果使用TypeScript,则可以将数据库行的类型作为类型参数传递,以在链中获得更好的自动完成支持。

interface User {
  id: number;
  name: string;
  age: number;
}
knex('users')
  .where('id')
  .first(); // Resolves to any
knex<User>('users') // User is the type of row in database
  .where('id', 1) // Your IDE will be able to help with the completion of id
  .first(); // Resolves to User | undefined

通过JSDoc注释以纯JavaScript编写代码时,还可以利用自动完成支持(在支持TypeScript的IDE中)和泛型类型参数。

/**
 * @typedef {Object} User
 * @property {number} id
 * @property {number} age
 * @property {string} name
 *
 * @returns {Knex.QueryBuilder<User, {}>}
 */
const Users = () => knex('Users')
Users().where('id', 1) // 'id' property can be autocompleted by editor

使用类型推断和可变的流畅API的警告

大多数knex API都会变异当前对象并返回它。此模式不适用于类型推断。

knex<User>('users')
  .select('id')
  .then((users) => { // Type of users is inferred as Pick<User, "id">[]
    // Do something with users
  });
knex<User>('users')
  .select('id')
  .select('age')
  .then((users) => { // Type of users is inferred as Pick<User, "id" | "age">[]
    // Do something with users
  });
// The type of usersQueryBuilder is determined here
const usersQueryBuilder = knex<User>('users').select('id');
if (someCondition) {
  // This select will not change the type of usersQueryBuilder
  // We can not change the type of a pre-declared variabe in TypeScript
  usersQueryBuilder.select('age');
}
usersQueryBuilder.then((users) => {
  // Type of users here will be Pick<User, "id">[]
  // which may not be what you expect.
});
// You can specify the type of result explicitly through a second type parameter:
const queryBuilder = knex<User, Pick<User, "id" | "age">>('users');
// But there is no type constraint to ensure that these properties have actually been
// selected.
// So, this will compile:
queryBuilder.select('name').then((users) => {
  // Type of users is Pick<User, "id"> but it will only have name
})

如果您不想手动指定结果类型,建议始终使用链的最后一个值的类型,并将将来任何链延续的结果分配给单独的变量(类型将不同)。
超时 -.timeout(ms, options={cancel: boolean})
设置查询超时,如果超过超时,将抛出TimeoutError。该错误包含有关查询,绑定和设置的超时的信息。对于要确保不会花费太长时间执行的复杂查询很有用。传递选项的可选第二个参数: cancel:if true,如果达到超时则取消查询。*注意:目前仅在MySQL和PostgreSQL中受支持。

knex.select().from('books').timeout(1000)

输出:

select * from [books]
knex.select().from('books').timeout(1000, {cancel: true}) // MySQL and PostgreSQL only

错误:

Query cancelling not supported for this dialect

选择.select([*columns])
创建一个选择查询,为查询获取一个可选的列数组,如果在构建查询时未指定任何列,则最终默认为*。select调用的响应将使用从数据库中选择的对象数组解决。

knex.select('title', 'author', 'year').from('books')

输出:

select [title], [author], [year] from [books]
knex.select().table('books')

输出:

select * from [books]

TypeScript的用法

只要选择参数与记录类型中的键名完全匹配,我们通常就可以根据所选列来推断结果类型。但是,别名和作用域可能会妨碍推理。

knex.select('id').from<User>('users'); // Resolves to Pick<User, "id">[]
knex.select('users.id').from<User>('users'); // Resolves to any[]
// ^ TypeScript doesn't provide us a way to look into a string and infer the type
//   from a substring, so we fall back to any
// We can side-step this using knex.ref:
knex.select(knex.ref('id').withSchema('users')).from<User>('users'); // Resolves to Pick<User, "id">[]
knex.select('id as identifier').from<User>('users'); // Resolves to any[], for same reason as above
// Refs are handy here too:
knex.select(knex.ref('id').as('identifier')).from<User>('users'); // Resolves to { identifier: number; }[]

作为 -.as(name)
允许对子查询使用别名,并使用您希望为当前查询命名的字符串。如果查询不是子查询,它将被忽略。

knex.avg('sum_column1').from(function() {
  this.sum('column1 as sum_column1').from('t1').groupBy('column1').as('t1')
}).as('ignored_alias')

输出:

select avg([sum_column1]) from (select sum([column1]) as [sum_column1] from [t1] group by [column1]) as [t1]

-.column(columns)
专门设置要在选择查询中选择的列,采用数组,对象或列名列表。传递对象会自动使用给定的键对列进行别名。

knex.column('title', 'author', 'year').select().from('books')

输出:

select [title], [author], [year] from [books]
knex.column(['title', 'author', 'year']).select().from('books')

输出:

select [title], [author], [year] from [books]
knex.column('title', {by: 'author'}, 'year').select().from('books')

输出:

select [title], [author] as [by], [year] from [books]

来自.from([tableName], options={only: boolean})
指定当前查询中使用的表,如果已经指定了当前表名,则替换当前表名。这通常用在高级where或union方法中执行的子查询中。传递选项的可选第二个参数: :如果:true,则在之前使用ONLY关键字tableName来丢弃继承表的数据。*注意:目前仅在PostgreSQL中受支持。

knex.select('*').from('users')

输出:

select * from [users]

TypeScript的用法

我们可以通过TRecord type参数指定数据库行的类型

knex.select('id').from('users'); // Resolves to any[]
knex.select('id').from<User>('users'); // Results to Pick<User, "id">[]

-.with(alias, function|raw)
在查询中添加一个“ with”子句。PostgreSQL,Oracle,SQLite3和MSSQL支持“带有”子句。

knex.with('with_alias', knex.raw('select * from "books" where "author" = ?', 'Test')).select('*').from('with_alias')

输出:

with [with_alias] as (select * from "books" where "author" = 'Test') select * from [with_alias]
knex.with('with_alias', (qb) => {
  qb.select('*').from('books').where('author', 'Test')
}).select('*').from('with_alias')

输出:

with [with_alias] as (select * from [books] where [author] = 'Test') select * from [with_alias]

withRecursive.withRecursive(alias, function|raw)
与该with方法相同,但在“ with”后附加“递归”,以使自引用CTE成为可能。

knex.withRecursive('ancestors', (qb) => {
  qb.select('*').from('people').where('people.id', 1).union((qb) => {
    qb.select('*').from('people').join('ancestors', 'ancestors.parentId', 'people.id')
  })
}).select('*').from('ancestors')

输出:

with recursive [ancestors] as (select * from [people] where [people].[id] = 1 union select * from [people] inner join [ancestors] on [ancestors].[parentId] = [people].[id]) select * from [ancestors]

withSchema.withSchema([schemaName])
指定用作表名前缀的模式。

knex.withSchema('public').select('*').from('users')

输出:

select * from [public].[users]