如何使用pg-format插入带timestamp的多行数据?解决格式问题及工具必要性
问题描述
我有一个名为employees的表,字段如下:
| id | name | department | position | country | jobdesc | created_at |
|---|---|---|---|---|---|---|
在Node.js中使用pg库时,我希望批量插入如下格式的多行数据:
[ ["vini", "tech", "staff", "ID", "software engineer"], ["vidi", "tech", "CTO", "IN", "software engineer"], ["vici", "HR", "staff", "ID", "people"] ]
原本我可以用模板字符串拼接查询语句,但发现使用pg-format更合适。不过问题在于,当我想要插入带timestamp(使用current_timestamp::timestamp(0))的数据时,pg-format会将该timestamp表达式加上单引号,生成的查询语句如下:
INSERT INTO employees (name, department, position, country, jobdesc, created_at) VALUES ('vini', 'tech', 'staff', 'ID', 'software engineer', 'current_timestamp::timestamp(0)'), ('vidi', 'tech', 'CTO', 'IN', 'software engineer', 'current_timestamp::timestamp(0)'), ('vici', 'HR', 'staff', 'ID', 'people ', 'current_timestamp::timestamp(0)') RETURNING *
而我需要的正确格式是timestamp表达式不加单引号:
INSERT INTO employees (name, department, position, country, jobdesc, created_at) VALUES ('vini', 'tech', 'staff', 'ID', 'software engineer', current_timestamp::timestamp(0)), ('vidi', 'tech', 'CTO', 'IN', 'software engineer', current_timestamp::timestamp(0)), ('vici', 'HR', 'staff', 'ID', 'people ', current_timestamp::timestamp(0)) RETURNING *
请问这种情况下我该如何处理?是否还需要使用pg-format?
解决方法
方案1:继续用pg-format,区分SQL表达式和普通值
pg-format支持通过不同占位符类型区分普通字符串和SQL表达式:用%L处理需要加引号的普通值,用%s处理不需要加引号的SQL表达式。
具体实现代码:
const format = require('pg-format'); const data = [ ["vini", "tech", "staff", "ID", "software engineer"], ["vidi", "tech", "CTO", "IN", "software engineer"], ["vici", "HR", "staff", "ID", "people"] ]; // 给每一行补充timestamp表达式 const dataWithTimestamp = data.map(row => [...row, 'current_timestamp::timestamp(0)']); // 构造占位符模板:前5个字段用%L(自动加引号),最后一个用%s(保留表达式原样) const placeholders = dataWithTimestamp.map(() => '(%L, %L, %L, %L, %L, %s)').join(','); const query = format(`INSERT INTO employees (name, department, position, country, jobdesc, created_at) VALUES ${placeholders} RETURNING *`, ...dataWithTimestamp.flat() );
这样生成的SQL会自动给普通字段加单引号,timestamp表达式则保持原样不加引号。
方案2:改用pg原生参数化查询(更安全)
pg库本身支持批量参数化插入,不需要依赖pg-format,还能彻底避免SQL注入风险,更推荐这种方式:
const { Client } = require('pg'); const client = new Client(/* 你的数据库配置 */); async function batchInsert() { await client.connect(); const data = [ ["vini", "tech", "staff", "ID", "software engineer"], ["vidi", "tech", "CTO", "IN", "software engineer"], ["vici", "HR", "staff", "ID", "people"] ]; // 构造参数占位符,timestamp表达式直接写在SQL里 const placeholders = data.map((_, idx) => `($${idx*5+1}, $${idx*5+2}, $${idx*5+3}, $${idx*5+4}, $${idx*5+5}, current_timestamp::timestamp(0))` ).join(','); const query = `INSERT INTO employees (name, department, position, country, jobdesc, created_at) VALUES ${placeholders} RETURNING *`; const values = data.flat(); const result = await client.query(query, values); console.log(result.rows); await client.end(); } batchInsert();
这里current_timestamp::timestamp(0)直接嵌入SQL语句,不会被当作参数处理,自然不会被加引号;普通数据通过占位符传递,安全性拉满。
要不要继续用pg-format?
如果需要动态生成复杂SQL结构(比如动态指定插入字段),pg-format依然有用;但如果只是普通批量插入,优先用pg原生参数化查询,既能解决引号问题,又更安全。
内容的提问来源于stack exchange,提问作者Muhammad_Vidi
相关产品推荐
相关产品推荐

