Использование подготовленных инструкций для задания имени таблицы
Я пытаюсь использовать подготовленные инструкции для задания имени таблицы для выбора данных, но я продолжаю получать сообщение об ошибке при выполнении запроса.
Ошибка и пример кода показаны ниже.
[Microsoft][ODBC Microsoft Access Driver] Parameter 'Pa_RaM000' specified where a table name is required.
Вы не можете задать имя таблицы в подготовленном операторе
Как говорилось ранее, невозможно задать имя таблицы в подготовленном операторе с помощью preparedStatement.setString(1, tableName). Также невозможно добавить части SQL-запроса в подготовленную инструкцию (например preparedStatement.addSql(" or xyz is null")).
Как сделать это правильно, не рискуя SQL-инъекциями?
Имя таблицы должно быть вставлено в SQL (или JQL) запрос, который вы хотите выполнить со строковыми операциями, такими как "select * from " + tableName или String.format("select * from %s", tableName)
Но как избежать SQL-инъекций?
Если имя таблицы получено не из пользовательского ввода, вы, вероятно, в безопасности. Например, если вы принимаете решение, подобное приведенному здесь
Если имя таблицы зависит от пользовательского ввода, вам нужно проверить ввод вручную. Например, с помощью белого списка, содержащего все допустимые имена таблиц:
if(!tableNamesWhitelist.contains(tableName)) { thrownew IllegalArgumentException(tableName + " is not a valid table name"); } String sqlQuery = "delete from " + tableName;
а затем преобразуйте введенную пользователем строку типа ANIMAL в Table.ANIMAL. Выдается исключение, если не существует подходящего значения перечисления.
например
@DeleteMapping("/{table}") publicStringdeleteByEnum(@PathVariable("table") Table table) { final String sqlQuery = "delete from " + table.getSqlTableName(); ... }
Конечно, эти примеры также работают с select, update, ... и возможно множество других реализаций для проверки пользовательского ввода.
Ответ 3
Это технически возможно с обходным путем, но очень плохая практика.
А затем, когда вы хотите выбрать из first_table, вы устанавливаете параметр с помощью
ps.setInt(1, 99);
Или, если нет, вы задаете ему что-то другое.
Ответ 4
Как говорили многие люди, вы не можете использовать параметр инструкции для имени таблицы, только для переменных как часть условия.
Исходя из того факта, что у вас есть переменная table name с (как минимум) двумя именами таблиц, возможно, было бы лучше создать метод, который принимает объект, который вы храните, и возвращает подготовленную инструкцию.