2013-03-14 13 views
6

Zrobiłem odczytać rozwiązanie z tego pytania PreparedStatement IN clause alternatives?. Ale w moim przypadku mam około 5000 parametrów w klauzuli "In" i prowadzi to do java.sql.SQLException: Przygotowana lub wywoływalna instrukcja ma ponad 2000 znaczników parametrów.PreparedStatement z tysiącami parametrów w klauzuli IN

używałem SQL jak

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

projectIds jest StringBuilder który jest jak "(1,2,3,4 ....)" Ale raport security code mówi, że może to prowadzić do wtrysk sql. Więc muszę użyć? symbol zastępczy, aby tego uniknąć.

Próbowałem użyć

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

Ale to kończy się błędnym błąd składni.

Czy istnieje jakieś rozwiązanie?

+0

programu SQL * charIndex * wydaje niepoprawne. Zalecamy sprawdzenie go ponownie i przepisanie go w inny sposób, jeśli możesz. – Minus

Odpowiedz

1

Najlepszym sposobem, aby to zrobić, jest nieużywanie instrukcji in. Zamiast tego powinieneś umieścić wszystkie wartości, które chcesz sprawdzić w tabeli i użyć sprzężenia.

Na przykład jeśli miał tabeli z jednej kolumny (nazywane id), który miał lista wówczas oświadczenie będzie wyglądać następująco:

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

To będzie znacznie szybciej, ponieważ serwery SQL są dość dobry w wykonywaniu dołącza się szybko.


Można to również zrobić przy użyciu CTE. Na przykład:

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 

Można to wysłać jako jedno duże zapytanie i zadziała. Jedynym ograniczeniem będzie maksymalny rozmiar zapytania, nie wiem, czy taki limit istnieje.

+0

W rzeczywistości nie mam dostępu do aktualizacji do bazy danych. Mamy dwie bazy danych, A to baza danych dla innej aplikacji, do której nie mamy dostępu, a B to nasza własna baza danych. Co chcę zrobić, to pobrać najnowsze dane z bazy danych A dla tych identyfikatorów projektu w bazie danych B. Jakieś sugestie? –

+0

@WangWei - Tak, patrz wyżej. – Hogan

2

Sugestia Hogana, by zamiast tego użyć tabeli, jest dobra. Jedyne co zmienię to zapytanie, ponieważ JOIN tworzy wiersz dla każdej wartości w tablelist. Zamiast (zgadywania na swoje nazwy kolumn)

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

lub

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

Proszę zobaczyć komentarz, odpowiedziałem na Hogan. Thx –

+0

Jeśli bazy danych A i B znajdują się na tym samym serwerze, możesz dołączyć do nich, jeśli możesz ustawić uprawnienia. Można również wstawić do globalnej tabeli tymczasowej. Naprawdę, administratorzy DBA powinni ci pomóc, a nie wznosić głupich przeszkód.W najgorszym przypadku możesz przekazać ciąg, pętlę nad nim za pomocą charindex lub czegoś podobnego, wstawić wartości do zmiennej tabeli i dołączyć. –

+0

Łączenie nie powoduje powstania wiersza, było to wewnętrzne sprzężenie ... lewe dołączenie mogłoby to zrobić. Nie użyłem lewego sprzężenia. \ – Hogan

1

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

jest błędna składnia, powinno być coś jak

select * from project where id in (" + projectIds + ")"; 
Powiązane problemy