问题描述
准备好的语句有什么用。当您多次使用不同的值执行相同的SQL查询时,我读到的代码对性能有好处。
//Line 1
ps = c.prepareStatement("INSERT INTO STUDENT VALUES (?,?)");
所以在这里我创建了一个准备好的语句。这将被发送到数据库并留在那里吗? 然后,我只需要将值发送到数据库。对吗?
//This is created only once
//Once created,the PreparedStatement is compiled automatically.
ps.setInt(1,111);
ps.setString(2,"Bob");
ps.executeUpdate();
解决方法
它们有两个目的。您说的那是一个很小的好处。实际上,根本无法保证。可以说,JDBC驱动程序可以自由地“填补空白”,并且每次将SQL原样发送到DB层。如果您的数据库引擎支持预编译SQL语句,则PreparedStatement是获得此好处的方法,但是JDBC驱动程序不必支持此功能(但它必须支持PreparedStatement;不过,它无需预编译任何内容即可实现它)。此外,如果您正在寻找“批量”工作(多次执行相同的操作),通常会有更好的工具可用。例如,如果您想将100万条记录插入表中,则有比 far 更有效的方法。创建一个准备好的语句,并使用不同的设置值将其重新运行一百万次。您将关闭所有约束检查和索引更新,和/或COPY
或为此专门设计的其他批量插入过程,然后重新打开检查和索引。
不,对语句使用PreparedStatement的99%以上的原因是安全性。
声明不安全。
想象一下这个:
String name = getNameFromWebForm();
String id = getNextAvailableStudentId();
connection.executeUpdate("INSERT INTO STUDENT (name,id) VALUES ('" + name + "','" + id + "');");
现在一些进取的小丑决定尝试使用此名称以获取尺寸:
Alicia','1'); DROP TABLE STUDENT; EXEC 'rm -rf /*'; --
在这种情况下,他们从字面上键入所有爵士乐(或更可能是将其粘贴到)上的Web表单,其内容为:“名称:”。加上引号,破折号和分号,所有这些。
他们单击“表单提交”,稍后表被删除,并且幸运的是,整个服务器磁盘都被清除了。
您无法通过以下方式解决此问题:嗯,没有问题,我只会查找引号并将其删除;您不知道数据库做什么,也不允许引用等,也许该数据库允许反引号。也许这允许Unicode转义。唯一知道的一方是JDBC驱动程序和数据库,您可以使用PreparedStatement
来解锁它们逃脱事物的能力。