跳至主内容区

在 WHERE 条件中处理 null 和 undefined 值

非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

在 'WHERE' 条件中,nullundefined 在 TypeORM 中并非严格有效的值。

在编译阶段,TypeScript(当你在 tsconfig.json 中启用了 strictNullChecks 时)会禁止传递已知的 null 值。运行时遇到 nullundefined 值的默认行为是抛出错误。

可以通过数据源配置中的 invalidWhereValuesBehavior 选项来自定义 nullundefined 值的处理方式。此设置适用于高级操作,包括查询操作、Repository 方法及 EntityManager 方法(update, delete, softDelete, restore)。

警告

此设置不会影响 QueryBuilder 的 .where().andWhere().orWhere() 方法。QueryBuilder 是底层 API,null/undefined 值会原样传递。请使用 IsNull() 操作符或参数化条件进行显式的 null 处理。

默认行为

默认情况下,当 WHERE 条件中出现 nullundefined 值时,TypeORM 会抛出错误。这能防止意外结果并帮助及早发现潜在问题:

// Both queries will throw an error
const posts1 = await repository.find({
where: {
text: null,
},
})
// Error: Null value encountered in property 'text' of a where condition.

const posts2 = await repository.find({
where: {
text: undefined,
},
})
// Error: Undefined value encountered in property 'text' of a where condition.

要在 WHERE 条件中匹配 null 值,请使用 IsNull 操作符(详见 查询选项):

const posts = await repository.find({
where: {
text: IsNull(),
},
})

配置

你可以通过数据源配置中的 invalidWhereValuesBehavior 选项来自定义 null 和 undefined 值的处理方式:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
null: "ignore" | "sql-null" | "throw",
undefined: "ignore" | "throw",
},
})

Null 行为选项

null 行为可以设置为以下三个值之一:

'ignore'(忽略)

WHERE 条件中的 JavaScript null 值会被忽略,该属性会被跳过:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
null: "ignore",
},
})

// This will return all posts, ignoring the text property
const posts = await repository.find({
where: {
text: null,
},
})

'sql-null'(SQL空值)

JavaScript null 值会被转换为 SQL NULL 条件:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
null: "sql-null",
},
})

// This will only return posts where the text column is NULL in the database
const posts = await repository.find({
where: {
text: null,
},
})

'throw'(抛出错误,默认值)

JavaScript null 值会导致抛出 TypeORMError:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
null: "throw",
},
})

// This will throw an error
const posts = await repository.find({
where: {
text: null,
},
})
// Error: Null value encountered in property 'text' of a where condition.
// To match with SQL NULL, the IsNull() operator must be used.
// Set 'invalidWhereValuesBehavior.null' to 'ignore' or 'sql-null' in data source options to skip or handle null values.

Undefined 行为选项

undefined 行为可以设置为以下两个值之一:

'ignore'(忽略)

WHERE 条件中的 JavaScript undefined 值会被忽略,该属性会被跳过:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
undefined: "ignore",
},
})

// This will return all posts, ignoring the text property
const posts = await repository.find({
where: {
text: undefined,
},
})

'throw'(抛出错误,默认值)

JavaScript undefined 值会导致抛出 TypeORMError:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
undefined: "throw",
},
})

// This will throw an error
const posts = await repository.find({
where: {
text: undefined,
},
})
// Error: Undefined value encountered in property 'text' of a where condition.
// Set 'invalidWhereValuesBehavior.undefined' to 'ignore' in data source options to skip properties with undefined values.

请注意,这仅适用于显式设置的 undefined 值,不适用于省略的属性。

同时使用两个选项

你可以独立配置这两种行为以实现全面控制:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
null: "sql-null",
undefined: "throw",
},
})

此配置将:

  1. 将 WHERE 条件中的 JavaScript null 值转换为 SQL NULL

  2. 遇到任何 undefined 值时抛出错误

  3. 仍然忽略 WHERE 子句中未提供的属性

这种组合在以下场景特别有用:

  • 明确地在数据库中搜索 NULL 值

  • 捕获可能潜入查询的 undefined 值导致的潜在编程错误

支持的操作

invalidWhereValuesBehavior 配置仅适用于 TypeORM 的高级操作,不适用于 QueryBuilder 的直接 .where() 方法:

查询操作

// Repository.find() / findOne() / findBy() / findOneBy()
await repository.find({ where: { text: null } }) // Respects invalidWhereValuesBehavior

// EntityManager.find() / findOne() / findBy() / findOneBy()
await manager.find(Post, { where: { text: null } }) // Respects invalidWhereValuesBehavior

Repository 和 EntityManager 方法

// Repository.update()
await repository.update({ text: null }, { title: "Updated" }) // Respects invalidWhereValuesBehavior

// Repository.delete()
await repository.delete({ text: null }) // Respects invalidWhereValuesBehavior

// EntityManager.update()
await manager.update(Post, { text: null }, { title: "Updated" }) // Respects invalidWhereValuesBehavior

// EntityManager.delete()
await manager.delete(Post, { text: null }) // Respects invalidWhereValuesBehavior

// EntityManager.softDelete()
await manager.softDelete(Post, { text: null }) // Respects invalidWhereValuesBehavior

使用 setFindOptions 的 QueryBuilder

// setFindOptions goes through the find-options path, so it respects the setting
await dataSource
.createQueryBuilder(Post, "post")
.setFindOptions({ where: { text: null } }) // Respects invalidWhereValuesBehavior
.getMany()

不受影响:QueryBuilder .where()

QueryBuilder 的 .where().andWhere().orWhere() 是底层 API,不受此设置影响。null 和 undefined 值会原样传递:

// This does NOT respect invalidWhereValuesBehavior — null passes through as-is
await dataSource
.createQueryBuilder()
.update(Post)
.set({ title: "Updated" })
.where({ text: null })
.execute()

null 和 undefined 在 QueryBuilder .where() 中的行为

由于 QueryBuilder 是底层 API,null 和 undefined 值不会被验证或转换。理解其行为对避免意外结果至关重要。

QueryBuilder .where() 中的 null

当在对象式 .where() 中传递 null 作为值时,会生成针对 NULL 的 SQL 等值检查:

await dataSource
.createQueryBuilder(Post, "post")
.where({ text: null })
.getMany()
// Generates: WHERE post.text = NULL

在 SQL 中,column = NULL 总是 false——没有任何值等于 NULL。此查询将返回零结果,这几乎肯定不是你的预期。要匹配 NULL 值,请使用 IsNull() 操作符:

import { IsNull } from "typeorm"

await dataSource
.createQueryBuilder(Post, "post")
.where({ text: IsNull() })
.getMany()
// Generates: WHERE post.text IS NULL

或使用字符串条件:

await dataSource
.createQueryBuilder(Post, "post")
.where("post.text IS NULL")
.getMany()

QueryBuilder .where() 中的 undefined

当传递 undefined 作为值时,行为相同——会生成 WHERE column = NULL,这总是 false:

await dataSource
.createQueryBuilder(Post, "post")
.where({ text: undefined })
.getMany()
// Generates: WHERE post.text = NULL
// Returns: zero results

总结表格

ValueHigh-level API (find/repository/manager)QueryBuilder .where()
null with "ignore"Property skipped — no filterWHERE col = NULL — zero results
null with "sql-null"WHERE col IS NULLWHERE col = NULL — zero results
null with "throw" (default)Throws errorWHERE col = NULL — zero results
undefined with "ignore"Property skipped — no filterWHERE col = NULL — zero results
undefined with "throw" (default)Throws errorWHERE col = NULL — zero results
IsNull()WHERE col IS NULLWHERE col IS NULL
技巧

无论使用哪种 API,当需要匹配 SQL NULL 值时,请始终使用 IsNull()。它在高级操作和 QueryBuilder 上下文中均可正确工作。