2013-04-19 2 views
11

Próbuję sprawdzić, czy określona wartość już istnieje w mojej bazie danych. Mam dostęp do bazy danych z autonomicznej aplikacji java przy użyciu JDBC (kwerendy dotyczące wstawiania rekordów do db pracy, więc moja instalacja i połączenie są w porządku).Java MySQL sprawdza, czy wartość istnieje w bazie danych

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; 
} 

otrzymuję ten błąd (tam widocznie coś nie tak z moim składni SQL):

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 

Jednakże jeśli próbuję wykonać tego polecenia w moim wierszu poleceń MySQL, to działa! Czy możesz mi powiedzieć, co jest nie tak z moim oświadczeniem? Dzięki za wszelkie wskazówki!

+2

Proszę, proszę, proszę, zawsze używaj zapytanie wiązania ... nie zawsze tylko ty Zapobiegaj atakom SQL injection, pomagasz także w bazie danych, ponieważ buforuje plan wykonania, co przyspiesza następne zapytanie. –

Odpowiedz

23

Trzeba owinąć String w cudzysłowach w MySQL, więc zapytanie musi być

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

Nie

SELECT * from messages WHERE msgid = d-f05708071f8f; 

Tak kod powinien przeczytać

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

Proponuję za pomocą PreparedStatement aby uniknąć tego rodzaju problemów i ryzyka SQL injection:

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

Korzystanie konkatenacji ciągów dla budynku zapytania jest za bardzo złą praktyką. Od dawna już.

Dalsze Sugerowałbym użyciu select count(*) zamiast pełnej select * jak to zwraca znacznie mniej danych (myślę o wielkości ResultSet) i MySQL może zoptymalizować go zbyt.

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

tak, zapomniałem łączników i testowałem to tylko z liczbami całkowitymi ... moje złe .. dzięki! – Smajl

3

Ponieważ msgid to varchar, musisz otoczyć wartość w klauzuli where pojedynczymi cudzysłowami.

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

Dynamiczne generowanie ciągów SQL nie jest jednak zalecane, ponieważ może narazić twoją aplikację na wtrysk sql.

Zamiast używać PreparedStatement:

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

Musisz użyć zmiennych wiążących.

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

Albo wdaj się w ręczne cytowanie, ale jest to ryzykowne.

Oprócz zapobiegania iniekcji SQL, przygotowane instrukcje powinny również poprawić wydajność, jeśli wielokrotnie uruchamiane jest to samo zapytanie.

+1

+1 dla wiązania zapytań –

1

Trzeba użyć apostrofów

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

Można spróbować to:

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

pominięcia cudzysłowie msgid. (Zakładam, że msgstr jest String i nie Integer wartość.)

+0

Tylko sugestia, gdy odpowiadasz tutaj, jeśli użytkownik łączy ciągi znaków, które mają być użyte do zapytań sql, zawsze polecam 'PreparedStatement' wielu użytkowników od razu ci powie, jeśli tego nie zrobisz, w tej samej notatce dostaniesz trochę upvotes dla wspominania o wtrysku/przygotowaniu sql. –

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)+"')"; 
} 

Wystarczy prosty algorytm duplikat wpisu