PostgreSQL+Typescript如何根据传入JSON动态构造可变SQL增改查询
PostgreSQL + TypeScript 动态字段SQL插入/更新实现
核心思路是通过白名单过滤合法字段,动态拼接SQL片段,避免硬编码字段,同时防止SQL注入。
完整实现代码
import type { QueryResult } from 'pg'; // 若使用pg库可添加该类型定义 // 1. 定义表的允许操作字段白名单,对应user_company_fk表的所有可写字段 const ALLOWED_FIELDS = ['siret', 'name', 'address', 'city'] as const; type AllowedField = typeof ALLOWED_FIELDS[number]; async function operateCompany(param: Record<string, any>): Promise<QueryResult> { // 2. 筛选出合法的、有值的字段 const validEntries = Object.entries(param).filter(([key]): key is [AllowedField, any] => ALLOWED_FIELDS.includes(key as AllowedField) && param[key] !== undefined ); if (validEntries.length === 0) { throw new Error('未传入任何有效字段'); } // 3. 动态生成SQL片段 const columns = validEntries.map(([key]) => `"${key}"`).join(', '); const placeholders = validEntries.map((_, index) => `$${index + 1}`).join(', '); const values = validEntries.map(([_, value]) => value); // 4. 普通插入场景(仅新增数据,未传字段使用表默认值) return db.query(` INSERT INTO user_company_fk (${columns}) VALUES (${placeholders}) `, values); // --- 若需要「存在则更新传入字段、不存在则插入」的UPSERT逻辑,替换上方查询即可 --- // const updateSet = validEntries.map(([key], index) => `"${key}" = $${index + 1}`).join(', '); // return db.query(` // INSERT INTO user_company_fk (${columns}) // VALUES (${placeholders}) // ON CONFLICT (siret) DO UPDATE SET ${updateSet} // `, values); }
特性说明
- 完全匹配需求:仅处理用户传入的合法字段,未传入的字段不会被操作,插入时使用表默认值,更新时保留原有值
- 可扩展性强:后续需要新增支持的字段,只需在
ALLOWED_FIELDS数组中添加对应列名即可 - 安全:白名单机制完全规避SQL注入风险,所有值通过参数化查询传入,不会直接拼接到SQL中
内容的提问来源于stack exchange,提问作者Matthieu
相关产品推荐
相关产品推荐

