在 WHERE 条件中处理 null 和 undefined 值
本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
在 'WHERE' 条件中,null 和 undefined 在 TypeORM 中并非严格有效的值。
在编译阶段,TypeScript(当你在 tsconfig.json 中启用了 strictNullChecks 时)会禁止传递已知的 null 值。运行时遇到 null 和 undefined 值的默认行为是抛出错误。
可以通过数据源配置中的 invalidWhereValuesBehavior 选项来自定义 null 和 undefined 值的处理方式。此设置适用于高级操作,包括查询操作、Repository 方法及 EntityManager 方法(update, delete, softDelete, restore)。
此设置不会影响 QueryBuilder 的 .where()、.andWhere() 或 .orWhere() 方法。QueryBuilder 是底层 API,null/undefined 值会原样传递。请使用 IsNull() 操作符或参数化条件进行显式的 null 处理。
默认行为
默认情况下,当 WHERE 条件中出现 null 或 undefined 值时,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",
},
})
此配置将:
-
将 WHERE 条件中的 JavaScript
null值转换为 SQLNULL -
遇到任何
undefined值时抛出错误 -
仍然忽略 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
总结表格
| Value | High-level API (find/repository/manager) | QueryBuilder .where() |
|---|---|---|
null with "ignore" | Property skipped — no filter | WHERE col = NULL — zero results |
null with "sql-null" | WHERE col IS NULL | WHERE col = NULL — zero results |
null with "throw" (default) | Throws error | WHERE col = NULL — zero results |
undefined with "ignore" | Property skipped — no filter | WHERE col = NULL — zero results |
undefined with "throw" (default) | Throws error | WHERE col = NULL — zero results |
IsNull() | WHERE col IS NULL | WHERE col IS NULL |
无论使用哪种 API,当需要匹配 SQL NULL 值时,请始终使用 IsNull()。它在高级操作和 QueryBuilder 上下文中均可正确工作。