Как использовать оператор WHERE … IN … с параметризованными массивами в node-firebird?

Вопрос или проблема

Я пишу 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 не поддерживается. Вместо этого вам нужно динамически создать строку запроса с использованием параметров.

Вот подход, который поможет решить эту проблему:

  1. Сначала нужно подготовить значения, которые вы хотите использовать в операторе IN. Мы создадим строку с заглушками для каждого значения, которые будут подставлены в запрос.

  2. После этого, в вашем запросе заменим ? на количество заглушек, то есть ? для каждого элемента массива.

  3. Затем создадим массив значений, который будет передан в качестве параметров в метод 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-инъекций и повышает читаемость кода.

Оцените материал
Добавить комментарий

Капча загружается...