Вопрос или проблема
Я пишу SQL-запрос, используя node-firebird с оператором WHERE … IN … и параметризованным массивом, например так:
SELECT * FROM MY_TABLE WHERE MY_FIELD IN ?
И передаю параметр:
[['string1', 'string2']]
Однако это приводит к следующей ошибке:
Dynamic SQL Error, SQL error code = -104, Token unknown - line 1, column 48, ?
(Примечание: имена таблиц и полей в реальной базе данных отличаются, поэтому индекс столбца, упомянутый в ошибке, может быть неточным.)
Что я пробовал:
Оборачивать вопросительный знак в скобки так:
SELECT * FROM MY_TABLE WHERE MY_FIELD IN (?)
Но это вызвало другую ошибку:
Dynamic SQL Error, SQL error code = -303, Арфметическое исключение, числовой переполнение, или обрезка строки, обрезка строки справа
Запросы, не содержащие WHERE … IN …, работают отлично.
Жесткое кодирование значений массива прямо в запрос работает, и использование JetBrains Database Manager для выполнения параметризованного запроса также работает (массив передан как (‘myString1’, ‘myString2’)).
Контекст кода:
Вот немного больше контекста о том, как я выполняю запрос:
pool.get(function (err: any, db) {
if (err) throw err
db.query(
`SELECT * FROM MY_TABLE WHERE MY_FIELD IN ?`,
[['string1', 'string2']],
function (err, result) {
if (err) {
console.error(err)
}
console.debug('result: ' + JSON.stringify(result, null, 2))
db.detach()
}
)
})
Документация и похожие проблемы:
Я проверил документацию node-firebird, но не нашел конкретных упоминаний о параметризованных IN-операторах.
Похожий вопрос был задан в 2018 году на GitHub, но ответа не было: https://github.com/hgourvest/node-firebird/issues/144
Вопрос:
Какой правильный синтаксис для использования оператора WHERE … IN … с параметризованными массивами в node-firebird? Есть ли альтернативный подход для этого?
Ответ или решение
Для использования оператора WHERE ... IN ...
с параметризованными массивами в node-firebird
необходимо учитывать особенности работы с JDBC и SQL в Firebird. К сожалению, прямой передачи массивов через параметры в оператор IN не поддерживается. Вместо этого вам нужно динамически создать строку запроса с использованием параметров.
Вот подход, который поможет решить эту проблему:
-
Сначала нужно подготовить значения, которые вы хотите использовать в операторе IN. Мы создадим строку с заглушками для каждого значения, которые будут подставлены в запрос.
-
После этого, в вашем запросе заменим
?
на количество заглушек, то есть?
для каждого элемента массива. -
Затем создадим массив значений, который будет передан в качестве параметров в метод
db.query()
.
Пример кода:
pool.get(function (err, db) {
if (err) throw err;
const values = ['string1', 'string2'];
// Генерируем строку с вопросительными знаками для каждого элемента массива
const placeholders = values.map(() => '?').join(', ');
// Формируем запрос с полученной строкой
const query = `SELECT * FROM MY_TABLE WHERE MY_FIELD IN (${placeholders})`;
db.query(query, values, function (err, result) {
if (err) {
console.error(err);
}
console.debug('result: ' + JSON.stringify(result, null, 2));
db.detach();
});
});
Пояснение к коду:
- Мы создаем массив
values
, содержащий строки, которые нужно использовать в запросе. - С помощью
map
создаем массив вопросов, где каждый элемент соответствует одному элементу из массиваvalues
, затем объединяем их с помощьюjoin(', ')
в одну строку. - Формируем запрос
query
, вставляя сгенерированную строку с вопросительными знаками в оператор IN. - Вызов
db.query()
теперь принимает сформированный запрос и массив значений.
Таким образом, мы добиваемся корректной работы с оператором IN
, используя параметризованные массивы. Этот способ обеспечивает защиту от SQL-инъекций и повышает читаемость кода.