簡體   English   中英

准備好的語句如何在 Java 中工作?

[英]How does prepared statement work in Java?

准備好的陳述有什么用。 當您使用不同的值多次執行相同的 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 萬條記錄插入到一個表中,有僅僅創建一個准備好的語句並使用不同的設置值重新運行它一百萬次更有效的方法。 您將關閉所有約束檢查和索引更新,和/或COPY或一些專門為此設計的其他批量插入過程,然后重新打開檢查和索引。

不,使用 PreparedStatement 而不是 Statement 的 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解鎖它們逃避事物的能力。

TL;DR:只要您的查詢中有“參數”,就必須使用 PreparedStatement。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM