Przygotowane oświadczenie jest nieco bardziej rozbudowaną wersją oświadczenia i zawsze powinno być co najmniej tak szybkie i łatwe w obsłudze jak oświadczenie.
Przygotowane oświadczenie można sparametryzować
Większość relacyjnych baz danych obsługuje zapytanie JDBC / SQL w czterech krokach:
- Analizuj przychodzące zapytanie SQL
- Skompiluj zapytanie SQL
- Zaplanuj / zoptymalizuj ścieżkę akwizycji danych
- Wykonaj zoptymalizowane zapytanie / pozyskaj i zwróć dane
Instrukcja będzie zawsze przebiegać przez cztery powyższe kroki dla każdego zapytania SQL wysłanego do bazy danych. Przygotowana instrukcja wstępnie wykonuje kroki (1) - (3) w powyższym procesie wykonywania. Dlatego podczas tworzenia Przygotowanej instrukcji natychmiast wykonywana jest wstępna optymalizacja. Efektem jest zmniejszenie obciążenia silnika bazy danych w czasie wykonywania.
Teraz moje pytanie brzmi: „Czy jest jakaś inna zaleta korzystania z Prepared Statement?”
Odpowiedzi:
Zalety
PreparedStatement
:Wstępna kompilacja i buforowanie po stronie DB instrukcji SQL prowadzi do ogólnie szybszego wykonania i możliwości ponownego użycia tej samej instrukcji SQL w partiach .
Automatyczne zapobieganie SQL injection ataków przez wbudowane ucieczki od cytatów i innych znaków specjalnych. Należy pamiętać, że wymaga to użycia dowolnej
PreparedStatement
setXxx()
metody do ustawienia wartościi dlatego nie wstawiaj wartości w ciągu SQL przez konkatenację ciągu.
Ułatwia ustawień niestandardowych obiektów Javy w ciąg SQL, na przykład
Date
,Time
,Timestamp
,BigDecimal
,InputStream
(Blob
) iReader
(Clob
). W większości tych typów nie można po prostu „zrobić” tak,toString()
jak w prosty sposóbStatement
. Możesz nawet zrefaktoryzować to wszystko do użyciaPreparedStatement#setObject()
wewnątrz pętli, jak pokazano w poniższej metodzie użyteczności:Które mogą być używane jak poniżej:
źródło
Statement
, ale może być warty przetestowania.Są one wstępnie skompilowane (raz), dzięki czemu są szybsze w przypadku wielokrotnego wykonywania dynamicznego SQL (w przypadku zmiany parametrów)
Buforowanie instrukcji bazy danych zwiększa wydajność wykonywania DB
Bazy danych przechowują pamięci podręczne planów wykonania wcześniej wykonanych instrukcji. Umożliwia to silnikowi bazy danych ponowne wykorzystanie planów dla instrukcji, które zostały wcześniej wykonane. Ponieważ PreparedStatement używa parametrów, za każdym razem, gdy jest wykonywany, pojawia się jako ten sam SQL, baza danych może ponownie użyć poprzedniego planu dostępu, zmniejszając przetwarzanie. Instrukcje „wstawiają” parametry do ciągu SQL, a więc nie pojawiają się w DB jako ten sam SQL, co uniemożliwia użycie pamięci podręcznej.
Binarny protokół komunikacyjny oznacza mniejszą przepustowość i szybsze połączenia z serwerem DB
Przygotowane instrukcje są zwykle wykonywane za pomocą binarnego protokołu innego niż SQL. Oznacza to, że w pakietach jest mniej danych, więc komunikacja z serwerem jest szybsza. Zasadniczo operacje sieciowe są o rząd wielkości wolniejsze niż operacje na dyskach, które są o rząd wielkości wolniejsze niż operacje CPU w pamięci. Dlatego każde zmniejszenie ilości danych przesyłanych przez sieć będzie miało dobry wpływ na ogólną wydajność.
Chronią przed wstrzyknięciem SQL, usuwając tekst dla wszystkich podanych wartości parametrów.
Zapewniają silniejszą separację między kodem zapytania a wartościami parametrów (w porównaniu do połączonych ciągów SQL), zwiększając czytelność i pomagając opiekunom kodu szybko zrozumieć dane wejściowe i wyjściowe zapytania.
W języku Java można wywoływać metody getMetadata () i getParameterMetadata () w celu odzwierciedlenia odpowiednio pól zestawu wyników i pól parametrów
W java inteligentnie akceptuje obiekty java jako typy parametrów za pomocą setObject, setBoolean, setByte, setDate, setDouble, setDouble, setFloat, setInt, setLong, setShort, setTime, setTimestamp - konwertuje na format typu JDBC, który jest zrozumiały dla DB (nie tylko toString () format).
W języku Java akceptuje tablice SQL jako typ parametru za pomocą metody setArray
W języku Java akceptuje CLOB, BLOB, OutputStreams i czytniki jako parametr „feeds” za pomocą metod setClob / setNClob, setBlob, setBinaryStream, setCharacterStream / setAsciiStream / setNCharacterStream odpowiednio
W java pozwala na ustawienie wartości specyficznych dla DB dla SQL DATALINK, SQL ROWID, SQL XML i NULL za pomocą metod setURL, setRowId, setSQLXML i setNull
W java dziedziczy wszystkie metody z instrukcji. Dziedziczy metodę addBatch, a ponadto umożliwia dodanie zestawu wartości parametrów w celu dopasowania zestawu zestawionych poleceń SQL za pomocą metody addBatch.
W java specjalny typ PreparedStatement (podklasa CallableStatement) pozwala na wykonywanie procedur przechowywanych - obsługujących wysoką wydajność, enkapsulację, programowanie proceduralne i SQL, administrację DB / konserwację / ulepszanie logiki oraz wykorzystanie zastrzeżonej logiki i funkcji DB
źródło
Connection.createStatement
iConnection.prepareStatement
. Ten projekt zmusza cię do pracy przeciwko interfejsom, więc nie musisz znać konkretnych klas implementacji i unikać niepotrzebnego ścisłego powiązania z takimi klasami implementacji. Wszystko wyjaśnione przykładami w dokumentach Java JDBC i Dokumentach Java. :)PreparedStatement
jest bardzo dobrą obroną (ale nie niezawodną) w zapobieganiu atakom SQL injection . Wartości parametrów wiązania to dobry sposób na ochronę przed „małymi stołami Bobby'ego” przed niepożądaną wizytą.źródło
ORDER BY
) i / lub stałe numeryczne w niektórych miejscach (myślęLIMIT
,OFFSET
i innych rozwiązań paginacji), więc te mogą być atakowane przez SQL injection, nawet gdy sporządzanych sprawozdań i parametryzacja jest używany wszędzie tam, gdzie możliwy.Niektóre zalety PreparedStatement nad wyciągiem to:
Przeczytaj więcej o problemie z iniekcją SQL na stronie http://www.journaldev.com/2489/jdbc-statement-vs-preparedstatement-sql-injection-example
źródło
nic więcej do dodania,
1 - jeśli chcesz wykonać zapytanie w pętli (więcej niż 1 raz), przygotowana instrukcja może być szybsza, ze względu na wspomnianą optymalizację.
2 - sparametryzowane zapytanie to dobry sposób na uniknięcie SQL Injection. Zapytania sparametryzowane są dostępne tylko w PreparedStatement.
źródło
Wyciąg jest statyczny, a przygotowany wyciąg jest dynamiczny.
Instrukcja jest odpowiednia dla DDL i przygotowana deklaracja dla DML.
Wyciąg jest wolniejszy, a wyciąg przygotowany szybciej.
więcej różnic (zarchiwizowane)
źródło
Nie można wykonywać CLOBów w wyciągu.
Oraz: (OraclePreparedStatement) ps
źródło
Jak cytował Mattjames
źródło
Wstrzykiwanie SQL jest ignorowane przez przygotowane polecenie, więc zwiększa się bezpieczeństwo przygotowanego polecenia
źródło
źródło
Instrukcja będzie używana do wykonywania statycznych instrukcji SQL i nie może zaakceptować parametrów wejściowych.
PreparedStatement będzie używany do wykonywania instrukcji SQL wiele razy dynamicznie. Przyjmie parametry wejściowe.
źródło
Inna cecha przygotowanego lub sparametryzowanego zapytania: odniesienie zaczerpnięte z tego artykułu.
Ta instrukcja jest jedną z cech systemu bazy danych, w której ta sama instrukcja SQL jest wykonywana wielokrotnie z wysoką wydajnością. Przygotowane instrukcje są jednym z rodzajów szablonów i są używane przez aplikację o różnych parametrach.
Szablon instrukcji jest przygotowywany i wysyłany do systemu bazy danych, a system bazy danych wykonuje parsowanie, kompilację i optymalizację tego szablonu i przechowuje go bez wykonywania.
Niektóre parametry, takie jak klauzula nie jest przekazywana podczas tworzenia późniejszej aplikacji szablonu, wysyłają te parametry do systemu bazy danych, a system bazy danych korzysta z szablonu instrukcji SQL i wykonuje się zgodnie z żądaniem.
Przygotowane instrukcje są bardzo przydatne przeciwko SQL Injection, ponieważ aplikacja może przygotować parametr przy użyciu różnych technik i protokołów.
Gdy liczba danych rośnie i indeksy często się zmieniają w tym czasie Przygotowane instrukcje mogą zawieść, ponieważ w tej sytuacji wymagają nowego planu zapytań.
źródło
Statement
interfejs wykonuje statyczne instrukcje SQL bez parametrówPreparedStatement
interfejs (instrukcja rozszerzająca) wykonuje wstępnie skompilowaną instrukcję SQL z / bez parametrówWydajny w przypadku wielokrotnych egzekucji
Jest wstępnie skompilowany, więc jest szybszy
źródło
Nie wpadaj w zamieszanie: po prostu pamiętaj
źródło
Postępowałem zgodnie ze wszystkimi odpowiedziami na to pytanie, aby zmienić działający stary kod, używając -
Statement
(ale mając SQL Injections) na rozwiązanie korzystającePreparedStatement
ze znacznie wolniejszego kodu z powodu słabego zrozumienia semantyki wokółStatement.addBatch(String sql)
&PreparedStatement.addBatch()
.Podaję więc tutaj mój scenariusz, aby inni nie popełnili tego samego błędu.
Mój scenariusz był
Tak więc w powyższym kodzie miałem tysiące różnych zapytań, wszystkie dodane do tej samej instrukcji, a ten kod działał szybciej, ponieważ instrukcje, które nie były buforowane, były dobre i ten kod był wykonywany rzadko w aplikacji.
Teraz, aby naprawić Zastrzyki SQL, zmieniłem ten kod na,
Widzicie, zacząłem tworzyć tysiące
PreparedStatement
obiektów, a potem ostatecznie nie byłem w stanie korzystać z grupowania, ponieważ mój scenariusz tego wymagał - istnieją tysiące zapytań UPDATE lub INSERT, a wszystkie te zapytania są różne.Naprawianie wstrzykiwania SQL było obowiązkowe bez kosztów obniżenia wydajności i nie sądzę, aby było możliwe
PreparedStatement
w tym scenariuszu.Ponadto, gdy korzystasz z wbudowanej funkcji grupowania, musisz martwić się o zamknięcie tylko jednej instrukcji, ale w przypadku tej metody Listy musisz zamknąć instrukcję przed ponownym użyciem, Ponowne użycie PreparedStatement
źródło