2013-03-14 10 views
6

Ho letto la soluzione da questa domanda PreparedStatement IN clause alternatives?. Ma nel mio caso, ho circa 5000 parametri in una clausola In e porterei a java.sql.SQLException: L'istruzione preparata o callable ha più di 2000 marcatori di parametri.PreparedStatement con migliaia di parametri in una clausola IN

Io sto usando uno SQL come

String sql = "select * from project in " + projectIds.toString() 

projectIds è uno StringBuilder, che è come "(1,2,3,4 ....)" Ma rapporto di sicurezza il codice dice che potrebbe portare ad una SQL Injection. Quindi devo usare? segnaposto per evitarlo.

Ho cercato di usare

String sql = "select * from project where charindex(','+convert(varchar(max),id)+',', ?)>0"; 
statement.setString(1,projectIds.toString);//projectIds like ",1,2,3,4,".. 

ma finisce con un errore di sintassi non corretta.

C'è qualche soluzione ???

+0

SQL, * charindex * sembra Non corretto. Suggerisci di ricontrollarlo e riscriverlo in un altro modo, se puoi. – Minus

risposta

1

Il modo migliore per farlo è non utilizzare una dichiarazione in. Invece dovresti mettere tutti i valori che vuoi controllare in una tabella e usare un join.

Per esempio se si ha una tabella con una colonna (chiamato id) che aveva la lista poi la sua dichiarazione sarebbe simile a questa:

select * 
from project 
join tablelist on project.project = tablelist.id 

Questo sarà molto più veloce perché i server SQL sono abbastanza bravo a esecuzione si unisce rapidamente


È anche possibile farlo con un CTE. Ad esempio:

WITH tablelist as 
(
    SELECT 1 AS id 
    UNION ALL 
    SELECT 3 
    UNION ALL 
    SELECT 4 
    UNION ALL 
    SELECT 5 
    UNION ALL 
    SELECT 6 
    UNION ALL 
    SELECT 7 
    // More if needed 
) 
select * 
from project 
join tablelist on project.project = tablelist.id 

Questo può essere inviato come una query di grandi dimensioni e funzionerebbe. Il tuo unico limite sarebbe la dimensione massima di una query, non so se esiste un tale limite.

+0

In realtà, non ho l'accesso di aggiornamento al database. Abbiamo 2 database, A è un database per un'altra app, che non abbiamo accesso agli aggiornamenti, e B è il nostro database. Quello che voglio fare è recuperare gli ultimi dati dal database A per quegli ID di progetto nel database B. Qualche suggerimento ?? –

+0

@WangWei - Sì, vedi sopra. – Hogan

2

Il suggerimento di Hogan di utilizzare un tavolo è invece buono. L'unica cosa che cambierei è la query, perché JOIN produce una riga per ogni valore in tablelist. Invece (indovinare i nomi delle colonne)

select * from project 
where projectID in (select id from tablelist) 

o

where exists (select 1 from tablelist where id = projectID) 
+0

Si prega di vedere il commento che ho risposto a Hogan. Thx –

+0

Se i database A e B si trovano sullo stesso server, è possibile unirli se è possibile disporre le autorizzazioni. Puoi anche inserire in una tabella temporanea globale. Davvero, i DBA dovrebbero aiutarti, non erigere ostacoli stupidi.Nel peggiore dei casi, è possibile passare una stringa, ricollegarla con charindex o qualcosa, inserire i valori in una variabile di tabella e unirsi. –

+0

Join non produce una riga, era un join interno ... un join sinistro lo avrebbe fatto. Non ho usato un join di sinistra. – Hogan

1

select * from project in " + projectIds.toString()

è la sintassi non corretta, dovrebbe essere qualcosa di simile a

select * from project where id in (" + projectIds + ")"; 
Problemi correlati