2015-12-19 14 views
0

當我運行下面的程序如何保持報價進行正確的SQL查詢

package com.util; 
import java.util.ArrayList; 
public class Test { 
    public static void main(String[] args) throws Exception { 
     ArrayList<String> list_of_symbols = new ArrayList<String>(); 
     list_of_symbols.add("ABB"); 
     list_of_symbols.add("ACC"); 
     list_of_symbols.add("SBIN"); 
     StringBuilder sb_builder = new StringBuilder(); 
     for (int i = 0; i < list_of_symbols.size(); i++) { 
      sb_builder.append(list_of_symbols.get(i) + ","); 
     } 
     String sql = "Select * from data where symbol_name IN (" 
       + sb_builder.deleteCharAt(sb_builder.length() - 1).toString() 
       + ")"; 
     System.out.println(sql); 
    } 
} 

SQL的結果是

Select * from data where symbol_name IN (ABB,ACC,SBIN) 

凡爲預期的結果應該是

Select * from data where symbol_name IN ('ABB','ACC','SBIN') 

請問我可以讓我知道如何保持行情,使其變得有效SQL

+0

只是將'''添加到您的查詢字符串 – Ramanlfc

+0

你不能保留它們,因爲它們不在那裏。你必須添加它們。 –

+3

offtopic:組合字符串使得SQL注入成爲可能,你應該避免這種情況 – svenhornberg

回答

6

請勿使用字符串連接來填充SQL參數。這很容易出錯。相反,根據需要使用盡可能多的?來構建SQL,然後使用PreparedStatement以及儘可能多的setString(x, theString)來填充?

在你的情況下,它看起來大致是這樣的:

package com.util; 
import java.util.ArrayList; 
public class Test { 
    public static void main(String[] args) throws Exception { 
     ArrayList<String> list_of_symbols = new ArrayList<String>(); 
     list_of_symbols.add("ABB"); 
     list_of_symbols.add("ACC"); 
     list_of_symbols.add("SBIN"); 

     // Build the statement 
     StringBuilder sql = new StringBuilder(200); 
     sql.append("Select * from data where symbol_name IN ("); 
     for (int i = 0; i < list_of_symbols.size(); i++) { 
      sql.append(i == 0 ? "?" : ", ?"); 
     } 
     sql.append(')'); 

     // Build the PreparedStatement and fill in the parameters 
     PreparedStatement ps = someConnection.prepareStatement(sql.toString()); 
     for (int i = 0; i < list_of_symbols.size(); i++) { 
      ps.setString(i + 1, list_of_symbols.get(i)); 
     } 

     // Do it 
     ResultSet rs = ps.executeQuery(); 
    } 
} 

(這個是未經優化,並急匆匆有些編輯會要求。)

This site有一個很好的解釋,爲什麼使用字符串連接參數是一個壞主意,以及如何在許多語言中正確地做事情的實際例子,包括Java

+0

編寫安全的SQL [這裏(OWASP注入預防備忘單)](https://www.owasp.org/index.php/ SQL_Injection_Prevention_Cheat_Sheet) –

+0

@Jan:*「(這是未優化的,可能需要一些編輯。)」* –

0

由於你知道我建議把它放在一個列表中的值的數量?每IN值並使其成爲PreparedStatement。

後來乾脆

ps.setString (n, nthString); 

在爲1..1參數的循環,驅動程序將處理正確轉義。

像這樣:

List<String> list_of_symbols = new ArrayList<String>(); 
    list_of_symbols.add("ABB"); 
    list_of_symbols.add("ACC"); 
    list_of_symbols.add("SBIN"); 
    StringJoiner join = new StringJoiner(",", 
      "Select * from data where symbol_name IN (", ")"); 
    for (int i = 0; i < list_of_symbols.size(); i++) { 
     join.add("?"); 
    } 
    PreparedStatement ps = aConnection.prepareStatement(join.toString()); 
    for (int i = 0; i < list_of_symbols.size(); i++) { 
     ps.setString(i+1, list_of_symbols.get(i)); 
    } 
-1

當讓你列表,使用這樣的:

sb_builder.append("'"+list_of_symbols.get(i) + "',"); 

通知的'的字符串。這僅適用於簡單的情況,字符串沒有',並且您並不擔心SQL注入。對於更復雜的情況,使用PreparedStatements並添加一個?的列表。然後用您要使用的字符串替換?

+0

非常感謝,我感到困惑。 – Pawan

+0

@PreethiJain:當然,如果你的字符串中有''',這會失敗。連接參數是*糟糕的做法*,這是最好不要進入的習慣。 –

+0

你的回答很糟糕,因爲你的代碼很容易被SQL注入。 –