2012-07-03 11 views
27

Estoy usando un objeto Java PreparedStatment para construir una serie de consultas INSERT por lotes. La instrucción de consulta es el formato de ...Cómo usar una variable de nombre de tabla para una instrucción preparada java insertar

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

... por lo tanto los valores de campo y el nombre de tabla son variables (es decir. Tengo varias tablas con el mismo formato de columna de los cuales cada inserto se dirige a una uno diferente). Puedo hacer funcionar los ejecutables si elimino el "?" variable de tablas y de código duro, pero se insertará cada declaración preparada en una tabla diferente, así tiene que seguir siendo una variable que pueblan inmediatamente antes de ejecutar la consulta por lotes utilizando ...

stmt.setString(1, "tableName1"); 

¿Cómo puedo dejar que esto sea una dinámica variable por favor?

Respuesta

37

No puede. Debe construir el sql con concatenación de cadena/marcador de posición con String.format. la declaración preparada es para los valores de la columna, no para el nombre de la tabla.

+2

Gracias amigos ... parece que no sé el nombre de la tabla en la que quiero insertar hasta el punto de intercambio en las variables para cada fila, lo mejor es construir la inserción dentro de un procedimiento almacenado de base de datos. A continuación, pase todos los parámetros para cada fila en el proceso almacenado y deje que la BD maneje la manipulación del nombre de tabla. De todos modos, gracias por las respuestas. :-) – ForestSDMC

+13

¿Significa esto que la protección de inyección SQL es imposible con los nombres de tablas dinámicas? –

+0

@Richard Llegué a la misma conclusión y suena tonto, pero al menos es bastante fácil verificar el nombre de la tabla con la lista de tablas disponibles en la base de datos. – JulienD

-3

Usted tendría que añadirlo a la cadena original:

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

quiere el punto y coma en el strQuery? (Puede hacer, simplemente se ve un poco raro para mí :-))

+6

vulnerable a la inyección de SQL. NO USE ESTA RESPUESTA, NIÑOS! – SigmaX

+6

... bueno eso depende de dónde viene su tableName. Si proviene de un usuario o de un cliente no confiable, entonces estaría de acuerdo contigo. Pero si está contenido dentro de tu propio método, entonces la inmutabilidad de String significa que es seguro. –

+0

Técnicamente cierto. Pero una buena respuesta todavía necesita una importante aclaración: "como regla, evite el uso de consultas SQL dinámicas, período: es ampliamente considerada una práctica insegura. Si tiene que hacer esto, asegúrese de saber exactamente lo que está haciendo". – SigmaX

-2

El nombre de la tabla no se puede utilizar como un parámetro. Debe estar codificado. Pruebe algo como:

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

Vulnerable a inyección SQL. NO USE ESTA RESPUESTA, NIÑOS! – SigmaX

-1

Una alternativa podría ser String.format:

por ejemplo

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

Vulnerable a la inyección de SQL.NO USE ESTA RESPUESTA, NIÑOS! – SigmaX

+12

Esta es la paranoia habitual "oh, sé lo que es inyección SQL", depende completamente de dónde viene myTablename. – davidfrancis

+3

De acuerdo. Pero, al igual que con la mayoría de los problemas de seguridad, una gran parte de los visitantes de los sitios de preguntas y respuestas no comprenderán que deben estar atentos a la procedencia de myTablename. Entonces la respuesta necesita ser calificada. – SigmaX

11

Puede utilizar el marcador de posición en lugar del nombre de la tabla y luego reemplazarlo con su nombre de tabla.

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

y reemplazar cuando u llegar a conocer el nombre de tabla

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

Vulnerable a inyección SQL. NO USE ESTA RESPUESTA, NIÑOS! – SigmaX

+7

solo si $ tablename se toma de la entrada del usuario, ¿verdad? Pero estaría bien si algo así como la selección de un botón de opción devolviera un valor de enumerador, o cualquier otro método que restrinja los posibles valores de $ tablename a un conjunto definido. – Toadfish

+9

@SigmaX, entonces, ¿cuál es su solución que no es vulnerable a la inyección de SQL? – Mahdi

Cuestiones relacionadas