SQLite语法错误排查:自定义Wrapper插入JSON字符串报错
问题原因分析
你的语法错误根源是直接拼接SQL字符串并手动用双引号包裹值,当JSON序列化后的字符串包含双引号时,会破坏SQL语句的结构:
比如你传入的JSON是{"name":"hii","tetst":"thisis a test"},手动用双引号包裹后变成"{"name":"hii","tetst":"thisis a test"}",SQL解析器会把第一个"之后的{当作合法内容,遇到name时就会触发语法错误——因为此时SQL认为这是一个未定义的标识符。
同时这种写法存在严重的SQL注入风险,任何包含特殊字符的字符串都可能破坏SQL结构,甚至被恶意利用。
解决方法:使用参数化查询
sqlite3原生支持参数化查询(占位符?),驱动会自动处理值的转义与类型转换,彻底避免语法错误和注入问题。修改你的insert方法如下:
export class sqlite3Wrapper { #connection; #run; #get; constructor(dbName: string) { this.#connection = new sqlite3.Database(dbName); this.#run = promisify(this.#connection.run.bind(this.#connection)); this.#get = promisify(this.#connection.get.bind(this.#connection)); } async insert(table: string, { fields, values, object, updateOnDuplicate = false }: { fields?: string | string[]; values?: any | any[]; object?: { [key: string]: any }; updateOnDuplicate?: boolean }): Promise<any> { let f = object ? Object.keys(object) : fields; let v = object ? Object.values(object) : values; if (!f || !v) throw new Error("Fields can't be empty"); if (!Array.isArray(v)) { v = [values as any]; } if (!Array.isArray(f)) { f = [fields as string]; } if (f.length !== v.length) throw new Error("Fields and values must be the same length"); // 构建占位符字符串,比如 [?, ?] const placeholders = f.map(() => '?').join(', '); let sql = `INSERT INTO ${table} (${f.join(', ')}) VALUES (${placeholders})`; const params = [...v]; // 处理更新逻辑:SQLite不支持ON DUPLICATE KEY UPDATE,需用ON CONFLICT DO UPDATE if (updateOnDuplicate) { // 构建SET部分的占位符,比如 field1 = ?, field2 = ? const updateClauses = f.map(field => `${field} = ?`).join(', '); sql += ` ON CONFLICT DO UPDATE SET ${updateClauses}`; // 将更新值追加到参数数组 params.push(...v); } return await this.#run(sql, params); } }
关键修改点说明
- 参数化占位符:用
?代替直接拼接值,所有值都作为参数数组传给#run方法,驱动会自动处理转义,包括JSON字符串里的双引号。 - SQLite冲突更新修正:SQLite不支持MySQL的
ON DUPLICATE KEY UPDATE,需替换为ON CONFLICT DO UPDATE(注意:你需要确保表中有唯一约束,比如id字段是主键或唯一索引,否则该语句不会生效)。 - 避免手动字符串拼接:彻底移除了手动判断值类型并添加引号的逻辑,由驱动统一处理类型转换。
验证调用
你的原有调用代码无需修改,直接使用即可:
const obj = { name: "hii", tetst: "thisis a test" }; const theJsonFile = JSON.stringify(obj); console.log(theJsonFile); await db.insert("jsonTest", { fields: ["id", "value"], values: ["3", theJsonFile] });
内容的提问来源于stack exchange,提问作者Yoru
相关产品推荐
相关产品推荐

