java - example - ¿Cuándo debemos usar un PreparedStatement en lugar de un Statement?
preparedstatement java select (8)
Query es reescrito y compilado por el servidor de la base de datos
Si no usa una declaración preparada, el servidor de la base de datos tendrá que analizar y calcular un plan de ejecución para la declaración cada vez que la ejecute. Si encuentra que ejecutará la misma declaración varias veces (con diferentes parámetros), entonces vale la pena preparar la declaración una vez y reutilizar esa declaración preparada. Si está consultando la base de datos adhoc, probablemente haya poco beneficio.
Protegido contra inyección SQL
Esta es una ventaja que casi siempre desea, por lo tanto, es una buena razón para usar un Estado
PreparedStatement
cada vez. Es una consecuencia de tener que parametrizar la consulta, pero hace que correrla sea mucho más seguro. La única vez que puedo pensar que esto no sería útil es si permitía consultas de bases de datos adhoc; Puede usar simplemente el objeto Statement si estuvo creando un prototipo de la aplicación y es más rápido para usted, o si la consulta no contiene parámetros.
Conozco las ventajas de usar PreparedStatement
, que son
- la consulta es reescrita y compilada por el servidor de la base de datos
- protección contra inyección de SQL
Pero, ¿quiero saber cuándo lo usamos en lugar de Statement
?
Además de evitar la inyección de SQL, la portabilidad del formato (que no se puede obtener de Statement
), el rendimiento es la razón obvia. Sin embargo, PreparedStatement
no viene sin ninguna penalización. Por ejemplo, generalmente es más lento que Statement
si se ejecuta solo una vez, ya que hay una sobrecarga. Por lo tanto, la idea general es PreparedStatement
debe usar cuando se realiza la misma consulta muchas veces. Sin embargo, la cantidad de sobrecarga es muy específica para la implementación del servidor de base de datos, por lo que exactamente cuándo elegir PreparedStatement
sobre Statement
, desde la consideración del rendimiento, realmente debería basarse en su experiencia real / experimentos de un servidor de base de datos específico.
Daría la vuelta a esto: en una aplicación distribuida públicamente, generalmente siempre debes usar declaraciones preparadas a menos que tengas una razón realmente convincente para no hacerlo , y siempre debes proporcionar los parámetros "correctamente" a la declaración preparada, y no empalmándolos en el cadena de consulta.
¿Por qué? Bueno, básicamente por las razones que diste (o al menos, la segunda) ...
Prefiero usar PreparedStatement si quiero ejecutar una consulta. (Insertar, Seleccionar, ... etc.). El mismo rasoson que otros escritos arriba.
Pero si necesito usar parámetros dinámicos , uso simplemente Statement porque puedo construir fácilmente mi cadena SQL que simplemente ejecutar. (inmyopinion) Si quieres construir una consulta dinámica con preparedStatment tendrás un gran código de spaghetti que nadie entiende.
Pregúntale a Tom:
El uso de un Statement en JDBC debe estar 100% localizado para ser usado para DDL (ALTER, CREATE, GRANT, etc.) ya que estos son los únicos tipos de declaración que no pueden aceptar BIND VARIABLES.PreparedStatements o CallableStatements se deben usar para CADA OTRO tipo de instrucción (DML, Consultas). Como estos son los tipos de declaración que aceptan variables de vinculación.
Esto es un hecho, una regla, una ley: use declaraciones preparadas POR TODAS PARTES. Use DECLARACIONES casi en ninguna parte.
Está hablando específicamente de Oracle, pero el mismo principio se aplica a cualquier base de datos que almacena en caché los planes de ejecución.
¿Aplicaciones de base de datos que escalan y previenen ataques de inyección SQL al mismo tiempo? ¿Cuál es el inconveniente?
Siempre puede usar PreparedStatement en lugar de Statment (seleccionar, insertar, actualizar, eliminar). Mejor rendimiento y protegido contra la inyección de SQL.
Pero, no lo use con una solicitud dinámica como una solicitud con la WHERE variable IN [ hundreds possibilities ]
:
Es contraproducente, ha perdido rendimiento y memoria porque almacena en caché cada vez que una nueva solicitud, y PreparedStatement no son solo para inyección de SQL, se trata de rendimiento. En este caso, Statement no será más lento.
Su grupo tiene un límite de PreparedStatment (-1 defaut pero debe limitarlo), y alcanzará este límite. y si no tiene un límite o un límite muy grande, tiene algún riesgo de pérdida de memoria y, en casos extremos, errores de OutofMemory. Entonces, si es para su pequeño proyecto personal utilizado por 3 usuarios, no es dramático, pero no quiere que si está en una gran compañía y que su aplicación es utilizada por miles de personas y un millón de personas lo soliciten.
Algunos leyendo. IBM: Consideraciones sobre la utilización de la memoria cuando se utiliza el almacenamiento en caché preparado
Los estados preparados deben usarse con mucho cuidado en las cláusulas WHERE.
Supongamos que una tabla se define como:
create table t (int o, k varchar(100), v varchar(100))
(por ejemplo, "o: object-ID (clave externa), k: attribute-key, v: attribute-value").
Además hay un índice (no único) en v.
create index ixt on t ( v )
Supongamos que esta tabla contiene 200 millones de filas insertadas como:
for (i = 0; i < 100*1000*1000; i++) {
insert into t (o,k,v) values (i,''k1'',''v1'');
insert into t (o,k,v) values (i,''k2'', Convert(i, varchar));
}
("Por lo tanto, cada objeto o tiene atributos k1 = v1 y k2 = o")
Entonces no deberías construir consultas como:
select o,p,v from t as tx, t as ty where tx.o=ty.o and tx.k=? and tx.v=? and ty.k=? and ty.v=?
("encuentra objetos que tienen dos atributos dados")
Mi experiencia con ORACLE y MSSQL es que esas consultas pueden tardar muchos minutos en regresar. Esto es cierto incluso si ninguna fila coincide con la cláusula where. Depende de si el servidor SQL decide buscar primero tx.v o ty.v.
Una vez, coloque los valores de las columnas k y v en la instrucción. Creo que esto se debe a que los Servidores SQL toman en cuenta los valores al calcular el plan de ejecución.
Una consulta similar a esto vuelve siempre después de milisegundos:
select o,p,v from t as tx, t as ty where tx.o=ty.o and tx.k=''k1'' and tx.v=''v1'' and ty.k=''k2'' and ty.v=''1234''
("SQL-Server siempre buscará primero v = ''1234'' y luego para v = ''v1''")
Saludos
Wolfgang
Declaración : cada vez que se ejecuta la consulta sql, esta instrucción sql se envía al DBMS donde se compila. Por lo tanto, aumenta las cargas del servidor y disminuye el rendimiento.
connection con=null;
String sql="select * from employee where id=5";
Statement st=conn.createStatement();
PreparedStatement : A diferencia de Statement, PreparedStatement recibe una consulta sql como parámetro cuando se crea.
connection con=null;
String sql="select * from employee where id=?";
PreparedStatement ps=conn.prepareStatement(sql);
Esta instrucción SQL se envía a la Base de datos donde se compila. Entonces, en preparedStatement compiled ocurre una sola vez pero en el enunciado compilado ocurre cada vez que se invoca a Statement.