2013-04-19 57 views
11

特定の値が既にデータベースに存在するかどうかを確認しようとしています。私はJDBCを使用してJavaスタンドアロンアプリケーションからデータベースにアクセスしています(レコードをdbワークに挿入するためのクエリで、セットアップと接続が正常です)。Java MySQLがデータベースに値が存在するかどうかを調べる

String queryCheck = "SELECT * from messages WHERE msgid = " + msgid; 
Statement st = conn.createStatement(); 
ResultSet rs = st.executeQuery(queryCheck); // execute the query, and get a java resultset 

// if this ID already exists, we quit 
if(rs.absolute(1)) { 
    conn.close(); 
    return; 
} 

私は(私のSQL構文と間違って何かが明らかに存在している)、このエラーを取得しています:私は私のMySQLのコマンドラインで次のコマンドを実行しようとした場合

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'd-f05708071f8f' at line 1 

しかし、それは動作します!あなたは私の声明に間違っていることを教えてくれますか?あらゆるヒントありがとう!

+2

してください、、、常にだけでなく、常に...あなたを結合クエリを使用してくださいしてくださいSQLインジェクション攻撃を防ぐために、実行計画をキャッシュするときにデータベースを助けて、次のクエリを高速化します。 –

答えて

23

クエリだから

SELECT * from messages WHERE msgid = 'd-f05708071f8f'; 

ない

SELECT * from messages WHERE msgid = d-f05708071f8f; 

にする必要があるので、あなたは、MySQLでの引用符でStringをラップする必要がありますコードを読み取る必要があります

私は問題のこれらの種類とSQLインジェクションのリスクを回避するために PreparedStatementを使用することをお勧めし
String queryCheck = "SELECT * from messages WHERE msgid = '" + msgid + "'"; 

final String queryCheck = "SELECT * from messages WHERE msgid = ?"; 
final PreparedStatement ps = conn.prepareStatement(queryCheck); 
ps.setString(1, msgid); 
final ResultSet resultSet = ps.executeQuery(); 

クエリの構築のための文字列の連結を使用しては非常に悪い習慣と考えられています。長い間ずっと続いてきました。

さらに私は、これははるかに少ないデータを返すようフルselect *ではなくselect count(*)を使用することをお勧めし(ResultSetの大きさを考える)とMySQLは、あまりにもそれを最適化することができます。

final String queryCheck = "SELECT count(*) from messages WHERE msgid = ?"; 
final PreparedStatement ps = conn.prepareStatement(queryCheck); 
ps.setString(1, msgid); 
final ResultSet resultSet = ps.executeQuery(); 
if(resultSet.next()) { 
    final int count = resultSet.getInt(1); 
} 
+0

うん、ハイフンを忘れて、整数でしかテストしていなかった...私の悪い..ありがとう! – Smajl

3

msgidはvarcharなので、where句の値を一重引用符で囲む必要があります。

String queryCheck = "SELECT * from messages WHERE msgid = '" + msgid + "'"; 

SQL文字列を動的に生成することは、アプリケーションをSQLインジェクションに公開する可能性があるため推奨されません。

代わりPreparedStatementを使用します。

  String queryCheck = "SELECT * from messages WHERE msgid = ?"; 
      PreparedStatement st = conn.prepareStatement(queryCheck); 
      st.setString(1, msgid); 
      ResultSet rs = st.executeQuery(); 
5

バインド変数を使用する必要があります。

PreparedStatement st = conn.prepareStatement(
    "SELECT * from messages WHERE msgid = ?"); 
st.setString(1, msgid); 
ResultSet rs = st.executeQuery(queryCheck); 

または、引用符を付けるのは危険です。

SQLインジェクションを防止することに加えて、同じクエリを繰り返し実行すると、プリペアドステートメントでもパフォーマンスが向上するはずです。

"SELECT * FROM messages WHERE msgid = '" + msgid + "'"; 

それとも、より良いあなたがprepared statementsを使用します。

+1

+1クエリバインドの場合 –

3

使用単一引用符は、パラメータをarount。MSGID周り

String queryCheck = "SELECT * from messages WHERE msgid = '" + msgid + "'"; 

あなたが見逃している引用符を:あなたはこれを試すことができ

1

あなたは、単一引用符

SELECT * from messages WHERE msgid = 'd-f05708071f8f'; 
3

を使用する必要があります。 (私はMSGIDStringないInteger値であると仮定しています。)

+0

SQLクエリに使用する文字列をユーザーが連結している場合は、常にPreparedStatementを使用することをお勧めします。多くのユーザーが同じノートで即座にダウンボートしますあなたはSQLインジェクション/ preparedstatementsに言及するためにいくつかのアップフォースを得るでしょう。 –

0
String sql1 ="SELECT Time FROM monday_wednesday WHERE Time ='"+time.getSelectedItem()+"'"; 
pst=con.prepareStatement(sql1); 
rs=pst.executeQuery(); 
if(rs.next()) { 
    if(rs.getString("Time").equals(time.getSelectedItem())) { 
     JOptionPane.showMessageDialog(null,"Time is already taken","",JOptionPane.INFORMATION_MESSAGE); 
    } 
} else { 
    String sql="INSERT INTO monday_wednesday(pfname,pmname,plname,Birthdate,Gender,Address,City,Contact,Contactperson,Time,Date)\n" + "VALUES ('"+txtFirstName1.getText()+"','"+txtMiddleName1.getText()+"','"+txtLastName1.getText()+"','"+d+"','"+gender.getSelectedItem()+"','"+ txtAddress.getText()+"','"+txtCity.getText()+"','"+txtContact.getText()+"','"+txtContactPerson1.getText()+"','"+time.getSelectedItem()+"','"+dateFormat.format(date)+"')"; 
} 

だけの単純な重複エントリアルゴリズムは

関連する問題