2012-07-03 17 views
27

Używam obiektu Java PreparedStatment do skonstruowania serii zapytań INSERT z pakietowaniem. Wyrażenie jest w formacie ...Jak używać zmiennej tablename dla instrukcji przygotowanej w java insert

String strQuery = "INSERT INTO ? (col1, col2, col3, col4, col5) VALUES (?,?,?,?,?,?);"; 

... więc obie wartości pola i nazwatabeli są zmiennymi (tzn. Mam wiele tabel z tego samego formatu kolumny, z których każda wkładka zostanie skierowany na inny). Mogę sprawić, by egzekucje zadziałały, gdy usunę "?" nazwatabeli zmienna i trudno kod ale każdy przygotowano sprawozdanie zostanie wstawiona do innej tabeli tak musi pozostać zmienna I wypełnić bezpośrednio przed wykonaniem kwerendy wsadowy przy użyciu ...

stmt.setString(1, "tableName1"); 

Jak mogę pozwolić to być dynamiczna zmienna proszę?

Odpowiedz

37

Nie możesz. Musisz skonstruować sql z ciągiem konkatenacji/placeholder z String.format. przygotowane oświadczenie dotyczy wartości kolumny, a nie nazwy tabeli.

+2

Dzięki ludziom ... wydaje się, że nie znam nazwy tablicowej, którą chcę wstawić, aż do momentu zamiany zmiennych dla każdego wiersza, najlepszą rzeczą jest skonstruowanie wstawki w ramach procedury przechowywanej bazy danych. Następnie przeprowadź wszystkie parametry dla każdego wiersza do przechowywanego procesu, a następnie pozwól DB obsługiwać manipulację nazwami. Mimo to dziękuję za odpowiedzi. :-) – ForestSDMC

+13

Czy to oznacza, że ​​ochrona wstrzykiwania SQL jest niemożliwa w przypadku dynamicznych nazw tabel? –

+0

@Richard Doszedłem do tego samego wniosku i brzmi to głupio, ale przynajmniej łatwo jest sprawdzić nazwę tabeli na liście dostępnych tabel w bazie danych. – JulienD

-3

Trzeba by dodać go do oryginalnego napisu:

String tableName = "some_table_name"; 
// some other code 
String strQuery = "INSERT INTO " + tableName + " (col1, col2, col3, col4, col5) VALUES (?,?,?,?,?,?);"; 

Czy potrzebujesz średnik w strQuery? (możesz to zrobić, po prostu wygląda to trochę dziwnie :-))

+6

podatna na SQL injection. NIE UŻYWAJ TEGO ODPOWIEDZI, DZIECI! – SigmaX

+6

... Cóż, zależy to od tego, skąd pochodzi nazwa tabeli. Jeśli pochodzi od użytkownika lub od niewiarygodnego klienta, zgadzam się z tobą. Ale jeśli jest to zawarte w twojej własnej metodzie, to niezmienność Stringa oznacza, że ​​jest bezpiecznie na pewno. –

+0

Technicznie prawdziwe. Jednak dobra odpowiedź nadal wymaga dużego ograniczenia odpowiedzialności: "z reguły unikaj używania dynamicznych zapytań SQL, okresu - jest to powszechnie uważane za niebezpieczną praktykę. Jeśli musisz to zrobić, upewnij się, że dokładnie wiesz, co robisz." – SigmaX

-2

Nazwa tabeli nie może być użyta jako parametr. Musi być mocno zakodowany. Wypróbuj coś takiego:

String tableName = "tableName1"; 
String strQuery = "INSERT INTO " + tableName + " (col1, col2, col3, col4, col5) VALUES (?,?,?,?,?,?);"; 
+7

Podatny na iniekcję SQL. NIE UŻYWAJ TEGO ODPOWIEDZI, DZIECI! – SigmaX

-1

Jedną z możliwości może być String.format:

np

String sql = String.format("INSERT INTO $1%s (col1, col2, col3, (etc)", myTablename); 
+15

Wrażliwy na SQL injection.NIE UŻYWAJ TEGO ODPOWIEDZI, DZIECI! – SigmaX

+12

To jest zwykle "o, wiem, czym jest iniekcja SQL", "paranoja" - to całkowicie zależy od tego, skąd pochodzi nazwa mojego tablename. – davidfrancis

+3

Uzgodnione. Jednak, podobnie jak w przypadku większości problemów związanych z bezpieczeństwem, znaczna część użytkowników witryn z pytaniami i odpowiedziami nie zrozumie, że muszą zwracać uwagę na skąd pochodzi nazwa mojegoTablila. Tak więc odpowiedź musi być kwalifikowana. – SigmaX

11

Można użyć zastępczy zamiast nazwy tabeli, a następnie zastąpienie że z nazwa-tabeli.

String strQuery = "INSERT INTO $tableName (col1, col2, col3, col4, col5) 
        VALUES (?,?,?,?,?,?);"; 

i wymienić, gdy u poznali TableName

String query =strQuery.replace("$tableName",tableName); 
stmt =conn.prepareStatement(query); 
+27

Podatny na SQL injection. NIE UŻYWAJ TEGO ODPOWIEDZI, DZIECI! – SigmaX

+7

tylko jeśli nazwa $ tablename pochodzi z danych wprowadzonych przez użytkownika, prawda? Ale byłoby dobrze, gdyby coś takiego jak wybór przycisku radiowego zwróciło wartość modułu wyliczającego lub inną metodę, która ogranicza możliwe wartości $ tablename do zdefiniowanego zestawu? – Toadfish

+9

@SigmaX, jakie jest twoje rozwiązanie, które nie jest podatne na iniekcję SQL? – Mahdi

Powiązane problemy