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

使用Drizzle ORM(PostgreSQL)执行onConflictDoUpdate时数组追加报错

问题解决:Drizzle ORM PostgreSQL数组更新语法错误

问题背景

使用Drizzle ORM操作PostgreSQL的users表时,尝试在ON CONFLICT逻辑中用array_append更新INET类型数组字段ipList,代码触发syntax error at or near ")"报错;移除该更新字段后代码可正常运行,希望保留类型安全,不想使用db.execute()执行原生SQL。

当前代码:

const res = await db.insert(UsersTable)
    .values(newUser)
    .onConflictDoUpdate({ 
        target: UsersTable.email, 
        set: { 
            ipList:sql`array_append(${UsersTable.ipList}, ${newUser.ipList})`
        }
    })
    .returning({ insertedId: UsersTable.id });

期望生成的SQL:

INSERT INTO users (email, ip_list, name, phone, is_admin, password)
VALUES ($1, $2, $3, $4, $5, $6)
ON CONFLICT (email) DO UPDATE
SET ip_list = array_append(users.ip_list, $7::INET[])
RETURNING id;

解决方案

方案1:使用Drizzle内置数组操作函数(推荐,保留类型安全)

从drizzle-orm/pg-core导入arrayAppend函数,直接用它构建更新逻辑,Drizzle会自动处理参数绑定与类型转换:

import { arrayAppend } from 'drizzle-orm/pg-core';

// ...

const res = await db.insert(UsersTable)
    .values(newUser)
    .onConflictDoUpdate({ 
        target: UsersTable.email, 
        set: { 
            ipList: arrayAppend(UsersTable.ipList, newUser.ipList),
        }
    })
    .returning({ insertedId: UsersTable.id });

方案2:手动在SQL模板中指定类型转换

如果不想使用内置函数,可在SQL模板里明确给参数添加类型转换,确保PostgreSQL正确识别数组类型:

const res = await db.insert(UsersTable)
    .values(newUser)
    .onConflictDoUpdate({ 
        target: UsersTable.email, 
        set: { 
            ipList: sql`array_append(${UsersTable.ipList}, ${newUser.ipList}::inet[])`,
        }
    })
    .returning({ insertedId: UsersTable.id });

原因分析

之前的写法报错,是因为Drizzle处理直接传入的数组参数时,未自动完成正确的类型序列化,导致生成的SQL中数组格式不符合PostgreSQL要求,触发语法错误。上述两种方法要么通过内置函数自动处理类型,要么手动指定类型转换,都能让Drizzle生成符合预期的SQL,同时保留TypeScript的类型安全特性。

内容的提问来源于stack exchange,提问作者Pedro Santos

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 02:58:16