Newsgroup: it.comp.java
Titolo: PrepareStatement con IN

Ciao a tutti,
ho problema all'apparenza stupido che non riesco a risolvere.
Ho la seguente istruzione sql:
SELECT  *  FROM MIA_TABELLA WHERE USER IN ? ;
Con il codice seguente vorrei sostituire al carattere ? i miei para-
metri che ricavo con altre elaborazioni:
String miei_param = (29,27,2);
st = connForm.prepareStatement(s_sql);
st.setString(1, miei_param );
rst = st.executeQuery();
L'istruzione sql va in errore perche'  assieme ai miei parametri
vengo aggiunti i caratteri stringa all'inizio e alla fine della stessa
(risultato
SELECT  *  FROM MIA_TABELLA WHERE USER IN '(29,27,2)' ;
Qualche suggerimento???
Grazie


non funziona cosi', ma cosi'
SELECT  *  FROM MIA_TABELLA WHERE USER IN (?,?,?) ;
e poi
...
st.setString(1, 27 );
st.setString(2, 28 );
st.setString(3, 29 );

 ha scritto nel messaggio 
news:43ce88ad$0$349$5fc...@news.tiscali.it...


Puoi risolverlo aggiungendo a run time tanti "?" quanti sono quelli che 
ti servono.
-Jeffo
-
www.milkeyway.net
Markus71 ha scritto:


 
Eh, già, così ogni volta devi mandare il PreparedStatement al DB per 
la..preparazione, appunto! In questo modo non sfrutti il vantaggio di 
avere uno statement compilato, molto meglio usare uno Statement standard 
e crearti il comando SQL a mano: okkio al quoting (e SQL injection e 
compagnia bella...)

 ha scritto nel messaggio 
news:43cecaa1$0$1084$4faf...@reader4.news.tin.it...

Lo svantaggio puo' esserci come no.
Il vantaggio e' lasciare a jdbc il lavoro di inserire i parametri e inoltre 
bisogna ricordarsi del caching delle query, potrebbe essere che viene 
utilizzata piu' di una volta (ad esempio se gli utenti tendono a selezionare 
un oggetto solo alla volta). 

 ha scritto nel messaggio 
news:43cf6156$0$347$5fc...@news.tiscali.it...

inoltre meglio prediligere la mantenibilita' del codice piuttosto che una 
forse irrisoria ottimizzazione, visto che secondo quanto fatto capire siamo 
in un contesto di interazione con l'utente. 

 
Mah, secondo me anche usare un PreparedStatement è una falsa 
ottimizzazione. Potrebbe benissimo rivelarsi dannosa per le performance, 
ad esempio se il numero di elementi della IN cambia spesso: quanti 
prepared statement dovrebbe memorizzarsi il DB? Se non sbaglio poi 
alcuni DB fanno caching anche delle query non-prepared...
Io rimarrei sull'SQL "a mano", stando molto attento a formattare 
correttamente i parametri.
Cheers
-- 
  -- + Setaceous Pig + --
http://www.megadix.org/
http://www.jroller.com/page/megadix/


le cache non memorizzano tutto ma solo alcuni elementi secondo una certa 
politica quindi il problema non dovrebbe porsi.
Rimane il fatto che non ha senso usare Statement visto che non da alcun 
vantaggio in questo specifico caso, invece la prepared statement migliora la 
mantenibilita' e leggibilita' del codice. 

a me sembra una buona idea, sicuramente il codice esce piu pulito
usando i parameters piuttosto che scrivere brutalmente i valori!

 writes:
DDF> Mah, secondo me anche usare un PreparedStatement č una falsa
DDF> ottimizzazione.
Con Oracle un manuale parlava di vantaggi dopo la 60^ esecuzione.
DDF> Io rimarrei sull'SQL "a mano", stando molto
DDF> attento a formattare correttamente i parametri.
Concordo. 
Tra l'altro  mi domando  perché in Sun  abbiano fatto la  scelta "alla
ADO" di usare placeholder anonimi.   Quando devi chiamare S.P.  con un
numero elevato di parametri diventano una tortura.
-- 
 /\            ___
/___/\__|_|\_|__|___Gian Uberto Lauri_____________________
  //--\ | | \|  |   Integralista GNUslamico  
\/		    e allevatore di bug da competizione


forse per una questione di performance generale. 

 la..preparazione, appunto!
Non capisco, puoi spiegare meglio ? Una cosa del genere
   String[] param = ...;
   String query = "select * from table where user in (";
   for (int i = 0; i < param.length; i++) {
     query += "?";
     if (i != param.length) query += ",";
   }
   query += ")";
   st = connForm.prepareStatement(query);
   for (int i = 0; i < param.length; i++) {
     st.setString(i, param[i]);
   }
   rst = st.executeQuery();
cosa ha che non va' bene ?
-- 
Giambo - Occhio al filtro antispam _e_ alla whitelist !


nulla a parte il fatto che dovresti usare StringBuffer invece di concatenare 
le stringhe con l'operatore  "+".

 
Non ti preoccupare che va benissimo, però probabilmente non sai cosa 
succede di preciso, ecco una piccola spiega.
Quando esegui
connForm.prepareStatement(query)
il driver JDBC invia la query al database e gli dice "Voglio fare questo 
tipo di query con questi parametri, me la compili in modo che sia il più 
efficiente possibile?"
Quindi di mezzo c'è una chiamata (e cicli di CPU/disco/memoria) in più 
al database, mentre con gli Statement "normali" questa chiamata 
aggiuntiva non c'è: si esegue la query e basta. Tutto qua.


cpu e memoria volatile si, disco no (se no si che lo sconsiglio ;)).
ah per completare la questione dello StringBuffer ti dico che la 
concatenazione andrebbe fatta circa cosi' (e' un esempio):
StringBuffer sb = new StringBuffer("select ... where ...");
sb.append("?,");
sb.append("?,");
...
String sql = sb.toString();
altrimenti
s += "?";
crea un oggetto nuovo e lo assegna alla variabile "s" ogni volta, e il gc 
prima o poi deve pure distruggerlo.
Non che con poche iterazione del ciclo for sarebbe successo chissa' quale 
problema, ma e' buona norma abituarsi a evitare questi overhead da subito. 

> 
c> forse per una questione di performance generale. 
Non ci  perdi nulla se segui  la tecnica degli Oracle  Objects for Ole
(che mi ero dimenticato di citare),  dove invece di un anonimo ? metti
una piccola stringa. Lì si che il codice rimane leggibile.



Io terrei le preparedstatement, tanto non cambia nulla riguardo alle 
performance in questo caso, e' inutile specialmente con i siti web, stare 
la' a scervellarsi se usare una preparedstatement o una statement, tanto 
quasi sempre le prepredstatment non sono peggio (anzi di solito sono 
meglio), e inoltre sono piu' comode da usare. Io userei sempre le 
preparedstatement.
Inoltre pensiamoci bene, in quali circostanze si puo' avere una query sql 
che cambia di volta in volta?
Secondo me la risposta e' solo quando si ha a che fare con input esterni. 
Solitamente in questi casi ha poso senso ottimizzare il mezzodecimo di 
secondo. Gli utenti possono anche essere 1000 ma non faranno la stessa 
identica richiesta in 1000.

 writes:
c> Se anche gli
c> utenti fossero 1000 sarebbe assai improbabile ritrovarsi con la
c> stessa identica richiesta nello stesso identico tempo o
c> quasi.
Per lo meno con Oracle (che è il  DBMS che si usa di più al lavoro) il
lavoro fatto per ottimizzare la query viene messo in cache con un hash
basato  sul testo della  query. Con  gli statement  parametrici questo
hash diventa  indipendente dai valori con  cui si "popola"  la query e
quindi   invocazioni  successive   della  stessa   query   portano  ad
riutilizzare il lavoro già fatto. E' questa cosa che porta ad avere il
vantaggio che l'autore  di quel libro rilevava. Ora,  visto che non ha
pubblicato la  query, non so dire  se era più semplice  o complessa di
quelle con cui mi son trovato a fare i conti.
c> Inoltre se si tratta di un sito web, beh i siti web sono
c> "programmi" che girano per parecchio tempo quindi questi discorsi
c> non trovano quasi nessun motivo di esistere.
Con le cache il discorso diventa complicato. Il fatto che il programma
giri  a  lungo  non  dice  molto. Potrebbe  passare  molto  tempo  tra
invocazione e l'altra come potrebbe essere che quella query non ha mai
un attimo  di riposo. Oltretutto  ci sono vari generi  di applicazioni
web.
c> Io terrei le preparedstatement, tanto non cambia nulla riguardo alle 
c> performance in questo caso,
Ma di che siti web ti occupi ?
c> e inoltre sono piu' comode da
c> usare. Io userei sempre le preparedstatement.
Attenzione, qui sei entrato nel campo del soggettivo!!!
c> Gli utenti possono anche essere 1000 ma non faranno la
c> stessa identica richiesta in 1000.
Vedi sopra. Non  sono un esperto di DBMS, la  mia esperienza si limita
praticamente a  Oracle. Ma in  quello caso il guadagno  è indipendente
dall'input.


 Attenzione, qui sei entrato nel campo del soggettivo!!!
beh insomma non credo.
settare i parametri dovendo sbattersi con gli apici non mi sembra in nessun 
caso piu' comodo di lasciare il lavoro a jdbc. 

 writes:
c> Allora se passa tanto tempo tra una e l'altra ho ragione io, se non
c> ha un attimo di riposo continuo ad avere ragione io.
No, guarda,  c'è una buona probabilità  che io mia espresso  male ma è
altrettanto  buona che  tu  abbia  letto male.  Io  ho cominciato  con
l'affermare  che   userei  la  prepared  query  solo   per  motivi  di
prestazioni  in  quanto  personalmente  la trovo  poco  maneggevole  a
livello  di sorgente (tu  la preferisci,  ma qui  si ricade  nei gusti
personali ed ognuno è padrone di preferire ciò che vuole).
Per il resto siamo d'accordo al 100% sul discorso prestazioni. O quasi
:),  se una  query  viene chiamata  una  volta ogni  morte  di papa  è
possibile  che  la  cache  venga  scartata  (come  no,  dipende  dalla
situazione).
c> beh insomma non credo.  settare i parametri dovendo sbattersi con
c> gli apici non mi sembra in nessun caso piu' comodo di lasciare il
c> lavoro a jdbc.
Non _ti_ sembra :), io mi  trovo da cani con quei parametri anonimi ed
ho pronto un metodino statico per gli apici :). In quello che tu trovi
comodo io  non obietto, ma su  quello che è comodo  per me l'authority
sono io :).



Va bene in effetti anche io preferirei i parametri nominali (?), ma continuo 
a preferire quelli anonimi all' uso di statement.
Il bel metodino che mette a posto gli apici ok, pero' in generale dovrai 
averlo anche per le date, i timestamp ecc...per questo preferisco affidarmi 
al driver. 

 writes:
c> averlo anche per le date,
Dopo aver sbattuto  la faccia con ADO e come tratta  le date, JDBC con
gli statement scritti  su schede perforate ti pare  una libidine :) :)
:) :) :)
Saluti!!!
