如何在Prisma中无需原生查询实现WHERE子句字符串拼接查询?
在Prisma中实现字符串拼接条件查询(无需原生SQL)
你当前用原生SQL通过拼接国家码和手机号查询数据的逻辑是:
SELECT * FROM tbl_country, tbl_user WHERE CONCAT(tbl_country.code, '-', tbl_user.phone) = '+976-00000000';
对应的表结构:
tbl_country表
| id | name | code |
|---|---|---|
| 1 | Afghanistan | +93 |
| 2 | Aland Islands | +358 |
| 3 | Albania | +355 |
| ... | ... | ... |
| 240 | Yemen | +967 |
| 241 | Zambia | +260 |
| 242 | Zimbabwe | +263 |
tbl_user表
| id | name | phone |
|---|---|---|
| 1 | John Doe | 11111111 |
| 2 | Bob Doe | 22222222 |
| 3 | Adam Doe | 33333333 |
| ... | ... | ... |
| 8 | Jane Doe | 88888888 |
| 9 | Tom Doe | 99999999 |
| 10 | Thomas Doe | 00000000 |
解决方案:拆分目标字符串替代拼接查询
Prisma的类型安全查询API不支持直接在where条件中使用字符串拼接函数,但我们可以反向处理:把目标拼接字符串拆分为country.code和user.phone对应的子串,再分别作为过滤条件,完全替代原生SQL的逻辑。
实现代码(NestJS + Prisma)
import { Injectable, BadRequestException } from '@nestjs/common'; import { PrismaService } from './prisma.service'; @Injectable() export class UserService { constructor(private readonly prisma: PrismaService) {} async getByFullPhone(fullPhone: string) { // 拆分完整号码,校验格式 const dashIndex = fullPhone.indexOf('-'); if (dashIndex === -1) { throw new BadRequestException('号码格式错误,需包含"-"分隔国家码与手机号'); } const countryCode = fullPhone.slice(0, dashIndex); const phoneNumber = fullPhone.slice(dashIndex + 1); // 方案1:已定义表关联(推荐) // 假设Prisma Schema中tbl_user已关联tbl_country(如通过countryId外键) const matchedData = await this.prisma.tbl_user.findMany({ include: { // 关联的国家表字段名,需与Prisma Schema定义一致 country: { where: { code: countryCode }, }, }, where: { phone: phoneNumber }, // 过滤掉未匹配到对应国家的用户 having: { country: { isNot: null } }, }); // 方案2:未定义表关联(适配原SQL笛卡尔积逻辑) // const countries = await this.prisma.tbl_country.findMany({ // where: { code: countryCode }, // }); // const users = await this.prisma.tbl_user.findMany({ // where: { phone: phoneNumber }, // }); // // 生成所有符合条件的国家-用户组合 // const matchedData = countries.flatMap(country => // users.map(user => ({ ...country, ...user })) // ); return matchedData; } }
说明
- 方案1基于表关联实现,查询效率更高,且符合ORM的设计规范,优先推荐使用。需要提前在Prisma Schema中定义
tbl_user与tbl_country的关联关系,例如:
model tbl_user { id Int @id @default(autoincrement()) name String phone String countryId Int country tbl_country @relation(fields: [countryId], references: [id]) } model tbl_country { id Int @id @default(autoincrement()) name String code String @unique users tbl_user[] }
- 方案2适配原SQL的笛卡尔积逻辑,无需表关联,但查询效率较低,仅在无法修改Schema的场景下使用。
内容的提问来源于stack exchange,提问作者Enkh-Amar Ganbat
相关产品推荐
相关产品推荐

