2016-12-29 2 views
0

У меня есть программа, которая выбирает из базы данных данные таблицы и столбца.SQLite Query с параметрами, не работающими в Java

public void selectAllFrom(String table, String column){ 
     String sql = "SELECT ? FROM ?"; 

     try (Connection conn = this.connect(); 
      PreparedStatement pstmt = conn.prepareStatement(sql)){ 
      pstmt.setString(1, column); 
      pstmt.setString(2, table); 

      ResultSet rs = pstmt.executeQuery(); 

      while (rs.next()){ 
       System.out.println(rs.getString(column)); 
      } 

     } catch (SQLException e){ 
      System.out.println(" select didn't work"); 
      System.out.println(e.getMessage()); 
     } 
    } 

По какой-то причине он не работает, и это происходит прямо на улов

Вот подключение функции(), а также:

private Connection connect(){ 
    Connection conn = null; 
    // SQLite connection string 
    String url = "jdbc:sqlite:C:/sqlite/db/chinook.db"; 

    try{ 
    // creates connection to the database 
    conn = DriverManager.getConnection(url); 
    System.out.println("Connection to SQLite has been established"); 
    } catch (SQLException e){ 
     System.out.println(e.getMessage()); 
     System.out.println("Connection didn't work"); 
    } 

    return conn; 
} 

Я знаю, что проблема заключается не в с базой данных, потому что я могу запускать другие запросы выбора без параметров. Это параметры, которые дают мне проблему. Может ли кто-нибудь сказать, в чем проблема?

+0

Любопытный ... Почему бы вам даже потрудился пройти через все это беспорядок, когда это гораздо проще просто место ваши переменные непосредственно в строку SQL, как предложил @Gurwinder Singh. – DevilsHnd

ответ

1

Имя таблицы или столбца не может использоваться как параметр для PreparedStatement. Он должен быть жестко закодирован.

String sql = "SELECT " + column + " FROM " + table; 

Вы должны пересмотреть конструкцию, чтобы сделать эти две константы и параметризовать значения столбцов.

0

? является держателем места, указывающим переменную связывания. Когда выполняется инструкция SQL, база данных сначала проверяет синтаксис и проверяет ссылки на объекты, столбцы и права доступа для определенных объектов (т. Е. Метаданные об объектах) и подтверждает, что все они на месте и действительны. Этот этап называется синтаксическим разбором.

Последующий синтаксический анализ, он заменяет переменные связывания на запрос и затем выполняет фактический выбор результатов.

Переменные связывания могут быть заменены в любом месте запроса, чтобы заменить фактические жестко закодированные данные/строки, но запрос не создает их самих. Это означает, что

  • Вы не можете использовать переменные связывания для ключевых слов SQL-запрос (например: SELECT, UPDATE и т.д.)
  • Вы не можете использовать переменные связывания объектов или их атрибутов (т.е. имена таблиц, имена столбцов, функции, процедуры и т. д.)
  • Вы можете использовать их только вместо данных, жестко закодированных иначе.

например: SELECT FIRST_NAME, LAST_NAME, 'N' IS_DELETED FROM USER_DATA WHERE COUNTRY ='CANADA' AND VERIFIED_USER='YES' В приведенном выше запросе выборки 'N', 'CANADA' и 'YES' являются только строки, которые могут быть заменены переменной связывания, а не любое другое слово.

Использование переменной привязки - лучшая практика кодирования. Это улучшает производительность запросов (при использовании с большим количеством запросов в настроенных продуктах базы данных, таких как Oracle или MSSQL), а также защищает ваш код от атак sql injection.

Построение запроса путем конкатенации строк (особенно части данных запроса) никогда не рекомендуется. Вы все равно можете построить запрос путем конкатенации для других частей, таких как имя таблицы или имя столбца, пока эти строки не будут непосредственно взяты из ввода.

Ниже пример приемлемо:

query = "Select transaction_id, transaction_date from "; 
if (isHistorical(reportType) 
    { query = query + "HISTORY_TRANSACTIONS" ;} 
else 
    {query = query + "PRESENT_TRANSACTIONS" ; } 

рекомендуемая практика заключается в использовании

String query_present = "SELECT transaction_id, transaction_date from PRESENT_TRANSACTIONS"; 
String query_historical = "SELECT transaction_id, transaction_date from HISTORY_TRANSACTIONS"; 

if (isHisotrical(reportType)) 
{ 
    ps.executeQuery(query_historical); 
}else{ 
    ps.executeQuery(query_present); 
} 
Смежные вопросы