Ответ 1
Имя таблицы нельзя использовать в качестве параметра. Он должен быть жестко закодирован. Поэтому вы можете сделать что-то вроде:
private String query1 = "SELECT plantID, edrman, plant, vaxnode FROM [" + reportDate + "?]";
Я пытаюсь использовать подготовленные инструкции для установки имени таблицы для выбора данных, но при выполнении запроса я получаю сообщение об ошибке.
Ниже приведен пример кода ошибки и примера.
[Microsoft][ODBC Microsoft Access Driver] Parameter 'Pa_RaM000' specified where a table name is required.
private String query1 = "SELECT plantID, edrman, plant, vaxnode FROM [?]"; //?=date
public Execute(String reportDate){
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection conn = DriverManager.getConnection(Display.DB_MERC);
PreparedStatement st = conn.prepareStatement(query1);
st.setString(1, reportDate);
ResultSet rs = st.executeQuery();
Любые мысли о том, что может быть причиной этого?
Имя таблицы нельзя использовать в качестве параметра. Он должен быть жестко закодирован. Поэтому вы можете сделать что-то вроде:
private String query1 = "SELECT plantID, edrman, plant, vaxnode FROM [" + reportDate + "?]";
Это технически возможно с обходным путем, но очень плохая практика.
String sql = "IF ? = 99\n";
sql += "SELECT * FROM first_table\n";
sql += "ELSE\n";
sql += "SELECT * FROM second_table";
PreparedStatement ps = con.prepareStatement(sql);
И затем, когда вы хотите выбрать из first_table, вы устанавливаете параметр с помощью
ps.setInt(1, 99);
Или, если нет, вы установите его на что-то еще.
Как сказал ряд людей, вы не можете использовать параметр оператора для имени таблицы, только для переменных как часть условия.
Исходя из того факта, что у вас есть имя таблицы переменных с (по крайней мере) двумя именами таблиц, возможно, было бы лучше создать метод, который берет объект, который вы храните, и возвращает подготовленный оператор.
PreparedStatement p = createStatement(table);
Это может помочь:
public ResultSet getSomething(String tableName) {
PreparedStatement ps = conn.prepareStatement("select * from \'"+tableName+"\'");
ResultSet rs = ps.executeQuery();
}
Если вам нужно решение, которое не уязвимо для SQL-инъекций, вам нужно продублировать запрос для всех необходимых вам таблиц:
final static String QUERIES = {
"SELECT x FROM Table1 x WHERE a=:a AND b=:b AND ...",
"SELECT x FROM Table2 x WHERE a=:a AND b=:b AND ...",
"SELECT x FROM Table3 x WHERE a=:a AND b=:b AND ...",
...
};
И да: запросы являются дубликатами, и отличается только имя таблицы.
Теперь вы просто выбираете запрос, который соответствует вашей таблице, например, как
...
PreparedStatement st = conn.prepareStatement(QUERIES[index]);
...
Вы можете использовать этот подход с JPA, Hibernate, что угодно...
Если вы хотите более подробный подход, подумайте об использовании перечисления типа
enum AQuery {
Table1("SELECT x FROM Table1 x WHERE a=:a AND b=:b AND ..."),
Table2("SELECT x FROM Table2 x WHERE a=:a AND b=:b AND ..."),
Table3("SELECT x FROM Table3 x WHERE a=:a AND b=:b AND ..."),
...
private final String query;
AQuery(final String query) {
this.query = query;
}
public String getQuery() {
return query;
}
}
Теперь используйте индекс
String sql = AQuery.values()[index].getQuery();
PreparedStatement st = conn.prepareStatement(sql);
...
Или используйте имя таблицы
String sql = AQuery.valueOf("Table1").getQuery();
PreparedStatement st = conn.prepareStatement(sql);
...
Я не уверен, что вы можете использовать PreparedStatement для указания имени таблицы, просто значения некоторых полей. В любом случае, вы можете попробовать один и тот же запрос, но без скобок:
"SELECT plantID, edrman, plant, vaxnode FROM ?"
String table="pass";
String st="select * from " + table + " ";
PreparedStatement ps=con.prepareStatement(st);
ResultSet rs = ps.executeQuery();
Существует способ передать имя таблицы как переменную
Строка NameOfTable = "test.Employee";
String Fquery = "SELECT * FROM" + NameOfTable + ", где Done = 'No'";
Примечание: должно быть пространство между FROM и последующим "а также между" и где ключевое слово