2013-02-11 57 views
1

我想在我的SQL查詢中動態地綁定變量,我試圖通過java執行。在SQL中的動態綁定

對於這一點,我成功地構建使用數據下面的查詢綁定:

select HOST,PORT, VIRTUAL_HOST, CLUSTER from XYZ where TYPE='abc' and NAME=? 

但對於像查詢:

select HOST, PORT, VIRTUAL_HOST, CLUSTER from PQR where TYPE='abc' and NAME IN (?) 

如何使用動態的陳述結合? 這裏,我有與我的綁定變量的值是用逗號分隔的值,如姓名(I,J,K)

其中,i已經有一個參數的字符串: 字符串溫度=「I,J ,K」。

回答

1

其實你可以動態地這樣來做:

StringBuilder scmd = new StringBuilder (128); 
    scmd.append ("SELECT HOST, PORT, VIRTUAL_HOST, CLUSTER "); 
    scmd.append ("FROM PQR "); 
    scmd.append ("WHERE TYPE='abc' "); 
    if (names.length > 0) { 
    scmd.append ("AND NAME IN ("); 
    for (int i = 0; i < names.length; i++) { 
     if (i > 0) 
     scmd.append (','); 
     scmd.append ('?'); 
    } 
    scmd.append (")"); 
    } 
    PreparedStatement stmt = connection.prepareStatement(scmd.toString()); 

其中names是一個包含可變數量值的字符串數組。

然後,您可以分配值:

if (names.length > 0) { 
    for (int i = 0; i < names.length; i++) { 
     stmt.setString (i + 1, names[i]); 
    } 
    } 
5

你需要每個元素一個問號,廣告有沒有辦法解決它(除非使用一個封裝API,如Spring JDBC這會爲你):

String sql = "select HOST, PORT, VIRTUAL_HOST, CLUSTER" 
      + " from PQR where TYPE='abc' and NAME IN (?, ?, ?)"; 
PreparedStatement stmt = connection.prepareStatement(sql); 
stmt.setString(1, "I"); 
stmt.setString(2, "J"); 
stmt.setString(3, "K"); 
+0

爲什麼這不被標記爲接受?驚訝! – javabot 2015-05-08 10:46:37

2

你也可以寫你自己的解決方法來完成相同的JDBC NamedParameterStatement:

public class NamedParameterStatement { 

    // define the parameter format as a colon followed by at least one word letter 
    private final String PARAMETER_REGEX =":\\w+"; 

    // the parsed sql query string containing question marks, 
    // not named parameters 
    private String sql; 

    // hashtables for parameter mapping 
    private Hashtable<String, Integer> parameterNameMap; 
    private Hashtable<Integer, Object> parameterValueMap; 



    /** 
    * constructor for named parameter statements 
    * @param namedParameterSQL the sql query with named parameters 
    */ 
    public NamedParameterStatement(String namedParameterSQL) { 
     // init hashtables 
     this.parameterNameMap = new Hashtable<String, Integer>(); 
     this.parameterValueMap = new Hashtable<Integer, Object>(); 

     // create a matcher for the named parameter sql query based on 
     // the pattern specified for the named parameter format 
     Matcher m = Pattern.compile(
       PARAMETER_REGEX, 
       Pattern.CASE_INSENSITIVE) 
       .matcher(namedParameterSQL); 
     int i = 1; 
     while(m.find()) { 
      // watch out: this implementation does not check 
      // for multiple parameters with the same name. 
      parameterNameMap.put(m.group().replace(":", ""), i++); 
     } 
     // replace all named parameters with question marks 
     this.sql = m.replaceAll("?"); 
    } 



    /** 
    * creates a prepared statement for the specified connection, 
    * based on the parameter mapping 
    * @param conn the database connection 
    * @return a prepared statement 
    * @throws SQLException thrown on error with preparing the statement 
    * @throws InvalidBindingException thrown on errors with the parameter binding 
    */ 
    public PreparedStatement createPreparedStatement(Connection conn) 
      throws SQLException, InvalidBindingException { 
     // check if bindings match 
     if(parameterNameMap.size() == parameterValueMap.size()) { 
      // create prepared statement 
      PreparedStatement ps = conn.prepareStatement(this.sql); 
      // for each parameter binding, set the parameter and its index accordingly 
      for(Integer i : this.parameterValueMap.keySet()) { 
       Object value = this.parameterValueMap.get(i); 
       // map the parameter object types against the different parameter setters 
       // this mapping is incomplete!!! just a proof of concept. 
       if(value.getClass() == String.class) { 
        ps.setString(i, (String) value); 
       } else if(value.getClass() == Integer.class || value.getClass() == int.class) { 
        ps.setInt(i, (int) value); 
       } else if(value.getClass() == Double.class || value.getClass() == double.class) { 
        ps.setDouble(i, (double) value); 
       } else if(value.getClass() == Long.class || value.getClass() == long.class) { 
        ps.setLong(i, (long) value); 
       } 
      } 
      return ps; 
     } 
     else throw new InvalidBindingException("Not all parameters were bound."); 
    } 



    /** 
    * returns the converted prepared statement query string 
    * @return the query string 
    */ 
    public String getSQL() { 
     return this.sql; 
    } 



    /** 
    * binds a parameter value to a parameter name 
    * @param parameter the parameter name 
    * @param value the parameter value 
    */ 
    public void bindParameter(String parameter, Object value) { 
     // check if the parameter name existed in the named parameter query string 
     if(this.parameterNameMap.containsKey(parameter)) { 
      this.parameterValueMap.put((Integer)this.parameterNameMap.get(parameter), value); 
     } 
     else throw new IllegalArgumentException("Parameter '" + parameter + "' does not exist."); 
    } 

} 

用法:

NamedParameterStatement nps = new NamedParameterStatement(
    "SELECT * FROM table WHERE column1=:param1 AND column2=:param2"); 
nps.bindParameter("param1", "value1"); 
nps.bindParameter("param2", 2); 
PreparedStatement ps = nps.createPreparedStatement(conn); 
ResultSet results = ps.executeQuery(); 
while(results.next()) { 
    System.out.println(results.getString("column1")); 
} 

我知道,這也不是很理想,但是如果你不想使用JDBC或其他呃框架(Hibernate,...)。