You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Drizzle ORM向存在多对多关系的两张表中插入数据

如何使用Drizzle ORM向存在多对多关系的两张表中插入数据

嘿,我来帮你把这段Prisma代码转成Drizzle的写法~ 毕竟Drizzle在处理多对多关联数据插入时,没有Prisma那种connect的便捷语法,得我们手动拆分步骤处理,而且最好用事务包裹操作,确保所有步骤要么都成功要么都失败,避免数据不一致。

首先得确保你的Drizzle Schema已经正确定义了这三张表(主表+中间关联表),我给你个参考示例:

import { pgTable, serial, varchar, integer, boolean, timestamp, primaryKey } from 'drizzle-orm/pg-core';
// 如果用MySQL,替换成mysql-core对应的方法即可

// 产品表
export const productTable = pgTable('productTable', {
  id: serial('id').primaryKey(),
  // 这里可以添加你的其他产品字段,比如name、price等
});

// 折扣码表
export const discountCodeTable = pgTable('discountCodeTable', {
  id: serial('id').primaryKey(),
  code: varchar('code', { length: 50 }).notNull(),
  discountAmount: integer('discountAmount').notNull(),
  discountType: varchar('discountType').notNull(), // 如果是枚举类型,可用Drizzle的enum方法定义
  allProducts: boolean('allProducts').notNull(),
  expiredAt: timestamp('expiredAt'),
  limit: integer('limit'),
});

// 多对多关联中间表
export const productToDiscount = pgTable('productToDiscount', {
  productId: integer('productId')
    .notNull()
    .references(() => productTable.id),
  discountCodeId: integer('discountCodeId')
    .notNull()
    .references(() => discountCodeTable.id),
}, (table) => ({
  // 设置复合主键,避免同一产品和折扣码重复关联
  pk: primaryKey(table.productId, table.discountCodeId),
}));

接下来就是核心的插入逻辑,我们需要先创建折扣码记录,再根据传入的productIds插入中间表的关联数据,用事务包裹这两个操作:

import { db } from './your-db-setup'; // 导入你的Drizzle数据库实例
import { discountCodeTable, productToDiscount } from './your-schema-file';
import { DiscountCodeType } from './your-enum-definition'; // 导入你的折扣类型枚举

async function createDiscountCode(data: {
  code: string;
  discountAmount: number;
  discountType: DiscountCodeType;
  allProducts: boolean;
  productIds?: number[];
  expiredAt?: Date;
  limit?: number;
}) {
  return await db.transaction(async (tx) => {
    // 第一步:插入折扣码到主表,用returning()获取刚创建的折扣码数据(包含id)
    const [newDiscountCode] = await tx.insert(discountCodeTable)
      .values({
        code: data.code,
        discountAmount: data.discountAmount,
        discountType: data.discountType,
        allProducts: data.allProducts,
        expiredAt: data.expiredAt,
        limit: data.limit,
      })
      .returning();

    // 第二步:如果传入了productIds,批量插入中间表的关联记录
    if (data.productIds?.length) {
      const associationRecords = data.productIds.map(productId => ({
        productId,
        discountCodeId: newDiscountCode.id,
      }));

      await tx.insert(productToDiscount)
        .values(associationRecords);
    }

    return newDiscountCode;
  });
}

这里和Prisma的主要区别在于:

  • Drizzle不会自动处理多对多的关联插入,需要手动拆分「创建主记录」和「插入关联记录」两个步骤
  • 用transaction包裹操作,保证两个步骤的原子性——如果其中一步失败,整个操作会回滚,不会留下半截数据
  • 通过returning()方法获取刚插入的折扣码ID,这是关联产品的关键

不管你用的是PostgreSQL还是MySQL,核心逻辑都是一样的,只是Schema定义时的字段类型方法会略有不同~

备注:内容来源于stack exchange,提问作者Pooyan Honari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.17 08:50:30