2016-12-29 108 views
0

我有一個程序,從數據庫中選擇一個表和列字符串。SQLite查詢參數不工作在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()); 
     } 
    } 

出於某種原因,它不工作,這是正確的要

下面是connect()函數,以及:

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

好奇...爲什麼你會甚至懶得去通過所有的爛攤子時,它容易得多隻是地方您的變量直接作爲@Gurwinder Singh建議的SQL字符串。 – 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); 
}