Używanie znaku wieloznacznego „like” w przygotowanej instrukcji

176

Do wykonywania zapytań do bazy danych mysql używam przygotowanych instrukcji. Chcę wdrożyć funkcję wyszukiwania opartą na pewnego rodzaju słowach kluczowych.

W tym celu muszę użyć LIKEsłowa kluczowego, tyle wiem. I już wcześniej korzystałem z przygotowanych instrukcji, ale nie wiem, jak tego użyć, LIKEponieważ z poniższego kodu gdzie miałbym dodać 'keyword%'?

Czy mogę go bezpośrednio użyć w pstmt.setString(1, notes)as (1, notes+"%")lub coś takiego. Widzę wiele postów na ten temat w Internecie, ale nigdzie nie ma dobrej odpowiedzi.

PreparedStatement pstmt = con.prepareStatement(
      "SELECT * FROM analysis WHERE notes like ?");
pstmt.setString(1, notes);
ResultSet rs = pstmt.executeQuery();
ssn
źródło

Odpowiedzi:

281

Musisz ustawić go w samej wartości, a nie w przygotowanym ciągu SQL instrukcji.

Tak więc powinno to wystarczyć dla dopasowania przedrostka:

notes = notes
    .replace("!", "!!")
    .replace("%", "!%")
    .replace("_", "!_")
    .replace("[", "![");
PreparedStatement pstmt = con.prepareStatement(
        "SELECT * FROM analysis WHERE notes LIKE ? ESCAPE '!'");
pstmt.setString(1, notes + "%");

lub dopasowanie sufiksu:

pstmt.setString(1, "%" + notes);

lub mecz globalny:

pstmt.setString(1, "%" + notes + "%");
BalusC
źródło
18
+1 OP może „ustawić” to w SQL - jak przez ... LIKE '%' || ? || '%'lub podobnie - ale to jest znacznie mniej elastyczne.
pilcrow
jak to zrobić w trybie BEZ LITER WRAŻLIWYCH? :)
Alpha Gabriel V. Timbol
2
Bez rozróżniania wielkości liter można nadal używać WHERE UPPER(?) LIKE UPPER(?)podczas korzystaniapstmt.setString(2, "%" + notes + "%")
Zig
1
@Alain: Dziękuję. Zastanawiam się tylko, czy dotyczy to wszystkich RDBMS, których świat jest świadomy? Może '%' || ? || '%'jak wspomniano w 1 komentarzu, mimo wszystko było lepiej? Nie mam teraz okazji eksperymentować.
BalusC
2
@BalusC dotyczy to MSSQL, Postgres i MySQL w moich testach. Ciąg znaków przekształcony w parametr jest sam w sobie interpretowany jako połączenie danych i instrukcji sterujących. Konkatenacja SQL ma miejsce, zanim zostanie zinterpretowana i zachowuje lukę. IEEE Center for Secure Design zaleca ściśle oddzielne dane i instrukcje kontrolne oraz nigdy nie przetwarza instrukcji kontrolnych otrzymanych z niezaufanych źródeł .
Alain O'Dea
28

Zakoduj to w ten sposób:

PreparedStatement pstmt = con.prepareStatement(
    "SELECT * FROM analysis WHERE notes like ?");
pstmt.setString(1, notes + "%");`

Upewnij się, że NIE WIESZ cudzysłowów '' jak poniżej, ponieważ spowodują one wyjątek.

pstmt.setString(1,"'%"+ notes + "%'");
Weselny Wilk
źródło
1
Chociaż wydaje się, że ktoś nie wpadnie na to założenie, w rzeczywistości jest to bardzo ważne, zwłaszcza podczas pracy z Oracle. Dzięki za wskazanie!
asgs
5

możemy to w prosty sposób zrobić, używając funkcji CONCATE SQL.

PreparedStatement pstmt = con.prepareStatement(
      "SELECT * FROM analysis WHERE notes like CONCAT( '%',?,'%')";
pstmt.setString(1, notes);
ResultSet rs = pstmt.executeQuery();

to działa idealnie w moim przypadku.

Basharat Ali
źródło
4
PreparedStatement ps = cn.prepareStatement("Select * from Users where User_FirstName LIKE ?");
ps.setString(1, name + '%');

Wypróbuj to.

Faiz
źródło
1
String fname = "Sam\u0025";

PreparedStatement ps= conn.prepareStatement("SELECT * FROM Users WHERE User_FirstName LIKE ? ");

ps.setString(1, fname);
Ram Kumar
źródło
2
Czy mógłbyś raczej rozwinąć odpowiedź, niż tylko udzielić odpowiedzi? Zobacz: stackoverflow.com/help/how-to-answer
Edwin
-13
String query="select * from test1 where "+selected+" like '%"+SelectedStr+"%';";


PreparedStatement preparedStatement=con.prepareStatement(query);


// where seleced and SelectedStr are String Variables in my program
mahesh dhote
źródło
jest niebezpieczna, prosimy o użycie sparametryzowanego przygotowanego oświadczenia.
Durgesh Kumar