У меня есть следующая таблица базы данных:
CREATE TABLE IF NOT EXISTS notes
(id SERIAL PRIMARY KEY, board_id INT NOT NULL, note_type INT NOT NULL, note_location VARCHAR(150),
note_property VARCHAR(100), text TEXT, meta VARCHAR(150),
UNIQUE (id, board_id), FOREIGN KEY (board_id) REFERENCES boards(id));
У меня есть многострочный оператор вставки, использующий параметризованные значения, который выглядит так:
INSERT INTO notes(board_id, note_type, note_location, note_property, text, meta) VALUES ($1, $2, $3, $4, $5, $6), ($7, $8, $9, $10, $11, $12), (..);
Это загружается массивом значений, обрабатываемым for-l oop. Теперь это работает как есть, и я могу добавить большое количество строк одновременно в один запрос.
Теперь я пытаюсь сделать то же самое для оператора UPDATE, который разделяет большую часть кода с оператором INSERT builder:
const args: string[] = [];
let argNum = 1;
let sql = `UPDATE notes AS n SET board_id = c.board_id, note_type = c.note_type, note_location = c.note_location, note_property = c.note_property, text = c.text, meta = c.meta FROM (VALUES`;
for (let i = 0; i < pBoardObj.length; i++) {
args.push(pBoardObj[i].dbId);
args.push(boardId);
args.push(pBoardObj[i].class);
const notLoc = {x: pBoardObj[i].position.x, y: pBoardObj[i].position.y, z: pBoardObj[i].position.z};
args.push(JSON.stringify(notLoc));
const notProp: {[k: string]: any} = {};
notProp.type = pBoardObj[i].type;
notProp.textSize = pBoardObj[i].textSize;
if (pBoardObj[i].scale) {
notProp.scale = pBoardObj[i].scale;
}
args.push(JSON.stringify(notProp));
const text = pBoardObj[i].text || '';
args.push(text);
args.push('');
sql += `($${argNum}, $${argNum += 1}, $${argNum += 1}, $${argNum += 1}, $${argNum += 1}, $${argNum += 1}, $${argNum += 1})`;
sql += ((i < pBoardObj.length - 1) ? ', ' : '');
argNum += 1;
}
sql += `) AS c(id, board_id, note_type, note_location, note_property, text, meta) WHERE c.id = n.id;`;
const pgDbQuery = await this.pgdb.query(sql, args);
Это многострочный оператор обновления, основанный на этот ответ здесь , обновленный, поэтому окончательный запрос должен привести к примерно такому результату с массивом в качестве входных данных.
UPDATE notes AS n SET board_id = c.board_id,note_type = c.note_type,note_location = c.note_location,note_property = c.note_property,text = c.text,meta = c.meta
FROM (VALUES($1, $2, $3, $4, $5, $6, $7), ($8, $9, $10, $11, $12, $13, $14)) AS c(id, board_id, note_type, note_location, note_property, text, meta)
WHERE c.id = n.id;
Но для этого запроса я получаю эту ошибку:
error: operator does not exist: text = integer
No operator matches the given name and argument type(s). You might need to add explicit type casts.
Если попытаться изменить args
с string
на any
, в надежде, что тип будет сохранились. Я также изменил тип параметра функции приема на any
. Я даже попытался изменить массив параметров так, чтобы он представлял собой массив объектов, а не просто значений ({id: number, board_id: number, note_type: number, etc}
).
Пока не повезло. Ничего из того, что я пробовал, не обходилось без этой ошибки, которую я даже полностью не понимаю. Первоначально это был простой запрос на замену строки c, который работал до тех пор, пока нам не потребовалась специальная обработка символов, где он не удался. Я также понимаю, что такой подход может иметь некоторые проблемы с безопасностью.
Следует отметить, что проект, над которым я работаю, находится на стадии бета-тестирования, и это в основном для демонстрационных целей, и поэтому мы не совсем заинтересован в добавлении пакетов или библиотек слева и справа, чтобы решить эту проблему (в будущем мы, возможно, даже не go с postgres).
Могу ли я что-нибудь сделать, чтобы исправить это?